diff options
71 files changed, 2155 insertions, 545 deletions
diff --git a/libc/ChangeLog b/libc/ChangeLog index 7169ecd8f..d799ba831 100644 --- a/libc/ChangeLog +++ b/libc/ChangeLog @@ -1,7 +1,95 @@ +2007-05-21 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/x86_64/cacheinfo.c (init_cacheinfo): Pass correct value + as second parameter to handle_intel. + + * nscd/aicache.c (addhstaiX): If reported TTL is zero don't cache + the entry. + + * sysdeps/unix/sysv/linux/x86_64/sysconf.c: Move cache information + handling to ... + * sysdeps/x86_64/cacheinfo.c: ... here. New file. + * sysdeps/x86_64/Makefile [subdir=string] (sysdep_routines): Add + cacheinfo. + * sysdeps/x86_64/memcpy.S: Complete rewrite. + * sysdeps/x86_64/mempcpy.S: Adjust appropriately. + Patch by Evandro Menezes <evandro.menezes@amd.com>. + + * sysdeps/unix/sysv/linux/i386/epoll_pwait.S: New file. + +2007-05-21 Jakub Jelinek <jakub@redhat.com> + + [BZ #4525] + * sysdeps/unix/sysv/linux/Makefile (sysdep_routines): Add epoll_pwait. + * sysdeps/unix/sysv/linux/epoll_pwait.c: New file. + * sysdeps/unix/sysv/linux/syscalls.list (epoll_pwait): Remove. + + * sysdeps/unix/sysv/linux/x86_64/sys/epoll.h (epoll_pwait): Declare. + + [BZ #4514] + * stdio-common/vfprintf.c (vfprintf): Don't shadow workstart variable, + reinitialize workend at the start of each do_positional format spec + loop, free workstart before do_positional loops. + (printf_unknown): Fix size of work_buffer. + * stdio-common/tst-sprintf.c (main): Add 3 new testcases. + + * malloc/hooks.c (MALLOC_STATE_VERSION): Bump. + (public_sET_STATe): If ms->version < 3, put all chunks into + unsorted chunks and clear {fd,bk}_nextsize fields of largebin + chunks. + + * malloc/malloc.c [MALLOC_DEBUG]: Revert 2007-05-13 changes. + * malloc/hooks.c: Likewise. + * malloc/arena.c: Likewise. + * malloc/malloc.c (do_check_malloc_state): Don't assert + n_mmaps is not greater than n_mmaps_max. This removes the need + for the previous change. + + * malloc/Makefile (CFLAGS-malloc.c): Revert accidental + 2007-05-07 commit. + +2007-05-19 Ulrich Drepper <drepper@redhat.com> + + * sysdeps/unix/sysv/linux/kernel-features.h (__ASSUME_PRIVATE_FUTEX): + Define for kernel >= 2.6.22. + +2007-05-18 Ulrich Drepper <drepper@redhat.com> + + * elf/dl-close.c (_dl_close_worker): When removing object from + global scope, wait for all lookups to finish afterwards. + * elf/dl-open.c (add_to_global): When global scope array must + grow, allocate a new one and free old array only after all + lookups finish. + * elf/dl-runtime.c (_dl_fixup): Protect using global scope. + (_dl_lookup_symbol_x): Likewise. + * elf/dl-support.c: Define _dl_wait_lookup_done. + * sysdeps/generic/ldsodefs.h (struct rtld_global): Add + _dl_wait_lookup_done. + + * malloc/malloc.c (do_check_chunk): Correct check for mmaped block + not overlapping with arena. + + * malloc/mcheck.c (reallochook): If size==0, free the block. + + * rt/tst-shm.c: Use fstat64 instead of fstat. + + * sysdeps/unix/sysv/linux/i386/sync_file_range.S: Fix case where + __NR_sync_file_range is not defined. + +2007-05-17 Ulrich Drepper <drepper@redhat.com> + + Dummy files to prevent stub versions from being used. + * sysdeps/x86_64/fpu/k_cosl.c: New file. + * sysdeps/x86_64/fpu/k_rem_pio2l.c: New file. + * sysdeps/x86_64/fpu/k_sinl.c: New file. + * sysdeps/x86_64/fpu/k_tanl.c: New file. + + * version.h (VERSION): Set to 2.6.90. + 2007-05-14 Ulrich Drepper <drepper@redhat.com> - * version.h (VERSION): Define to 6. - * include/features.h (__GLIBC_MINOR__): Likewise. + * version.h (VERSION): Define to 2.6. + * include/features.h (__GLIBC_MINOR__): Define to 6. * malloc/malloc.c: Use all small bin slots on 64-bit archs. diff --git a/libc/elf/dl-close.c b/libc/elf/dl-close.c index e0fe26ad0..8e5c9fc03 100644 --- a/libc/elf/dl-close.c +++ b/libc/elf/dl-close.c @@ -31,6 +31,7 @@ #include <sys/types.h> #include <sys/mman.h> #include <sysdep-cancel.h> +#include <tls.h> /* Type of the constructor functions. */ @@ -487,6 +488,9 @@ _dl_close_worker (struct link_map *map) ns_msl->r_list[cnt - 1] = ns_msl->r_list[cnt]; --ns_msl->r_nlist; + + if (!RTLD_SINGLE_THREAD_P) + THREAD_GSCOPE_WAIT (); } /* Remove the object from the dtv slotinfo array if it uses TLS. */ diff --git a/libc/elf/dl-open.c b/libc/elf/dl-open.c index 583878781..a043cf61b 100644 --- a/libc/elf/dl-open.c +++ b/libc/elf/dl-open.c @@ -32,6 +32,7 @@ #include <bp-sym.h> #include <caller.h> #include <sysdep-cancel.h> +#include <tls.h> #include <dl-dst.h> @@ -125,15 +126,25 @@ add_to_global (struct link_map *new) { /* We have to extend the existing array of link maps in the main map. */ + struct link_map **old_global + = GL(dl_ns)[new->l_ns]._ns_main_searchlist->r_list; + size_t new_nalloc = ((ns->_ns_global_scope_alloc + to_add) * 2); + new_global = (struct link_map **) - realloc (ns->_ns_main_searchlist->r_list, - ((ns->_ns_global_scope_alloc + to_add + 8) - * sizeof (struct link_map *))); + malloc (new_nalloc * sizeof (struct link_map *)); if (new_global == NULL) goto nomem; - ns->_ns_global_scope_alloc += to_add + 8; + memcpy (new_global, old_global, + ns->_ns_global_scope_alloc * sizeof (struct link_map *)); + + ns->_ns_global_scope_alloc = new_nalloc; ns->_ns_main_searchlist->r_list = new_global; + + if (!RTLD_SINGLE_THREAD_P) + THREAD_GSCOPE_WAIT (); + + free (old_global); } /* Now add the new entries. */ diff --git a/libc/elf/dl-runtime.c b/libc/elf/dl-runtime.c index 9ecf62b43..6add5e4ff 100644 --- a/libc/elf/dl-runtime.c +++ b/libc/elf/dl-runtime.c @@ -26,6 +26,8 @@ #include <ldsodefs.h> #include <sysdep-cancel.h> #include "dynamic-link.h" +#include <tls.h> + #if (!defined ELF_MACHINE_NO_RELA && !defined ELF_MACHINE_PLT_REL) \ || ELF_MACHINE_NO_REL @@ -97,10 +99,15 @@ _dl_fixup ( not necessary for objects which cannot be unloaded or when we are not using any threads (yet). */ int flags = DL_LOOKUP_ADD_DEPENDENCY; - if (l->l_type == lt_loaded && !RTLD_SINGLE_THREAD_P) + if (!RTLD_SINGLE_THREAD_P) { - __rtld_mrlock_lock (l->l_scope_lock); - flags |= DL_LOOKUP_SCOPE_LOCK; + THREAD_GSCOPE_SET_FLAG (); + + if (l->l_type == lt_loaded) + { + __rtld_mrlock_lock (l->l_scope_lock); + flags |= DL_LOOKUP_SCOPE_LOCK; + } } result = _dl_lookup_symbol_x (strtab + sym->st_name, l, &sym, l->l_scope, @@ -109,6 +116,10 @@ _dl_fixup ( if ((flags & DL_LOOKUP_SCOPE_LOCK) != 0) __rtld_mrlock_unlock (l->l_scope_lock); + /* We are done with the global scope. */ + if (!RTLD_SINGLE_THREAD_P) + THREAD_GSCOPE_RESET_FLAG (); + /* Currently result contains the base load address (or link map) of the object that defines sym. Now add in the symbol offset. */ @@ -191,10 +202,15 @@ _dl_profile_fixup ( not necessary for objects which cannot be unloaded or when we are not using any threads (yet). */ int flags = DL_LOOKUP_ADD_DEPENDENCY; - if (l->l_type == lt_loaded && !RTLD_SINGLE_THREAD_P) + if (!RTLD_SINGLE_THREAD_P) { - __rtld_mrlock_lock (l->l_scope_lock); - flags |= DL_LOOKUP_SCOPE_LOCK; + THREAD_GSCOPE_SET_FLAG (); + + if (l->l_type == lt_loaded) + { + __rtld_mrlock_lock (l->l_scope_lock); + flags |= DL_LOOKUP_SCOPE_LOCK; + } } result = _dl_lookup_symbol_x (strtab + refsym->st_name, l, @@ -204,6 +220,10 @@ _dl_profile_fixup ( if ((flags & DL_LOOKUP_SCOPE_LOCK) != 0) __rtld_mrlock_unlock (l->l_scope_lock); + /* We are done with the global scope. */ + if (!RTLD_SINGLE_THREAD_P) + THREAD_GSCOPE_RESET_FLAG (); + /* Currently result contains the base load address (or link map) of the object that defines sym. Now add in the symbol offset. */ diff --git a/libc/elf/dl-support.c b/libc/elf/dl-support.c index c7479dc63..cecb603ae 100644 --- a/libc/elf/dl-support.c +++ b/libc/elf/dl-support.c @@ -1,5 +1,5 @@ /* Support for dynamic linking code in static libc. - Copyright (C) 1996-2005, 2006 Free Software Foundation, Inc. + Copyright (C) 1996-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 @@ -132,6 +132,9 @@ int (*_dl_make_stack_executable_hook) (void **) internal_function = _dl_make_stack_executable; +/* Function in libpthread to wait for termination of lookups. */ +void (*_dl_wait_lookup_done) (void); + #ifdef NEED_DL_SYSINFO /* Needed for improved syscall handling on at least x86/Linux. */ uintptr_t _dl_sysinfo = DL_SYSINFO_DEFAULT; diff --git a/libc/malloc/Makefile b/libc/malloc/Makefile index 4b49bd184..6df857d4c 100644 --- a/libc/malloc/Makefile +++ b/libc/malloc/Makefile @@ -104,7 +104,6 @@ $(objpfx)memusagestat: $(memusagestat-modules:%=$(objpfx)%.o) include ../Rules CFLAGS-mcheck-init.c = $(PIC-ccflag) -CFLAGS-malloc.c += -DMALLOC_DEBUG $(objpfx)libmcheck.a: $(objpfx)mcheck-init.o -rm -f $@ diff --git a/libc/malloc/arena.c b/libc/malloc/arena.c index 9e3ff4734..ce6433556 100644 --- a/libc/malloc/arena.c +++ b/libc/malloc/arena.c @@ -370,9 +370,6 @@ ptmalloc_init_minimal (void) mp_.top_pad = DEFAULT_TOP_PAD; #endif mp_.n_mmaps_max = DEFAULT_MMAP_MAX; -#if MALLOC_DEBUG - mp_.n_mmaps_cmax = DEFAULT_MMAP_MAX; -#endif mp_.mmap_threshold = DEFAULT_MMAP_THRESHOLD; mp_.trim_threshold = DEFAULT_TRIM_THRESHOLD; mp_.pagesize = malloc_getpagesize; diff --git a/libc/malloc/hooks.c b/libc/malloc/hooks.c index cde3e18cb..1e01b73af 100644 --- a/libc/malloc/hooks.c +++ b/libc/malloc/hooks.c @@ -496,7 +496,7 @@ free_starter(mem, caller) Void_t* mem; const Void_t *caller; then the hooks are reset to 0. */ #define MALLOC_STATE_MAGIC 0x444c4541l -#define MALLOC_STATE_VERSION (0*0x100l + 2l) /* major*0x100 + minor */ +#define MALLOC_STATE_VERSION (0*0x100l + 3l) /* major*0x100 + minor */ struct malloc_save_state { long magic; @@ -507,9 +507,6 @@ struct malloc_save_state { unsigned long trim_threshold; unsigned long top_pad; unsigned int n_mmaps_max; -#if MALLOC_DEBUG - unsigned int n_mmaps_cmax; -#endif unsigned long mmap_threshold; int check_action; unsigned long max_sbrked_mem; @@ -553,9 +550,6 @@ public_gET_STATe(void) ms->trim_threshold = mp_.trim_threshold; ms->top_pad = mp_.top_pad; ms->n_mmaps_max = mp_.n_mmaps_max; -#if MALLOC_DEBUG - ms->n_mmaps_cmax = mp_.n_mmaps_cmax; -#endif ms->mmap_threshold = mp_.mmap_threshold; ms->check_action = check_action; ms->max_sbrked_mem = main_arena.max_system_mem; @@ -601,8 +595,9 @@ public_sET_STATe(Void_t* msptr) assert(ms->av[2*i+3] == 0); first(b) = last(b) = b; } else { - if(i<NSMALLBINS || (largebin_index(chunksize(ms->av[2*i+2]))==i && - largebin_index(chunksize(ms->av[2*i+3]))==i)) { + if(ms->version >= 3 && + (i<NSMALLBINS || (largebin_index(chunksize(ms->av[2*i+2]))==i && + largebin_index(chunksize(ms->av[2*i+3]))==i))) { first(b) = ms->av[2*i+2]; last(b) = ms->av[2*i+3]; /* Make sure the links to the bins within the heap are correct. */ @@ -622,14 +617,22 @@ public_sET_STATe(Void_t* msptr) } } } + if (ms->version < 3) { + /* Clear fd_nextsize and bk_nextsize fields. */ + b = unsorted_chunks(&main_arena)->fd; + while (b != unsorted_chunks(&main_arena)) { + if (!in_smallbin_range(chunksize(b))) { + b->fd_nextsize = NULL; + b->bk_nextsize = NULL; + } + b = b->fd; + } + } mp_.sbrk_base = ms->sbrk_base; main_arena.system_mem = ms->sbrked_mem_bytes; mp_.trim_threshold = ms->trim_threshold; mp_.top_pad = ms->top_pad; mp_.n_mmaps_max = ms->n_mmaps_max; -#if MALLOC_DEBUG - mp_.n_mmaps_cmax = ms->n_mmaps_cmax; -#endif mp_.mmap_threshold = ms->mmap_threshold; check_action = ms->check_action; main_arena.max_system_mem = ms->max_sbrked_mem; diff --git a/libc/malloc/malloc.c b/libc/malloc/malloc.c index e061db94d..0755fd8f8 100644 --- a/libc/malloc/malloc.c +++ b/libc/malloc/malloc.c @@ -2358,9 +2358,6 @@ struct malloc_par { /* Memory map support */ int n_mmaps; int n_mmaps_max; -#if MALLOC_DEBUG - int n_mmaps_cmax; -#endif int max_n_mmaps; /* the mmap_threshold is dynamic, until the user sets it manually, at which point we need to disable any @@ -2572,7 +2569,7 @@ static void do_check_chunk(av, p) mstate av; mchunkptr p; #if HAVE_MMAP /* address is outside main heap */ if (contiguous(av) && av->top != initial_top(av)) { - assert(((char*)p) < min_address || ((char*)p) > max_address); + assert(((char*)p) < min_address || ((char*)p) >= max_address); } /* chunk is page-aligned */ assert(((p->prev_size + sz) & (mp_.pagesize-1)) == 0); @@ -2876,8 +2873,6 @@ static void do_check_malloc_state(mstate av) assert(total <= (unsigned long)(mp_.max_total_mem)); assert(mp_.n_mmaps >= 0); #endif - assert(mp_.n_mmaps <= mp_.n_mmaps_cmax); - assert(mp_.n_mmaps_max <= mp_.n_mmaps_cmax); assert(mp_.n_mmaps <= mp_.max_n_mmaps); assert((unsigned long)(av->system_mem) <= @@ -3475,13 +3470,6 @@ munmap_chunk(p) mchunkptr p; } mp_.n_mmaps--; -#if MALLOC_DEBUG - if (mp_.n_mmaps_cmax > mp_.n_mmaps_max) - { - assert (mp_.n_mmaps_cmax == mp_.n_mmaps + 1); - mp_.n_mmaps_cmax = mp_.n_mmaps; - } -#endif mp_.mmapped_mem -= total_size; int ret __attribute__ ((unused)) = munmap((char *)block, total_size); @@ -5397,9 +5385,6 @@ mstate av; size_t n_elements; size_t* sizes; int opts; Void_t* chunks[]; mp_.n_mmaps_max = 0; mem = _int_malloc(av, size); mp_.n_mmaps_max = mmx; /* reset mmap */ -#if MALLOC_DEBUG - mp_.n_mmaps_cmax = mmx; -#endif if (mem == 0) return 0; @@ -5725,17 +5710,8 @@ int mALLOPt(param_number, value) int param_number; int value; res = 0; else #endif - { -#if MALLOC_DEBUG - if (mp_.n_mmaps <= value) - mp_.n_mmaps_cmax = value; - else - mp_.n_mmaps_cmax = mp_.n_mmaps; -#endif - - mp_.n_mmaps_max = value; - mp_.no_dyn_threshold = 1; - } + mp_.n_mmaps_max = value; + mp_.no_dyn_threshold = 1; break; case M_CHECK_ACTION: diff --git a/libc/malloc/mcheck.c b/libc/malloc/mcheck.c index 02379d219..524acc755 100644 --- a/libc/malloc/mcheck.c +++ b/libc/malloc/mcheck.c @@ -1,5 +1,5 @@ /* Standard debugging hooks for `malloc'. - Copyright (C) 1990-1997,99,2000,01,02 Free Software Foundation, Inc. + Copyright (C) 1990-1997,1999,2000-2002,2007 Free Software Foundation, Inc. This file is part of the GNU C Library. Written May 1989 by Mike Haertel. @@ -264,6 +264,12 @@ memalignhook (__malloc_size_t alignment, __malloc_size_t size, static __ptr_t reallochook (__ptr_t ptr, __malloc_size_t size, const __ptr_t caller) { + if (size == 0) + { + freehook (ptr, caller); + return NULL; + } + struct hdr *hdr; __malloc_size_t osize; diff --git a/libc/nptl/ChangeLog b/libc/nptl/ChangeLog index 47d36966c..8198f00e0 100644 --- a/libc/nptl/ChangeLog +++ b/libc/nptl/ChangeLog @@ -1,3 +1,72 @@ +2007-05-23 Ulrich Drepper <drepper@redhat.com> + + * 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 <drepper@redhat.com> + + * 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 <jakub@redhat.com> + + * tst-robust9.c (do_test): Don't fail if ENABLE_PI and + pthread_mutex_init failed with ENOTSUP. + +2007-05-19 Ulrich Drepper <drepper@redhat.com> + + * 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 <drepper@redhat.com> + + [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 <anemo@mba.ocn.ne.jp>. + + * 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 <drepper@redhat.com> * sysdeps/unix/sysv/linux/x86_64/sem_wait.S: Remove unnecessary diff --git a/libc/nptl/Makefile b/libc/nptl/Makefile index a7b41cc78..fd9312ed6 100644 --- a/libc/nptl/Makefile +++ b/libc/nptl/Makefile @@ -1,4 +1,4 @@ -# Copyright (C) 2002,2003,2004,2005,2006 Free Software Foundation, Inc. +# 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 @@ -216,9 +216,9 @@ tests = tst-typesizes \ tst-cond14 tst-cond15 tst-cond16 tst-cond17 tst-cond18 tst-cond19 \ tst-cond20 tst-cond21 tst-cond22 \ tst-robust1 tst-robust2 tst-robust3 tst-robust4 tst-robust5 \ - tst-robust6 tst-robust7 tst-robust8 \ - tst-robustpi1 tst-robustpi2 tst-robustpi3 tst-robustpi4 \ - tst-robustpi5 tst-robustpi6 tst-robustpi7 tst-robustpi8 \ + tst-robust6 tst-robust7 tst-robust8 tst-robust9 \ + tst-robustpi1 tst-robustpi2 tst-robustpi3 tst-robustpi4 tst-robustpi5 \ + tst-robustpi6 tst-robustpi7 tst-robustpi8 tst-robustpi9 \ 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 \ diff --git a/libc/nptl/allocatestack.c b/libc/nptl/allocatestack.c index 6b6064204..5dac000d6 100644 --- a/libc/nptl/allocatestack.c +++ b/libc/nptl/allocatestack.c @@ -376,6 +376,12 @@ allocate_stack (const struct pthread_attr *attr, struct pthread **pdp, __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; @@ -510,6 +516,12 @@ allocate_stack (const struct pthread_attr *attr, struct pthread **pdp, __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; @@ -996,3 +1008,60 @@ __pthread_init_static_tls (struct link_map *map) lll_unlock (stack_cache_lock); } + + +void +attribute_hidden +__wait_lookup_done (void) +{ + lll_lock (stack_cache_lock); + + 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); + 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); + while (*gscope_flagp == THREAD_GSCOPE_FLAG_WAIT); + } + + lll_unlock (stack_cache_lock); +} diff --git a/libc/nptl/init.c b/libc/nptl/init.c index dddc975a5..ff81087d0 100644 --- a/libc/nptl/init.c +++ b/libc/nptl/init.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. +/* 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 <drepper@redhat.com>, 2002. @@ -35,27 +35,6 @@ #include <lowlevellock.h> -#ifndef __NR_set_tid_address -/* XXX For the time being... Once we can rely on the kernel headers - having the definition remove these lines. */ -#if defined __s390__ -# define __NR_set_tid_address 252 -#elif defined __ia64__ -# define __NR_set_tid_address 1233 -#elif defined __i386__ -# define __NR_set_tid_address 258 -#elif defined __x86_64__ -# define __NR_set_tid_address 218 -#elif defined __powerpc__ -# define __NR_set_tid_address 232 -#elif defined __sparc__ -# define __NR_set_tid_address 166 -#else -# error "define __NR_set_tid_address" -#endif -#endif - - /* Size and alignment of static TLS block. */ size_t __static_tls_size; size_t __static_tls_align_m1; @@ -297,6 +276,18 @@ __pthread_initialize_minimal_internal (void) #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; + res = INTERNAL_SYSCALL (futex, err, 3, &word, + FUTEX_WAKE | FUTEX_PRIVATE_FLAG, 1); + if (!INTERNAL_SYSCALL_ERROR_P (res, err)) + THREAD_SETMEM (pd, header.private_futex, FUTEX_PRIVATE_FLAG); + } +#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. */ @@ -386,6 +377,8 @@ __pthread_initialize_minimal_internal (void) GL(dl_init_static_tls) = &__pthread_init_static_tls; + GL(dl_wait_lookup_done) = &__wait_lookup_done; + /* Register the fork generation counter with the libc. */ #ifndef TLS_MULTIPLE_THREADS_IN_TCB __libc_multiple_threads_ptr = diff --git a/libc/nptl/pthreadP.h b/libc/nptl/pthreadP.h index f9634ab0f..21ce6fe0b 100644 --- a/libc/nptl/pthreadP.h +++ b/libc/nptl/pthreadP.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. +/* 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 <drepper@redhat.com>, 2002. @@ -545,6 +545,8 @@ extern int __nptl_setxid (struct xid_command *cmdp) attribute_hidden; extern void __free_stack_cache (void) attribute_hidden; +extern void __wait_lookup_done (void) attribute_hidden; + #ifdef SHARED # define PTHREAD_STATIC_FN_REQUIRE(name) #else diff --git a/libc/nptl/pthread_mutex_lock.c b/libc/nptl/pthread_mutex_lock.c index 52cc47f4c..1c3ee4fe2 100644 --- a/libc/nptl/pthread_mutex_lock.c +++ b/libc/nptl/pthread_mutex_lock.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. +/* 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 <drepper@redhat.com>, 2002. @@ -127,6 +127,8 @@ __pthread_mutex_lock (mutex) int newval = id; #ifdef NO_INCR newval |= FUTEX_WAITERS; +#else + newval |= (oldval & FUTEX_WAITERS); #endif newval diff --git a/libc/nptl/pthread_mutex_timedlock.c b/libc/nptl/pthread_mutex_timedlock.c index c8e6b8507..8fd681c6e 100644 --- a/libc/nptl/pthread_mutex_timedlock.c +++ b/libc/nptl/pthread_mutex_timedlock.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. +/* 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 <drepper@redhat.com>, 2002. @@ -119,9 +119,11 @@ pthread_mutex_timedlock (mutex, abstime) if ((oldval & FUTEX_OWNER_DIED) != 0) { /* The previous owner died. Try locking the mutex. */ - int newval + int newval = id | (oldval & FUTEX_WAITERS); + + newval = atomic_compare_and_exchange_val_acq (&mutex->__data.__lock, - id, oldval); + newval, oldval); if (newval != oldval) { oldval = newval; diff --git a/libc/nptl/pthread_mutex_trylock.c b/libc/nptl/pthread_mutex_trylock.c index 4990ecd71..9db904c60 100644 --- a/libc/nptl/pthread_mutex_trylock.c +++ b/libc/nptl/pthread_mutex_trylock.c @@ -84,9 +84,11 @@ __pthread_mutex_trylock (mutex) if ((oldval & FUTEX_OWNER_DIED) != 0) { /* The previous owner died. Try locking the mutex. */ - int newval + int newval = id | (oldval & FUTEX_WAITERS); + + newval = atomic_compare_and_exchange_val_acq (&mutex->__data.__lock, - id, oldval); + newval, oldval); if (newval != oldval) { diff --git a/libc/nptl/sysdeps/i386/tcb-offsets.sym b/libc/nptl/sysdeps/i386/tcb-offsets.sym index 7c8d9a5ca..69f9deb36 100644 --- a/libc/nptl/sysdeps/i386/tcb-offsets.sym +++ b/libc/nptl/sysdeps/i386/tcb-offsets.sym @@ -12,3 +12,6 @@ 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/libc/nptl/sysdeps/i386/tls.h b/libc/nptl/sysdeps/i386/tls.h index d5b3797e6..3bdf0f2b0 100644 --- a/libc/nptl/sysdeps/i386/tls.h +++ b/libc/nptl/sysdeps/i386/tls.h @@ -1,5 +1,5 @@ /* Definition for thread-local data handling. nptl/i386 version. - Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. + 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 @@ -27,6 +27,8 @@ # include <stdint.h> # include <stdlib.h> # include <list.h> +# include <sysdep.h> +# include <kernel-features.h> /* Type for the dtv. */ @@ -51,6 +53,10 @@ typedef struct uintptr_t sysinfo; uintptr_t stack_guard; uintptr_t pointer_guard; + int gscope_flag; +#ifndef __ASSUME_PRIVATE_FUTEX + int private_futex; +#endif } tcbhead_t; # define TLS_MULTIPLE_THREADS_IN_TCB 1 @@ -431,6 +437,35 @@ union user_desc_init = 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 ("xchg %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); \ + } \ + while (0) +#define THREAD_GSCOPE_SET_FLAG() \ + THREAD_SETMEM (THREAD_SELF, header.gscope_flag, THREAD_GSCOPE_FLAG_USED) +#ifdef PTR_DEMANGLE +# define THREAD_GSCOPE_WAIT() \ + do { void (*ptr) (void) = GL(dl_wait_lookup_done); \ + PTR_DEMANGLE (ptr); \ + ptr (); \ + } while (0) +#else +# define THREAD_GSCOPE_WAIT() \ + GL(dl_wait_lookup_done) () +#endif + + #endif /* __ASSEMBLER__ */ #endif /* tls.h */ diff --git a/libc/nptl/sysdeps/pthread/pthread-functions.h b/libc/nptl/sysdeps/pthread/pthread-functions.h index a13b93703..0c404fcbb 100644 --- a/libc/nptl/sysdeps/pthread/pthread-functions.h +++ b/libc/nptl/sysdeps/pthread/pthread-functions.h @@ -97,7 +97,6 @@ struct pthread_functions void (*ptr__nptl_deallocate_tsd) (void); int (*ptr__nptl_setxid) (struct xid_command *); void (*ptr_freeres) (void); - void (*ptr_wait_lookup_done) (int); }; /* Variable in libc.so. */ diff --git a/libc/nptl/sysdeps/unix/sysv/linux/i386/i486/libc-lowlevellock.S b/libc/nptl/sysdeps/unix/sysv/linux/i386/i486/libc-lowlevellock.S index 88885b735..f24671148 100644 --- a/libc/nptl/sysdeps/unix/sysv/linux/i386/i486/libc-lowlevellock.S +++ b/libc/nptl/sysdeps/unix/sysv/linux/i386/i486/libc-lowlevellock.S @@ -1,4 +1,4 @@ -/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. +/* Copyright (C) 2002, 2003, 2007 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. @@ -17,6 +17,8 @@ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ +#include <kernel-features.h> + /* In libc.so we do not unconditionally use the lock prefix. Only if the application is using threads. */ #ifndef UP @@ -27,4 +29,17 @@ 0: #endif +/* All locks in libc are private. Use the kernel feature if possible. */ +#define FUTEX_PRIVATE_FLAG 128 +#ifdef __ASSUME_PRIVATE_FUTEX +# define FUTEX_WAIT (0 | FUTEX_PRIVATE_FLAG) +# define FUTEX_WAKE (1 | FUTEX_PRIVATE_FLAG) +#else +# define LOAD_FUTEX_WAIT(reg) \ + movl %gs:PRIVATE_FUTEX, reg +# define LOAD_FUTEX_WAKE(reg) \ + movl %gs:PRIVATE_FUTEX, reg ; \ + orl $FUTEX_WAKE, reg +#endif + #include "lowlevellock.S" diff --git a/libc/nptl/sysdeps/unix/sysv/linux/i386/i486/lowlevellock.S b/libc/nptl/sysdeps/unix/sysv/linux/i386/i486/lowlevellock.S index e2da5b04c..1c47b37bb 100644 --- a/libc/nptl/sysdeps/unix/sysv/linux/i386/i486/lowlevellock.S +++ b/libc/nptl/sysdeps/unix/sysv/linux/i386/i486/lowlevellock.S @@ -1,4 +1,4 @@ -/* Copyright (C) 2002, 2003, 2004, 2006 Free Software Foundation, Inc. +/* Copyright (C) 2002, 2003, 2004, 2006, 2007 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. @@ -32,8 +32,22 @@ #define SYS_gettimeofday __NR_gettimeofday #define SYS_futex 240 -#define FUTEX_WAIT 0 -#define FUTEX_WAKE 1 +#ifndef FUTEX_WAIT +# define FUTEX_WAIT 0 +# define FUTEX_WAKE 1 +#endif + +#ifndef LOAD_FUTEX_WAIT +# if FUTEX_WAIT == 0 +# define LOAD_FUTEX_WAIT(reg) \ + xorl reg, reg +# else +# define LOAD_FUTEX_WAIT(reg) \ + movl $FUTEX_WAIT, reg +# endif +# define LOAD_FUTEX_WAKE(reg) \ + movl $FUTEX_WAKE, reg +#endif .globl __lll_mutex_lock_wait @@ -55,7 +69,7 @@ __lll_mutex_lock_wait: movl $2, %edx movl %ecx, %ebx xorl %esi, %esi /* No timeout. */ - xorl %ecx, %ecx /* movl $FUTEX_WAIT, %ecx */ + LOAD_FUTEX_WAIT (%ecx) cmpl %edx, %eax /* NB: %edx == 2 */ jne 2f @@ -151,7 +165,7 @@ __lll_mutex_timedlock_wait: /* Futex call. */ movl %esp, %esi - xorl %ecx, %ecx /* movl $FUTEX_WAIT, %ecx */ + LOAD_FUTEX_WAIT (%ecx) movl $SYS_futex, %eax ENTER_KERNEL movl %eax, %ecx @@ -252,7 +266,7 @@ __lll_mutex_unlock_wake: movl %eax, %ebx movl $0, (%eax) - movl $FUTEX_WAKE, %ecx + LOAD_FUTEX_WAKE (%ecx) movl $1, %edx /* Wake one thread. */ movl $SYS_futex, %eax ENTER_KERNEL @@ -314,6 +328,8 @@ __lll_timedwait_tid: 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 diff --git a/libc/nptl/sysdeps/unix/sysv/linux/i386/lowlevellock.h b/libc/nptl/sysdeps/unix/sysv/linux/i386/lowlevellock.h index 21de09fe9..b89d5dd7d 100644 --- a/libc/nptl/sysdeps/unix/sysv/linux/i386/lowlevellock.h +++ b/libc/nptl/sysdeps/unix/sysv/linux/i386/lowlevellock.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2002, 2003, 2004, 2006 Free Software Foundation, Inc. +/* Copyright (C) 2002, 2003, 2004, 2006, 2007 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. @@ -38,6 +38,7 @@ #define FUTEX_LOCK_PI 6 #define FUTEX_UNLOCK_PI 7 #define FUTEX_TRYLOCK_PI 8 +#define FUTEX_PRIVATE_FLAG 128 /* Initializer for compatibility lock. */ diff --git a/libc/nptl/sysdeps/unix/sysv/linux/i386/pthread_once.S b/libc/nptl/sysdeps/unix/sysv/linux/i386/pthread_once.S index 312933c5e..8ff0dad27 100644 --- a/libc/nptl/sysdeps/unix/sysv/linux/i386/pthread_once.S +++ b/libc/nptl/sysdeps/unix/sysv/linux/i386/pthread_once.S @@ -1,4 +1,4 @@ -/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. +/* Copyright (C) 2002, 2003, 2007 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. @@ -19,6 +19,8 @@ #include <unwindbuf.h> #include <sysdep.h> +#include <kernel-features.h> + #ifndef UP # define LOCK lock @@ -26,8 +28,10 @@ # define LOCK #endif -#define SYS_futex 240 -#define FUTEX_WAKE 1 +#define SYS_futex 240 +#define FUTEX_WAIT 0 +#define FUTEX_WAKE 1 +#define FUTEX_PRIVATE_FLAG 128 .comm __fork_generation, 4, 4 @@ -90,7 +94,16 @@ __pthread_once: jnz 3f /* Different for generation -> run initializer. */ /* Somebody else got here first. Wait. */ - movl %esi, %ecx /* movl $FUTEX_WAIT, %ecx */ +#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 @@ -131,7 +144,12 @@ __pthread_once: /* 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 @@ -152,7 +170,12 @@ __pthread_once: 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 diff --git a/libc/nptl/sysdeps/unix/sysv/linux/libc_pthread_init.c b/libc/nptl/sysdeps/unix/sysv/linux/libc_pthread_init.c index 92a188a2f..4b614bd1a 100644 --- a/libc/nptl/sysdeps/unix/sysv/linux/libc_pthread_init.c +++ b/libc/nptl/sysdeps/unix/sysv/linux/libc_pthread_init.c @@ -26,6 +26,7 @@ #include <pthreadP.h> #include <bits/libc-lock.h> #include <sysdep.h> +#include <ldsodefs.h> #ifdef TLS_MULTIPLE_THREADS_IN_TCB diff --git a/libc/nptl/sysdeps/unix/sysv/linux/sem_wait.c b/libc/nptl/sysdeps/unix/sysv/linux/sem_wait.c index e6733e88a..d1aa97571 100644 --- a/libc/nptl/sysdeps/unix/sysv/linux/sem_wait.c +++ b/libc/nptl/sysdeps/unix/sysv/linux/sem_wait.c @@ -1,5 +1,5 @@ /* sem_wait -- wait on a semaphore. Generic futex-using version. - Copyright (C) 2003 Free Software Foundation, Inc. + Copyright (C) 2003, 2007 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Paul Mackerras <paulus@au.ibm.com>, 2003. @@ -31,9 +31,6 @@ int __new_sem_wait (sem_t *sem) { - /* First check for cancellation. */ - CANCELLATION_P (THREAD_SELF); - int *futex = (int *) sem; int err; diff --git a/libc/nptl/sysdeps/unix/sysv/linux/x86_64/libc-lowlevellock.S b/libc/nptl/sysdeps/unix/sysv/linux/x86_64/libc-lowlevellock.S index 3621efa4f..21bf58cbb 100644 --- a/libc/nptl/sysdeps/unix/sysv/linux/x86_64/libc-lowlevellock.S +++ b/libc/nptl/sysdeps/unix/sysv/linux/x86_64/libc-lowlevellock.S @@ -1,4 +1,4 @@ -/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. +/* Copyright (C) 2002, 2003, 2007 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. @@ -17,6 +17,8 @@ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ +#include <kernel-features.h> + /* In libc.so we do not unconditionally use the lock prefix. Only if the application is using threads. */ #ifndef UP @@ -27,4 +29,17 @@ 0: #endif +/* All locks in libc are private. Use the kernel feature if possible. */ +#define FUTEX_PRIVATE_FLAG 128 +#ifdef __ASSUME_PRIVATE_FUTEX +# define FUTEX_WAIT (0 | FUTEX_PRIVATE_FLAG) +# define FUTEX_WAKE (1 | FUTEX_PRIVATE_FLAG) +#else +# define LOAD_FUTEX_WAIT(reg) \ + movl %fs:PRIVATE_FUTEX, reg +# define LOAD_FUTEX_WAKE(reg) \ + movl %fs:PRIVATE_FUTEX, reg ; \ + orl $FUTEX_WAKE, reg +#endif + #include "lowlevellock.S" diff --git a/libc/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.S b/libc/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.S index 6724ded76..de70b1852 100644 --- a/libc/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.S +++ b/libc/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.S @@ -31,8 +31,23 @@ #endif #define SYS_futex 202 -#define FUTEX_WAIT 0 -#define FUTEX_WAKE 1 +#ifndef FUTEX_WAIT +# define FUTEX_WAIT 0 +# define FUTEX_WAKE 1 +#endif + +#ifndef LOAD_FUTEX_WAIT +# if FUTEX_WAIT == 0 +# define LOAD_FUTEX_WAIT(reg) \ + xorl reg, reg +# else +# define LOAD_FUTEX_WAIT(reg) \ + movl $FUTEX_WAIT, reg +# endif +# define LOAD_FUTEX_WAKE(reg) \ + movl $FUTEX_WAKE, reg +#endif + /* For the calculation see asm/vsyscall.h. */ #define VSYSCALL_ADDR_vgettimeofday 0xffffffffff600000 @@ -52,11 +67,7 @@ __lll_mutex_lock_wait: cfi_offset(%rdx, -24) xorq %r10, %r10 /* No timeout. */ movl $2, %edx -#if FUTEX_WAIT == 0 - xorl %esi, %esi -#else - movl $FUTEX_WAIT, %esi -#endif + LOAD_FUTEX_WAIT (%esi) cmpl %edx, %eax /* NB: %edx == 2 */ jne 2f @@ -151,11 +162,7 @@ __lll_mutex_timedlock_wait: je 8f movq %rsp, %r10 -#if FUTEX_WAIT == 0 - xorl %esi, %esi -#else - movl $FUTEX_WAIT, %esi -#endif + LOAD_FUTEX_WAIT (%esi) movq %r12, %rdi movl $SYS_futex, %eax syscall @@ -247,7 +254,7 @@ __lll_mutex_unlock_wake: cfi_offset(%rdx, -24) movl $0, (%rdi) - movl $FUTEX_WAKE, %esi + LOAD_FUTEX_WAKE (%esi) movl $1, %edx /* Wake one thread. */ movl $SYS_futex, %eax syscall @@ -311,6 +318,8 @@ __lll_timedwait_tid: 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 diff --git a/libc/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.h b/libc/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.h index bb988f3b2..fbe48b37a 100644 --- a/libc/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.h +++ b/libc/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.h @@ -39,6 +39,7 @@ #define FUTEX_LOCK_PI 6 #define FUTEX_UNLOCK_PI 7 #define FUTEX_TRYLOCK_PI 8 +#define FUTEX_PRIVATE_FLAG 128 /* Initializer for compatibility lock. */ diff --git a/libc/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_once.S b/libc/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_once.S index 9db551691..7740c599d 100644 --- a/libc/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_once.S +++ b/libc/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_once.S @@ -1,4 +1,4 @@ -/* Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc. +/* Copyright (C) 2002, 2003, 2005, 2007 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. @@ -17,14 +17,19 @@ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ +#include <kernel-features.h> +#include <tcb-offsets.h> + #ifndef UP # define LOCK lock #else # define LOCK #endif -#define SYS_futex 202 -#define FUTEX_WAKE 1 +#define SYS_futex 202 +#define FUTEX_WAIT 0 +#define FUTEX_WAKE 1 +#define FUTEX_PRIVATE_FLAG 128 .comm __fork_generation, 4, 4 @@ -74,10 +79,15 @@ __pthread_once: jnz 3f /* Different for generation -> run initializer. */ /* Somebody else got here first. Wait. */ -#if FUTEX_WAIT == 0 - xorl %esi, %esi +#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 @@ -106,7 +116,12 @@ __pthread_once: /* 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 @@ -133,7 +148,12 @@ clear_once_control: 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 diff --git a/libc/nptl/sysdeps/x86_64/tcb-offsets.sym b/libc/nptl/sysdeps/x86_64/tcb-offsets.sym index 21274ecab..1c70c6bde 100644 --- a/libc/nptl/sysdeps/x86_64/tcb-offsets.sym +++ b/libc/nptl/sysdeps/x86_64/tcb-offsets.sym @@ -12,3 +12,6 @@ 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 diff --git a/libc/nptl/sysdeps/x86_64/tls.h b/libc/nptl/sysdeps/x86_64/tls.h index 0b5aeb00f..5ddaafada 100644 --- a/libc/nptl/sysdeps/x86_64/tls.h +++ b/libc/nptl/sysdeps/x86_64/tls.h @@ -26,6 +26,8 @@ # include <stddef.h> # include <stdint.h> # include <stdlib.h> +# include <sysdep.h> +# include <kernel-features.h> /* Type for the dtv. */ @@ -47,10 +49,14 @@ typedef struct 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; +#endif } tcbhead_t; #else /* __ASSEMBLER__ */ @@ -337,6 +343,27 @@ typedef struct = 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); \ + } \ + 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/libc/nptl/tst-robust9.c b/libc/nptl/tst-robust9.c new file mode 100644 index 000000000..1d6ba179b --- /dev/null +++ b/libc/nptl/tst-robust9.c @@ -0,0 +1,94 @@ +#include <stdio.h> +#include <stdlib.h> +#include <errno.h> +#include <pthread.h> +#include <unistd.h> +#include <sys/time.h> + + +static pthread_mutex_t m; + +static void * +tf (void *data) +{ + int err = pthread_mutex_lock (&m); + if (err == EOWNERDEAD) + { + err = pthread_mutex_consistent_np (&m); + if (err) + { + puts ("pthread_mutex_consistent_np"); + exit (1); + } + } + else if (err) + { + puts ("pthread_mutex_lock"); + exit (1); + } + printf ("thread%ld got the lock.\n", (long int) data); + sleep (1); + /* exit without unlock */ + return NULL; +} + +static int +do_test (void) +{ + int err, i; + pthread_t t[3]; + pthread_mutexattr_t ma; + + pthread_mutexattr_init (&ma); + err = pthread_mutexattr_setrobust_np (&ma, PTHREAD_MUTEX_ROBUST_NP); + if (err) + { + puts ("pthread_mutexattr_setrobust_np"); + return 1; + } +#ifdef ENABLE_PI + if (pthread_mutexattr_setprotocol (&ma, PTHREAD_PRIO_INHERIT) != 0) + { + puts ("pthread_mutexattr_setprotocol failed"); + return 1; + } +#endif + err = pthread_mutex_init (&m, &ma); +#ifdef ENABLE_PI + if (err == ENOTSUP) + { + puts ("PI robust mutexes not supported"); + return 0; + } +#endif + if (err) + { + puts ("pthread_mutex_init"); + return 1; + } + + for (i = 0; i < sizeof (t) / sizeof (t[0]); i++) + { + err = pthread_create (&t[i], NULL, tf, (void *) (long int) i); + if (err) + { + puts ("pthread_create"); + return 1; + } + } + + for (i = 0; i < sizeof (t) / sizeof (t[0]); i++) + { + err = pthread_join (t[i], NULL); + if (err) + { + puts ("pthread_join"); + return 1; + } + } + return 0; +} + +#define TIMEOUT 5 +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" diff --git a/libc/nptl/tst-robustpi9.c b/libc/nptl/tst-robustpi9.c new file mode 100644 index 000000000..d059aa7d8 --- /dev/null +++ b/libc/nptl/tst-robustpi9.c @@ -0,0 +1,2 @@ +#define ENABLE_PI 1 +#include "tst-robust9.c" diff --git a/libc/nscd/aicache.c b/libc/nscd/aicache.c index 4640b4df9..bccac3abb 100644 --- a/libc/nscd/aicache.c +++ b/libc/nscd/aicache.c @@ -1,5 +1,5 @@ /* Cache handling for host lookup. - Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc. + Copyright (C) 2004, 2005, 2006, 2007 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@redhat.com>, 2004. @@ -78,15 +78,6 @@ addhstaiX (struct database_dyn *db, int fd, request_header *req, dbg_log (_("Reloading \"%s\" in hosts cache!"), (char *) key); } -#if 0 - uid_t oldeuid = 0; - if (db->secure) - { - oldeuid = geteuid (); - pthread_seteuid_np (uid); - } -#endif - static service_user *hosts_database; service_user *nip = NULL; int no_more; @@ -263,8 +254,10 @@ addhstaiX (struct database_dyn *db, int fd, request_header *req, total = sizeof (*dataset) + naddrs + addrslen + canonlen; - /* Now we can allocate the data structure. */ - if (he == NULL) + /* Now we can allocate the data structure. If the TTL + of the entry is reported as zero do not cache the + entry at all. */ + if (ttl != 0 && he == NULL) { dataset = (struct dataset *) mempool_alloc (db, total @@ -453,11 +446,6 @@ addhstaiX (struct database_dyn *db, int fd, request_header *req, out: _res.options = old_res_options; -#if 0 - if (db->secure) - pthread_seteuid_np (oldeuid); -#endif - if (dataset != NULL && !alloca_used) { /* If necessary, we also propagate the data to disk. */ diff --git a/libc/rt/tst-shm.c b/libc/rt/tst-shm.c index 01bf89fa7..5838b0ee1 100644 --- a/libc/rt/tst-shm.c +++ b/libc/rt/tst-shm.c @@ -60,7 +60,7 @@ static void worker (int write_now) { struct timespec ts; - struct stat st; + struct stat64 st; int i; int fd = do_open (); char *mem; @@ -68,8 +68,10 @@ worker (int write_now) if (fd == -1) exit (fd); - if (fstat (fd, &st) == -1 || st.st_size != 4000) + if (fstat64 (fd, &st) == -1) error (EXIT_FAILURE, 0, "stat failed"); + if (st.st_size != 4000) + error (EXIT_FAILURE, 0, "size incorrect"); mem = mmap (NULL, 4000, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); if (mem == NULL) @@ -131,7 +133,7 @@ do_test (void) pid_t pid2; int status1; int status2; - struct stat st; + struct stat64 st; /* Create the shared memory object. */ fd = shm_open ("/shm-test", O_RDWR | O_CREAT | O_TRUNC | O_EXCL, 0600); @@ -155,11 +157,16 @@ do_test (void) return 0; } - if (fstat (fd, &st) == -1 || st.st_size != 4000) + if (fstat64 (fd, &st) == -1) { shm_unlink ("/shm-test"); error (EXIT_FAILURE, 0, "initial stat failed"); } + if (st.st_size != 4000) + { + shm_unlink ("/shm-test"); + error (EXIT_FAILURE, 0, "initial size not correct"); + } /* Spawn to processes which will do the work. */ pid1 = fork (); diff --git a/libc/stdio-common/tst-sprintf.c b/libc/stdio-common/tst-sprintf.c index c61d3b50e..c04fef18f 100644 --- a/libc/stdio-common/tst-sprintf.c +++ b/libc/stdio-common/tst-sprintf.c @@ -37,5 +37,26 @@ main (void) free (dst); } + if (sprintf (buf, "%1$d%3$.*2$s%4$d", 7, 67108863, "x", 8) != 3 + || strcmp (buf, "7x8") != 0) + { + printf ("sprintf (buf, \"%%1$d%%3$.*2$s%%4$d\", 7, 67108863, \"x\", 8) produced `%s' output", buf); + result = 1; + } + + if (sprintf (buf, "%67108863.16\"%d", 7) != 14 + || strcmp (buf, "%67108863.16\"7") != 0) + { + printf ("sprintf (buf, \"%%67108863.16\\\"%%d\", 7) produced `%s' output", buf); + result = 1; + } + + if (sprintf (buf, "%*\"%d", 0x3ffffff, 7) != 11 + || strcmp (buf, "%67108863\"7") != 0) + { + printf ("sprintf (buf, \"%%*\\\"%%d\", 0x3ffffff, 7) produced `%s' output", buf); + result = 1; + } + return result; } diff --git a/libc/stdio-common/vfprintf.c b/libc/stdio-common/vfprintf.c index 20638ad1f..25edde751 100644 --- a/libc/stdio-common/vfprintf.c +++ b/libc/stdio-common/vfprintf.c @@ -1627,6 +1627,8 @@ do_positional: /* Just a counter. */ size_t cnt; + free (workstart); + workstart = NULL; if (grouping == (const char *) -1) { @@ -1801,7 +1803,9 @@ do_positional: int use_outdigits = specs[nspecs_done].info.i18n; char pad = specs[nspecs_done].info.pad; CHAR_T spec = specs[nspecs_done].info.spec; - CHAR_T *workstart = NULL; + + workstart = NULL; + workend = &work_buffer[sizeof (work_buffer) / sizeof (CHAR_T)]; /* Fill in last information. */ if (specs[nspecs_done].width_arg != -1) @@ -1897,8 +1901,7 @@ do_positional: break; } - if (__builtin_expect (workstart != NULL, 0)) - free (workstart); + free (workstart); workstart = NULL; /* Write the following constant string. */ @@ -1926,7 +1929,7 @@ printf_unknown (FILE *s, const struct printf_info *info, { int done = 0; - CHAR_T work_buffer[MAX (info->width, info->spec) + 32]; + CHAR_T work_buffer[MAX (sizeof (info->width), sizeof (info->prec)) * 3]; CHAR_T *const workend = &work_buffer[sizeof (work_buffer) / sizeof (CHAR_T)]; register CHAR_T *w; diff --git a/libc/sysdeps/generic/ldsodefs.h b/libc/sysdeps/generic/ldsodefs.h index a9d20b215..5205c4149 100644 --- a/libc/sysdeps/generic/ldsodefs.h +++ b/libc/sysdeps/generic/ldsodefs.h @@ -486,6 +486,8 @@ struct rtld_global EXTERN void (*_dl_init_static_tls) (struct link_map *); + EXTERN void (*_dl_wait_lookup_done) (void); + #ifdef SHARED }; # define __rtld_global_attribute__ diff --git a/libc/sysdeps/unix/sysv/linux/Makefile b/libc/sysdeps/unix/sysv/linux/Makefile index 4df66440c..0fd9150ff 100644 --- a/libc/sysdeps/unix/sysv/linux/Makefile +++ b/libc/sysdeps/unix/sysv/linux/Makefile @@ -13,7 +13,7 @@ endif ifeq ($(subdir),misc) sysdep_routines += sysctl clone llseek umount umount2 readahead \ - setfsuid setfsgid makedev + setfsuid setfsgid makedev epoll_pwait inet-CFLAGS-$(OPTION_EGLIBC_INET) = -DOPTION_EGLIBC_INET diff --git a/libc/sysdeps/unix/sysv/linux/epoll_pwait.c b/libc/sysdeps/unix/sysv/linux/epoll_pwait.c new file mode 100644 index 000000000..e689073d1 --- /dev/null +++ b/libc/sysdeps/unix/sysv/linux/epoll_pwait.c @@ -0,0 +1,69 @@ +/* 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 <errno.h> +#include <signal.h> +#include <unistd.h> +#include <sys/epoll.h> + +#include <sysdep-cancel.h> +#include <sys/syscall.h> + +#ifdef __NR_epoll_pwait + +/* 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). + The thread's signal mask is temporarily and atomically replaced with + the one provided as parameter. */ + +int epoll_pwait (int epfd, struct epoll_event *events, + int maxevents, int timeout, + const sigset_t *set) +{ + if (SINGLE_THREAD_P) + return INLINE_SYSCALL (epoll_pwait, 6, epfd, events, maxevents, timeout, + set, _NSIG / 8); + + int oldtype = LIBC_CANCEL_ASYNC (); + + int result = INLINE_SYSCALL (epoll_pwait, 6, epfd, events, maxevents, + timeout, set, _NSIG / 8); + + LIBC_CANCEL_RESET (oldtype); + + return result; +} + +#else + +int epoll_pwait (int epfd, struct epoll_event *events, + int maxevents, int timeout, + const sigset_t *set) +{ + __set_errno (ENOSYS); + return -1; +} +stub_warning (epoll_pwait) + +# include <stub-tag.h> +#endif diff --git a/libc/sysdeps/unix/sysv/linux/i386/epoll_pwait.S b/libc/sysdeps/unix/sysv/linux/i386/epoll_pwait.S new file mode 100644 index 000000000..5f51db229 --- /dev/null +++ b/libc/sysdeps/unix/sysv/linux/i386/epoll_pwait.S @@ -0,0 +1,80 @@ +/* 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 <sysdep.h> +#define _ERRNO_H +#include <bits/errno.h> +#define _SIGNAL_H +#include <bits/signum.h> + + + .text +ENTRY (epoll_pwait) + +#ifdef __NR_epoll_pwait + + /* Save registers. */ + pushl %ebp + cfi_adjust_cfa_offset (4) + pushl %ebx + cfi_adjust_cfa_offset (4) + pushl %esi + cfi_adjust_cfa_offset (4) + pushl %edi + cfi_adjust_cfa_offset (4) + cfi_rel_offset (edi, 0) + cfi_rel_offset (esi, 4) + cfi_rel_offset (ebx, 8) + cfi_rel_offset (ebp, 12) + + movl 20(%esp), %ebx + movl 24(%esp), %ecx + movl 28(%esp), %edx + movl 32(%esp), %esi + movl 36(%esp), %edi + movl $_NSIG/8, %ebp + movl $__NR_epoll_pwait, %eax + + ENTER_KERNEL + + /* Restore registers. */ + 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) + popl %ebp + cfi_adjust_cfa_offset (-4) + cfi_restore (ebp) + + /* If 0 > %eax > -4096 there was an error. */ + cmpl $-4096, %eax + ja SYSCALL_ERROR_LABEL + + /* Successful; return the syscall's value. */ +#else + movl $-ENOSYS, %eax + jmp SYSCALL_ERROR_LABEL +#endif +L(pseudo_end): + ret +PSEUDO_END (epoll_pwait) diff --git a/libc/sysdeps/unix/sysv/linux/i386/sync_file_range.S b/libc/sysdeps/unix/sysv/linux/i386/sync_file_range.S index f39e8a00d..8544703d5 100644 --- a/libc/sysdeps/unix/sysv/linux/i386/sync_file_range.S +++ b/libc/sysdeps/unix/sysv/linux/i386/sync_file_range.S @@ -1,5 +1,5 @@ /* Selective file content synch'ing. - Copyright (C) 2006 Free Software Foundation, Inc. + 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 @@ -63,10 +63,10 @@ ENTRY (sync_file_range) cmpl $-4095, %eax jae SYSCALL_ERROR_LABEL -L(pseudo_end): - ret #else movl $-ENOSYS, %eax jmp SYSCALL_ERROR_LABEL #endif +L(pseudo_end): + ret PSEUDO_END (sync_file_range) diff --git a/libc/sysdeps/unix/sysv/linux/kernel-features.h b/libc/sysdeps/unix/sysv/linux/kernel-features.h index ed3200154..f6bd906f5 100644 --- a/libc/sysdeps/unix/sysv/linux/kernel-features.h +++ b/libc/sysdeps/unix/sysv/linux/kernel-features.h @@ -1,6 +1,6 @@ /* Set flags signalling availability of kernel features based on given kernel version number. - Copyright (C) 1999-2003, 2004, 2005, 2006 Free Software Foundation, Inc. + Copyright (C) 1999-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 @@ -463,3 +463,8 @@ #if __LINUX_KERNEL_VERSION >= 0x020616 # define __ASSUME_UTIMENSAT 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/libc/sysdeps/unix/sysv/linux/syscalls.list b/libc/sysdeps/unix/sysv/linux/syscalls.list index d1226ef82..e16110480 100644 --- a/libc/sysdeps/unix/sysv/linux/syscalls.list +++ b/libc/sysdeps/unix/sysv/linux/syscalls.list @@ -10,7 +10,6 @@ delete_module EXTRA delete_module 3 delete_module epoll_create EXTRA epoll_create i:i epoll_create epoll_ctl EXTRA epoll_ctl i:iiip epoll_ctl epoll_wait EXTRA epoll_wait Ci:ipii epoll_wait -epoll_pwait EXTRA epoll_pwait Ci:ipiipi epoll_pwait fdatasync - fdatasync Ci:i fdatasync flock - flock i:ii __flock flock fork - fork i: __libc_fork __fork fork diff --git a/libc/sysdeps/unix/sysv/linux/x86_64/sys/epoll.h b/libc/sysdeps/unix/sysv/linux/x86_64/sys/epoll.h index 02672d3c7..26f23da40 100644 --- a/libc/sysdeps/unix/sysv/linux/x86_64/sys/epoll.h +++ b/libc/sysdeps/unix/sysv/linux/x86_64/sys/epoll.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2002,2003,2004,2005,2006 Free Software Foundation, Inc. +/* 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 @@ -22,6 +22,14 @@ #include <stdint.h> #include <sys/types.h> +/* Get __sigset_t. */ +#include <bits/sigset.h> + +#ifndef __sigset_t_defined +# define __sigset_t_defined +typedef __sigset_t sigset_t; +#endif + enum EPOLL_EVENTS { @@ -105,6 +113,16 @@ extern int epoll_ctl (int __epfd, int __op, int __fd, extern int epoll_wait (int __epfd, struct epoll_event *__events, int __maxevents, int __timeout); + +/* Same as epoll_wait, but the thread's signal mask is temporarily + and atomically replaced with the one provided as parameter. + + This function is a cancellation point and therefore not marked with + __THROW. */ +extern int epoll_pwait (int __epfd, struct epoll_event *__events, + int __maxevents, int __timeout, + __const __sigset_t *__ss); + __END_DECLS #endif /* sys/epoll.h */ diff --git a/libc/sysdeps/unix/sysv/linux/x86_64/sysconf.c b/libc/sysdeps/unix/sysv/linux/x86_64/sysconf.c index 5a898b785..126aae719 100644 --- a/libc/sysdeps/unix/sysv/linux/x86_64/sysconf.c +++ b/libc/sysdeps/unix/sysv/linux/x86_64/sysconf.c @@ -1,5 +1,5 @@ /* Get file-specific information about a file. Linux version. - Copyright (C) 2003, 2004, 2006 Free Software Foundation, Inc. + 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 @@ -24,328 +24,17 @@ static long int linux_sysconf (int name); - - -static const struct intel_02_cache_info -{ - unsigned int idx; - int name; - long int size; - long int assoc; - long int linesize; -} intel_02_known[] = - { - { 0x06, _SC_LEVEL1_ICACHE_SIZE, 8192, 4, 32 }, - { 0x08, _SC_LEVEL1_ICACHE_SIZE, 16384, 4, 32 }, - { 0x0a, _SC_LEVEL1_DCACHE_SIZE, 8192, 2, 32 }, - { 0x0c, _SC_LEVEL1_DCACHE_SIZE, 16384, 4, 32 }, - { 0x22, _SC_LEVEL3_CACHE_SIZE, 524288, 4, 64 }, - { 0x23, _SC_LEVEL3_CACHE_SIZE, 1048576, 8, 64 }, - { 0x25, _SC_LEVEL3_CACHE_SIZE, 2097152, 8, 64 }, - { 0x29, _SC_LEVEL3_CACHE_SIZE, 4194304, 8, 64 }, - { 0x2c, _SC_LEVEL1_DCACHE_SIZE, 32768, 8, 64 }, - { 0x30, _SC_LEVEL1_ICACHE_SIZE, 32768, 8, 64 }, - { 0x39, _SC_LEVEL2_CACHE_SIZE, 131072, 4, 64 }, - { 0x3a, _SC_LEVEL2_CACHE_SIZE, 196608, 6, 64 }, - { 0x3b, _SC_LEVEL2_CACHE_SIZE, 131072, 2, 64 }, - { 0x3c, _SC_LEVEL2_CACHE_SIZE, 262144, 4, 64 }, - { 0x3d, _SC_LEVEL2_CACHE_SIZE, 393216, 6, 64 }, - { 0x3e, _SC_LEVEL2_CACHE_SIZE, 524288, 4, 64 }, - { 0x41, _SC_LEVEL2_CACHE_SIZE, 131072, 4, 32 }, - { 0x42, _SC_LEVEL2_CACHE_SIZE, 262144, 4, 32 }, - { 0x43, _SC_LEVEL2_CACHE_SIZE, 524288, 4, 32 }, - { 0x44, _SC_LEVEL2_CACHE_SIZE, 1048576, 4, 32 }, - { 0x45, _SC_LEVEL2_CACHE_SIZE, 2097152, 4, 32 }, - { 0x46, _SC_LEVEL3_CACHE_SIZE, 4194304, 4, 64 }, - { 0x47, _SC_LEVEL3_CACHE_SIZE, 8388608, 8, 64 }, - { 0x49, _SC_LEVEL2_CACHE_SIZE, 4194304, 16, 64 }, - { 0x4a, _SC_LEVEL3_CACHE_SIZE, 6291456, 12, 64 }, - { 0x4b, _SC_LEVEL3_CACHE_SIZE, 8388608, 16, 64 }, - { 0x4c, _SC_LEVEL3_CACHE_SIZE, 12582912, 12, 64 }, - { 0x4d, _SC_LEVEL3_CACHE_SIZE, 16777216, 16, 64 }, - { 0x60, _SC_LEVEL1_DCACHE_SIZE, 16384, 8, 64 }, - { 0x66, _SC_LEVEL1_DCACHE_SIZE, 8192, 4, 64 }, - { 0x67, _SC_LEVEL1_DCACHE_SIZE, 16384, 4, 64 }, - { 0x68, _SC_LEVEL1_DCACHE_SIZE, 32768, 4, 64 }, - { 0x78, _SC_LEVEL2_CACHE_SIZE, 1048576, 8, 64 }, - { 0x79, _SC_LEVEL2_CACHE_SIZE, 131072, 8, 64 }, - { 0x7a, _SC_LEVEL2_CACHE_SIZE, 262144, 8, 64 }, - { 0x7b, _SC_LEVEL2_CACHE_SIZE, 524288, 8, 64 }, - { 0x7c, _SC_LEVEL2_CACHE_SIZE, 1048576, 8, 64 }, - { 0x7d, _SC_LEVEL2_CACHE_SIZE, 2097152, 8, 64 }, - { 0x7f, _SC_LEVEL2_CACHE_SIZE, 524288, 2, 64 }, - { 0x82, _SC_LEVEL2_CACHE_SIZE, 262144, 8, 32 }, - { 0x83, _SC_LEVEL2_CACHE_SIZE, 524288, 8, 32 }, - { 0x84, _SC_LEVEL2_CACHE_SIZE, 1048576, 8, 32 }, - { 0x85, _SC_LEVEL2_CACHE_SIZE, 2097152, 8, 32 }, - { 0x86, _SC_LEVEL2_CACHE_SIZE, 524288, 4, 64 }, - { 0x87, _SC_LEVEL2_CACHE_SIZE, 1048576, 8, 64 }, - }; -#define nintel_02_known (sizeof (intel_02_known) / sizeof (intel_02_known[0])) - - -static int -intel_02_known_compare (const void *p1, const void *p2) -{ - const struct intel_02_cache_info *i1; - const struct intel_02_cache_info *i2; - - i1 = (const struct intel_02_cache_info *) p1; - i2 = (const struct intel_02_cache_info *) p2; - - if (i1->idx == i2->idx) - return 0; - - return i1->idx < i2->idx ? -1 : 1; -} - - -static long int -__attribute__ ((noinline)) -intel_check_word (int name, unsigned int value, bool *has_level_2, - bool *no_level_2_or_3) -{ - if ((value & 0x80000000) != 0) - /* The register value is reserved. */ - return 0; - - /* Fold the name. The _SC_ constants are always in the order SIZE, - ASSOC, LINESIZE. */ - int folded_name = (_SC_LEVEL1_ICACHE_SIZE - + ((name - _SC_LEVEL1_ICACHE_SIZE) / 3) * 3); - - while (value != 0) - { - unsigned int byte = value & 0xff; - - if (byte == 0x40) - { - *no_level_2_or_3 = true; - - if (folded_name == _SC_LEVEL3_CACHE_SIZE) - /* No need to look further. */ - break; - } - else - { - if (byte == 0x49 && folded_name == _SC_LEVEL3_CACHE_SIZE) - { - /* Intel reused this value. For family 15, model 6 it - specifies the 3rd level cache. Otherwise the 2nd - level cache. */ - unsigned int eax; - unsigned int ebx; - unsigned int ecx; - unsigned int edx; - asm volatile ("xchgl %%ebx, %1; cpuid; xchgl %%ebx, %1" - : "=a" (eax), "=r" (ebx), "=c" (ecx), "=d" (edx) - : "0" (1)); - - unsigned int family = ((eax >> 20) & 0xff) + ((eax >> 8) & 0xf); - unsigned int model = ((((eax >>16) & 0xf) << 4) - + ((eax >> 4) & 0xf)); - if (family == 15 && model == 6) - { - /* The level 3 cache is encoded for this model like - the level 2 cache is for other models. Pretend - the caller asked for the level 2 cache. */ - name = (_SC_LEVEL2_CACHE_SIZE - + (name - _SC_LEVEL3_CACHE_SIZE)); - folded_name = _SC_LEVEL3_CACHE_SIZE; - } - } - - struct intel_02_cache_info *found; - struct intel_02_cache_info search; - - search.idx = byte; - found = bsearch (&search, intel_02_known, nintel_02_known, - sizeof (intel_02_known[0]), intel_02_known_compare); - if (found != NULL) - { - if (found->name == folded_name) - { - unsigned int offset = name - folded_name; - - if (offset == 0) - /* Cache size. */ - return found->size; - if (offset == 1) - return found->assoc; - - assert (offset == 2); - return found->linesize; - } - - if (found->name == _SC_LEVEL2_CACHE_SIZE) - *has_level_2 = true; - } - } - - /* Next byte for the next round. */ - value >>= 8; - } - - /* Nothing found. */ - return 0; -} - - -static long int __attribute__ ((noinline)) -handle_intel (int name, unsigned int maxidx) -{ - assert (maxidx >= 2); - - /* OK, we can use the CPUID instruction to get all info about the - caches. */ - unsigned int cnt = 0; - unsigned int max = 1; - long int result = 0; - bool no_level_2_or_3 = false; - bool has_level_2 = false; - while (cnt++ < max) - { - unsigned int eax; - unsigned int ebx; - unsigned int ecx; - unsigned int edx; - asm volatile ("xchgl %%ebx, %1; cpuid; xchgl %%ebx, %1" - : "=a" (eax), "=r" (ebx), "=c" (ecx), "=d" (edx) - : "0" (2)); - - /* The low byte of EAX in the first round contain the number of - rounds we have to make. At least one, the one we are already - doing. */ - if (cnt == 1) - { - max = eax & 0xff; - eax &= 0xffffff00; - } - - /* Process the individual registers' value. */ - result = intel_check_word (name, eax, &has_level_2, &no_level_2_or_3); - if (result != 0) - return result; - - result = intel_check_word (name, ebx, &has_level_2, &no_level_2_or_3); - if (result != 0) - return result; - - result = intel_check_word (name, ecx, &has_level_2, &no_level_2_or_3); - if (result != 0) - return result; - - result = intel_check_word (name, edx, &has_level_2, &no_level_2_or_3); - if (result != 0) - return result; - } - - if (name >= _SC_LEVEL2_CACHE_SIZE && name <= _SC_LEVEL3_CACHE_LINESIZE - && no_level_2_or_3) - return -1; - - return 0; -} - - -static long int __attribute__ ((noinline)) -handle_amd (int name) -{ - unsigned int eax; - unsigned int ebx; - unsigned int ecx; - unsigned int edx; - asm volatile ("xchgl %%ebx, %1; cpuid; xchgl %%ebx, %1" - : "=a" (eax), "=r" (ebx), "=c" (ecx), "=d" (edx) - : "0" (0x80000000)); - - if (name >= _SC_LEVEL3_CACHE_SIZE) - return 0; - - unsigned int fn = 0x80000005 + (name >= _SC_LEVEL2_CACHE_SIZE); - if (eax < fn) - return 0; - - asm volatile ("xchgl %%ebx, %1; cpuid; xchgl %%ebx, %1" - : "=a" (eax), "=r" (ebx), "=c" (ecx), "=d" (edx) - : "0" (fn)); - - if (name < _SC_LEVEL1_DCACHE_SIZE) - { - name += _SC_LEVEL1_DCACHE_SIZE - _SC_LEVEL1_ICACHE_SIZE; - ecx = edx; - } - - switch (name) - { - case _SC_LEVEL1_DCACHE_SIZE: - return (ecx >> 14) & 0x3fc00; - case _SC_LEVEL1_DCACHE_ASSOC: - ecx >>= 16; - if ((ecx & 0xff) == 0xff) - /* Fully associative. */ - return (ecx << 2) & 0x3fc00; - return ecx & 0xff; - case _SC_LEVEL1_DCACHE_LINESIZE: - return ecx & 0xff; - case _SC_LEVEL2_CACHE_SIZE: - return (ecx & 0xf000) == 0 ? 0 : (ecx >> 6) & 0x3fffc00; - case _SC_LEVEL2_CACHE_ASSOC: - ecx >>= 12; - switch (ecx & 0xf) - { - case 0: - case 1: - case 2: - case 4: - return ecx & 0xf; - case 6: - return 8; - case 8: - return 16; - case 0xf: - return (ecx << 6) & 0x3fffc00; - default: - return 0; - } - case _SC_LEVEL2_CACHE_LINESIZE: - return (ecx & 0xf000) == 0 ? 0 : ecx & 0xff; - default: - assert (! "cannot happen"); - } - return -1; -} +extern long int __cache_sysconf (int) attribute_hidden; /* Get the value of the system variable NAME. */ long int __sysconf (int name) { - /* We only handle the cache information here (for now). */ - if (name < _SC_LEVEL1_ICACHE_SIZE || name > _SC_LEVEL4_CACHE_LINESIZE) - return linux_sysconf (name); - - /* Find out what brand of processor. */ - unsigned int eax; - unsigned int ebx; - unsigned int ecx; - unsigned int edx; - asm volatile ("xchgl %%ebx, %1; cpuid; xchgl %%ebx, %1" - : "=a" (eax), "=r" (ebx), "=c" (ecx), "=d" (edx) - : "0" (0)); - - /* This spells out "GenuineIntel". */ - if (ebx == 0x756e6547 && ecx == 0x6c65746e && edx == 0x49656e69) - return handle_intel (name, eax); - - /* This spells out "AuthenticAMD". */ - if (ebx == 0x68747541 && ecx == 0x444d4163 && edx == 0x69746e65) - return handle_amd (name); - - // XXX Fill in more vendors. + if (name >= _SC_LEVEL1_ICACHE_SIZE && name <= _SC_LEVEL4_CACHE_LINESIZE) + return __cache_sysconf (name); - /* CPU not known, we have no information. */ - return 0; + return linux_sysconf (name); } /* Now the generic Linux version. */ diff --git a/libc/sysdeps/x86_64/Makefile b/libc/sysdeps/x86_64/Makefile index 65b7aa94c..edbdac0e3 100644 --- a/libc/sysdeps/x86_64/Makefile +++ b/libc/sysdeps/x86_64/Makefile @@ -9,3 +9,7 @@ endif ifeq ($(subdir),gmon) sysdep_routines += _mcount endif + +ifeq ($(subdir),string) +sysdep_routines += cacheinfo +endif diff --git a/libc/sysdeps/x86_64/cacheinfo.c b/libc/sysdeps/x86_64/cacheinfo.c new file mode 100644 index 000000000..f8217a175 --- /dev/null +++ b/libc/sysdeps/x86_64/cacheinfo.c @@ -0,0 +1,451 @@ +/* x86_64 cache info. + 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 <assert.h> +#include <stdbool.h> +#include <stdlib.h> +#include <unistd.h> + +static const struct intel_02_cache_info +{ + unsigned int idx; + int name; + long int size; + long int assoc; + long int linesize; +} intel_02_known [] = + { + { 0x06, _SC_LEVEL1_ICACHE_SIZE, 8192, 4, 32 }, + { 0x08, _SC_LEVEL1_ICACHE_SIZE, 16384, 4, 32 }, + { 0x0a, _SC_LEVEL1_DCACHE_SIZE, 8192, 2, 32 }, + { 0x0c, _SC_LEVEL1_DCACHE_SIZE, 16384, 4, 32 }, + { 0x22, _SC_LEVEL3_CACHE_SIZE, 524288, 4, 64 }, + { 0x23, _SC_LEVEL3_CACHE_SIZE, 1048576, 8, 64 }, + { 0x25, _SC_LEVEL3_CACHE_SIZE, 2097152, 8, 64 }, + { 0x29, _SC_LEVEL3_CACHE_SIZE, 4194304, 8, 64 }, + { 0x2c, _SC_LEVEL1_DCACHE_SIZE, 32768, 8, 64 }, + { 0x30, _SC_LEVEL1_ICACHE_SIZE, 32768, 8, 64 }, + { 0x39, _SC_LEVEL2_CACHE_SIZE, 131072, 4, 64 }, + { 0x3a, _SC_LEVEL2_CACHE_SIZE, 196608, 6, 64 }, + { 0x3b, _SC_LEVEL2_CACHE_SIZE, 131072, 2, 64 }, + { 0x3c, _SC_LEVEL2_CACHE_SIZE, 262144, 4, 64 }, + { 0x3d, _SC_LEVEL2_CACHE_SIZE, 393216, 6, 64 }, + { 0x3e, _SC_LEVEL2_CACHE_SIZE, 524288, 4, 64 }, + { 0x41, _SC_LEVEL2_CACHE_SIZE, 131072, 4, 32 }, + { 0x42, _SC_LEVEL2_CACHE_SIZE, 262144, 4, 32 }, + { 0x43, _SC_LEVEL2_CACHE_SIZE, 524288, 4, 32 }, + { 0x44, _SC_LEVEL2_CACHE_SIZE, 1048576, 4, 32 }, + { 0x45, _SC_LEVEL2_CACHE_SIZE, 2097152, 4, 32 }, + { 0x46, _SC_LEVEL3_CACHE_SIZE, 4194304, 4, 64 }, + { 0x47, _SC_LEVEL3_CACHE_SIZE, 8388608, 8, 64 }, + { 0x49, _SC_LEVEL2_CACHE_SIZE, 4194304, 16, 64 }, + { 0x4a, _SC_LEVEL3_CACHE_SIZE, 6291456, 12, 64 }, + { 0x4b, _SC_LEVEL3_CACHE_SIZE, 8388608, 16, 64 }, + { 0x4c, _SC_LEVEL3_CACHE_SIZE, 12582912, 12, 64 }, + { 0x4d, _SC_LEVEL3_CACHE_SIZE, 16777216, 16, 64 }, + { 0x60, _SC_LEVEL1_DCACHE_SIZE, 16384, 8, 64 }, + { 0x66, _SC_LEVEL1_DCACHE_SIZE, 8192, 4, 64 }, + { 0x67, _SC_LEVEL1_DCACHE_SIZE, 16384, 4, 64 }, + { 0x68, _SC_LEVEL1_DCACHE_SIZE, 32768, 4, 64 }, + { 0x78, _SC_LEVEL2_CACHE_SIZE, 1048576, 8, 64 }, + { 0x79, _SC_LEVEL2_CACHE_SIZE, 131072, 8, 64 }, + { 0x7a, _SC_LEVEL2_CACHE_SIZE, 262144, 8, 64 }, + { 0x7b, _SC_LEVEL2_CACHE_SIZE, 524288, 8, 64 }, + { 0x7c, _SC_LEVEL2_CACHE_SIZE, 1048576, 8, 64 }, + { 0x7d, _SC_LEVEL2_CACHE_SIZE, 2097152, 8, 64 }, + { 0x7f, _SC_LEVEL2_CACHE_SIZE, 524288, 2, 64 }, + { 0x82, _SC_LEVEL2_CACHE_SIZE, 262144, 8, 32 }, + { 0x83, _SC_LEVEL2_CACHE_SIZE, 524288, 8, 32 }, + { 0x84, _SC_LEVEL2_CACHE_SIZE, 1048576, 8, 32 }, + { 0x85, _SC_LEVEL2_CACHE_SIZE, 2097152, 8, 32 }, + { 0x86, _SC_LEVEL2_CACHE_SIZE, 524288, 4, 64 }, + { 0x87, _SC_LEVEL2_CACHE_SIZE, 1048576, 8, 64 }, + }; + +#define nintel_02_known (sizeof (intel_02_known) / sizeof (intel_02_known [0])) + +static int +intel_02_known_compare (const void *p1, const void *p2) +{ + const struct intel_02_cache_info *i1; + const struct intel_02_cache_info *i2; + + i1 = (const struct intel_02_cache_info *) p1; + i2 = (const struct intel_02_cache_info *) p2; + + if (i1->idx == i2->idx) + return 0; + + return i1->idx < i2->idx ? -1 : 1; +} + + +static long int +__attribute__ ((noinline)) +intel_check_word (int name, unsigned int value, bool *has_level_2, + bool *no_level_2_or_3) +{ + if ((value & 0x80000000) != 0) + /* The register value is reserved. */ + return 0; + + /* Fold the name. The _SC_ constants are always in the order SIZE, + ASSOC, LINESIZE. */ + int folded_name = (_SC_LEVEL1_ICACHE_SIZE + + ((name - _SC_LEVEL1_ICACHE_SIZE) / 3) * 3); + + while (value != 0) + { + unsigned int byte = value & 0xff; + + if (byte == 0x40) + { + *no_level_2_or_3 = true; + + if (folded_name == _SC_LEVEL3_CACHE_SIZE) + /* No need to look further. */ + break; + } + else + { + if (byte == 0x49 && folded_name == _SC_LEVEL3_CACHE_SIZE) + { + /* Intel reused this value. For family 15, model 6 it + specifies the 3rd level cache. Otherwise the 2nd + level cache. */ + unsigned int eax; + unsigned int ebx; + unsigned int ecx; + unsigned int edx; + asm volatile ("cpuid" + : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx) + : "0" (1)); + + unsigned int family = ((eax >> 20) & 0xff) + ((eax >> 8) & 0xf); + unsigned int model = ((((eax >>16) & 0xf) << 4) + + ((eax >> 4) & 0xf)); + if (family == 15 && model == 6) + { + /* The level 3 cache is encoded for this model like + the level 2 cache is for other models. Pretend + the caller asked for the level 2 cache. */ + name = (_SC_LEVEL2_CACHE_SIZE + + (name - _SC_LEVEL3_CACHE_SIZE)); + folded_name = _SC_LEVEL3_CACHE_SIZE; + } + } + + struct intel_02_cache_info *found; + struct intel_02_cache_info search; + + search.idx = byte; + found = bsearch (&search, intel_02_known, nintel_02_known, + sizeof (intel_02_known[0]), intel_02_known_compare); + if (found != NULL) + { + if (found->name == folded_name) + { + unsigned int offset = name - folded_name; + + if (offset == 0) + /* Cache size. */ + return found->size; + if (offset == 1) + return found->assoc; + + assert (offset == 2); + return found->linesize; + } + + if (found->name == _SC_LEVEL2_CACHE_SIZE) + *has_level_2 = true; + } + } + + /* Next byte for the next round. */ + value >>= 8; + } + + /* Nothing found. */ + return 0; +} + + +static long int __attribute__ ((noinline)) +handle_intel (int name, unsigned int maxidx) +{ + assert (maxidx >= 2); + + /* OK, we can use the CPUID instruction to get all info about the + caches. */ + unsigned int cnt = 0; + unsigned int max = 1; + long int result = 0; + bool no_level_2_or_3 = false; + bool has_level_2 = false; + + while (cnt++ < max) + { + unsigned int eax; + unsigned int ebx; + unsigned int ecx; + unsigned int edx; + asm volatile ("cpuid" + : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx) + : "0" (2)); + + /* The low byte of EAX in the first round contain the number of + rounds we have to make. At least one, the one we are already + doing. */ + if (cnt == 1) + { + max = eax & 0xff; + eax &= 0xffffff00; + } + + /* Process the individual registers' value. */ + result = intel_check_word (name, eax, &has_level_2, &no_level_2_or_3); + if (result != 0) + return result; + + result = intel_check_word (name, ebx, &has_level_2, &no_level_2_or_3); + if (result != 0) + return result; + + result = intel_check_word (name, ecx, &has_level_2, &no_level_2_or_3); + if (result != 0) + return result; + + result = intel_check_word (name, edx, &has_level_2, &no_level_2_or_3); + if (result != 0) + return result; + } + + if (name >= _SC_LEVEL2_CACHE_SIZE && name <= _SC_LEVEL3_CACHE_LINESIZE + && no_level_2_or_3) + return -1; + + return 0; +} + + +static long int __attribute__ ((noinline)) +handle_amd (int name) +{ + unsigned int eax; + unsigned int ebx; + unsigned int ecx; + unsigned int edx; + asm volatile ("cpuid" + : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx) + : "0" (0x80000000)); + + if (name >= _SC_LEVEL3_CACHE_SIZE) + return 0; + + unsigned int fn = 0x80000005 + (name >= _SC_LEVEL2_CACHE_SIZE); + if (eax < fn) + return 0; + + asm volatile ("cpuid" + : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx) + : "0" (fn)); + + if (name < _SC_LEVEL1_DCACHE_SIZE) + { + name += _SC_LEVEL1_DCACHE_SIZE - _SC_LEVEL1_ICACHE_SIZE; + ecx = edx; + } + + switch (name) + { + case _SC_LEVEL1_DCACHE_SIZE: + return (ecx >> 14) & 0x3fc00; + case _SC_LEVEL1_DCACHE_ASSOC: + ecx >>= 16; + if ((ecx & 0xff) == 0xff) + /* Fully associative. */ + return (ecx << 2) & 0x3fc00; + return ecx & 0xff; + case _SC_LEVEL1_DCACHE_LINESIZE: + return ecx & 0xff; + case _SC_LEVEL2_CACHE_SIZE: + return (ecx & 0xf000) == 0 ? 0 : (ecx >> 6) & 0x3fffc00; + case _SC_LEVEL2_CACHE_ASSOC: + ecx >>= 12; + switch (ecx & 0xf) + { + case 0: + case 1: + case 2: + case 4: + return ecx & 0xf; + case 6: + return 8; + case 8: + return 16; + case 0xf: + return (ecx << 6) & 0x3fffc00; + default: + return 0; + } + case _SC_LEVEL2_CACHE_LINESIZE: + return (ecx & 0xf000) == 0 ? 0 : ecx & 0xff; + default: + assert (! "cannot happen"); + } + return -1; +} + + +/* Get the value of the system variable NAME. */ +long int +attribute_hidden +__cache_sysconf (int name) +{ + /* Find out what brand of processor. */ + unsigned int eax; + unsigned int ebx; + unsigned int ecx; + unsigned int edx; + asm volatile ("cpuid" + : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx) + : "0" (0)); + + /* This spells out "GenuineIntel". */ + if (ebx == 0x756e6547 && ecx == 0x6c65746e && edx == 0x49656e69) + return handle_intel (name, eax); + + /* This spells out "AuthenticAMD". */ + if (ebx == 0x68747541 && ecx == 0x444d4163 && edx == 0x69746e65) + return handle_amd (name); + + // XXX Fill in more vendors. + + /* CPU not known, we have no information. */ + return 0; +} + + +/* Half the core cache size for use in memory and string routines, typically + L1 size. */ +long int __x86_64_core_cache_size_half attribute_hidden = 32 * 1024 / 2; +/* Shared cache size for use in memory and string routines, typically + L2 or L3 size. */ +long int __x86_64_shared_cache_size_half attribute_hidden = 1024 * 1024 / 2; +/* PREFETCHW support flag for use in memory and string routines. */ +int __x86_64_prefetchw attribute_hidden; + + +static void +__attribute__((constructor)) +init_cacheinfo (void) +{ + /* Find out what brand of processor. */ + unsigned int eax; + unsigned int ebx; + unsigned int ecx; + unsigned int edx; + int max_cpuid; + int max_cpuid_ex; + long int core = -1; + long int shared = -1; + unsigned int level; + unsigned int threads = 0; + + asm volatile ("cpuid" + : "=a" (max_cpuid), "=b" (ebx), "=c" (ecx), "=d" (edx) + : "0" (0)); + + /* This spells out "GenuineIntel". */ + if (ebx == 0x756e6547 && ecx == 0x6c65746e && edx == 0x49656e69) + { + core = handle_intel (_SC_LEVEL1_DCACHE_SIZE, max_cpuid); + + /* Try L3 first. */ + level = 3; + shared = handle_intel (_SC_LEVEL3_CACHE_SIZE, max_cpuid); + + if (shared <= 0) + { + /* Try L2 otherwise. */ + level = 2; + shared = handle_intel (_SC_LEVEL2_CACHE_SIZE, max_cpuid); + } + + /* Figure out the number of logical threads that share the + highest cache level. */ + if (max_cpuid >= 4) + { + int i = 0; + + /* Query until desired cache level is enumerated. */ + do + { + asm volatile ("cpuid" + : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx) + : "0" (4), "2" (i++)); + } + while (((eax >> 5) & 0x7) != level); + + threads = ((eax >> 14) & 0x3ff) + 1; + } + else + { + /* Assume that all logical threads share the highest cache level. */ + asm volatile ("cpuid" + : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx) + : "0" (1)); + + threads = (ebx >> 16) & 0xff; + } + + /* Cap usage of highest cache level to the number of supported + threads. */ + if (shared > 0 && threads > 0) + shared /= threads; + } + /* This spells out "AuthenticAMD". */ + else if (ebx == 0x68747541 && ecx == 0x444d4163 && edx == 0x69746e65) + { + core = handle_amd (_SC_LEVEL1_DCACHE_SIZE); + shared = handle_amd (_SC_LEVEL2_CACHE_SIZE); + + asm volatile ("cpuid" + : "=a" (max_cpuid_ex), "=b" (ebx), "=c" (ecx), "=d" (edx) + : "0" (0x80000000)); + + if (max_cpuid_ex >= 0x80000001) + { + asm volatile ("cpuid" + : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx) + : "0" (0x80000001)); + /* PREFETCHW || 3DNow! */ + if ((ecx & 0x100) || (edx & 0x80000000)) + __x86_64_prefetchw = -1; + } + } + + if (core > 0) + __x86_64_core_cache_size_half = core / 2; + + if (shared > 0) + __x86_64_shared_cache_size_half = shared / 2; +} diff --git a/libc/sysdeps/x86_64/fpu/k_cosl.c b/libc/sysdeps/x86_64/fpu/k_cosl.c new file mode 100644 index 000000000..eea55a98d --- /dev/null +++ b/libc/sysdeps/x86_64/fpu/k_cosl.c @@ -0,0 +1 @@ +/* Not needed. */ diff --git a/libc/sysdeps/x86_64/fpu/k_rem_pio2l.c b/libc/sysdeps/x86_64/fpu/k_rem_pio2l.c new file mode 100644 index 000000000..eea55a98d --- /dev/null +++ b/libc/sysdeps/x86_64/fpu/k_rem_pio2l.c @@ -0,0 +1 @@ +/* Not needed. */ diff --git a/libc/sysdeps/x86_64/fpu/k_sinl.c b/libc/sysdeps/x86_64/fpu/k_sinl.c new file mode 100644 index 000000000..eea55a98d --- /dev/null +++ b/libc/sysdeps/x86_64/fpu/k_sinl.c @@ -0,0 +1 @@ +/* Not needed. */ diff --git a/libc/sysdeps/x86_64/fpu/k_tanl.c b/libc/sysdeps/x86_64/fpu/k_tanl.c new file mode 100644 index 000000000..eea55a98d --- /dev/null +++ b/libc/sysdeps/x86_64/fpu/k_tanl.c @@ -0,0 +1 @@ +/* Not needed. */ diff --git a/libc/sysdeps/x86_64/memcpy.S b/libc/sysdeps/x86_64/memcpy.S index 5f06198b5..231329864 100644 --- a/libc/sysdeps/x86_64/memcpy.S +++ b/libc/sysdeps/x86_64/memcpy.S @@ -1,7 +1,10 @@ -/* Highly optimized version for x86-64. - Copyright (C) 1997, 2000, 2002, 2003, 2004 Free Software Foundation, Inc. +/* + Optimized memcpy for x86-64. + + Copyright (C) 2007 Free Software Foundation, Inc. + Contributed by Evandro Menezes <evandro.menezes@amd.com>, 2007. + This file is part of the GNU C Library. - Based on i586 version contributed by Ulrich Drepper <drepper@cygnus.com>, 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 @@ -16,86 +19,556 @@ You should have received a copy of the GNU Lesser General Public License along with the GNU C Library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - 02111-1307 USA. */ + 02111-1307 USA. +*/ #include <sysdep.h> #include "asm-syntax.h" -#include "bp-sym.h" -#include "bp-asm.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) +/* Stack slots in the red-zone. */ + +#ifdef USE_AS_MEMPCPY +# define RETVAL (0) +#else +# define RETVAL (-8) +#endif +#define SAVE0 (RETVAL - 8) +#define SAVE1 (SAVE0 - 8) +#define SAVE2 (SAVE1 - 8) +#define SAVE3 (SAVE2 - 8) .text + #if defined PIC && !defined NOT_IN_libc ENTRY (__memcpy_chk) + cmpq %rdx, %rcx jb HIDDEN_JUMPTARGET (__chk_fail) + 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. */ + +ENTRY(memcpy) /* (void *, const void*, size_t) */ + +/* Handle tiny blocks. */ + +L(1try): /* up to 32B */ cmpq $32, %rdx - movq %rdx, %rcx -#if !MEMPCPY_P - movq %rdi, %r10 /* Save value. */ +#ifndef USE_AS_MEMPCPY + movq %rdi, %rax /* save return value */ #endif + jae L(1after) - /* We need this in any case. */ - cld +L(1): /* 1-byte once */ + testb $1, %dl + jz L(1a) - jbe 1f + movzbl (%rsi), %ecx + movb %cl, (%rdi) - /* Align destination. */ - movq %rdi, %rax - negq %rax - andq $7, %rax - subq %rax, %rcx - xchgq %rax, %rcx + incq %rsi + incq %rdi + + .p2align 4,, 4 + +L(1a): /* 2-byte once */ + testb $2, %dl + jz L(1b) + + movzwl (%rsi), %ecx + movw %cx, (%rdi) + + addq $2, %rsi + addq $2, %rdi + + .p2align 4,, 4 + +L(1b): /* 4-byte once */ + testb $4, %dl + jz L(1c) + + movl (%rsi), %ecx + movl %ecx, (%rdi) + + addq $4, %rsi + addq $4, %rdi + + .p2align 4,, 4 + +L(1c): /* 8-byte once */ + testb $8, %dl + jz L(1d) + + movq (%rsi), %rcx + movq %rcx, (%rdi) + + addq $8, %rsi + addq $8, %rdi + + .p2align 4,, 4 + +L(1d): /* 16-byte loop */ + andl $0xf0, %edx + jz L(exit) + + .p2align 4 + +L(1loop): + movq (%rsi), %rcx + movq 8 (%rsi), %r8 + movq %rcx, (%rdi) + movq %r8, 8 (%rdi) + + subl $16, %edx + + leaq 16 (%rsi), %rsi + leaq 16 (%rdi), %rdi + + jnz L(1loop) + + .p2align 4,, 4 + +L(exit): /* exit */ +#ifdef USE_AS_MEMPCPY + movq %rdi, %rax /* return value */ +#else + rep +#endif + retq + + .p2align 4 + +L(1after): +#ifndef USE_AS_MEMPCPY + movq %rax, RETVAL (%rsp) /* save return value */ +#endif + +/* Align to the natural word size. */ + +L(aligntry): + movl %esi, %ecx /* align by destination */ + + andl $7, %ecx + jz L(alignafter) /* already aligned */ + +L(align): /* align */ + leaq -8 (%rcx, %rdx), %rdx /* calculate remaining bytes */ + subl $8, %ecx + + .p2align 4 + +L(alignloop): /* 1-byte alignment loop */ + movzbl (%rsi), %eax + movb %al, (%rdi) + + incl %ecx + + leaq 1 (%rsi), %rsi + leaq 1 (%rdi), %rdi - rep; movsb + jnz L(alignloop) - movq %rax, %rcx - subq $32, %rcx - js 2f + .p2align 4 + +L(alignafter): + +/* Loop to handle mid-sized blocks. */ + +L(32try): /* up to 1KB */ + cmpq $1024, %rdx + ja L(32after) + +L(32): /* 32-byte loop */ + movl %edx, %ecx + shrl $5, %ecx + jz L(32skip) .p2align 4 -3: - /* Now correct the loop counter. Please note that in the following - code the flags are not changed anymore. */ - subq $32, %rcx +L(32loop): + decl %ecx movq (%rsi), %rax - movq 8(%rsi), %rdx - movq 16(%rsi), %r8 - movq 24(%rsi), %r9 + movq 8 (%rsi), %r8 + movq 16 (%rsi), %r9 + movq 24 (%rsi), %r10 + movq %rax, (%rdi) - movq %rdx, 8(%rdi) - movq %r8, 16(%rdi) - movq %r9, 24(%rdi) + movq %r8, 8 (%rdi) + movq %r9, 16 (%rdi) + movq %r10, 24 (%rdi) leaq 32(%rsi), %rsi leaq 32(%rdi), %rdi - jns 3b + jz L(32skip) /* help out smaller blocks */ + + decl %ecx + + movq (%rsi), %rax + movq 8 (%rsi), %r8 + movq 16 (%rsi), %r9 + movq 24 (%rsi), %r10 + + movq %rax, (%rdi) + movq %r8, 8 (%rdi) + movq %r9, 16 (%rdi) + movq %r10, 24 (%rdi) + + leaq 32 (%rsi), %rsi + leaq 32 (%rdi), %rdi - /* Correct extra loop counter modification. */ -2: addq $32, %rcx -1: rep; movsb + jnz L(32loop) -#if MEMPCPY_P - movq %rdi, %rax /* Set return value. */ + .p2align 4 + +L(32skip): + andl $31, %edx /* check for left overs */ +#ifdef USE_AS_MEMPCPY + jnz L(1) + + movq %rdi, %rax #else - movq %r10, %rax /* Set return value. */ + movq RETVAL (%rsp), %rax + jnz L(1) + rep +#endif + retq /* exit */ + + .p2align 4 + +L(32after): + +/* + In order to minimize code-size in RTLD, algorithms specific for + larger blocks are excluded when building for RTLD. +*/ + +/* Handle large blocks smaller than 1/2 L1. */ + +L(fasttry): /* first 1/2 L1 */ +#ifndef NOT_IN_libc /* only up to this algorithm outside of libc.so */ + movq __x86_64_core_cache_size_half (%rip), %r11 + cmpq %rdx, %r11 /* calculate the smaller of */ + cmovaq %rdx, %r11 /* remaining bytes and 1/2 L1 */ +#endif + +L(fast): /* good ol' MOVS */ +#ifndef NOT_IN_libc + movq %r11, %rcx + andq $-8, %r11 +#else + movq %rdx, %rcx +#endif + shrq $3, %rcx + jz L(fastskip) + + rep + movsq + + .p2align 4,, 4 + +L(fastskip): +#ifndef NOT_IN_libc + subq %r11, %rdx /* check for more */ + testq $-8, %rdx + jnz L(fastafter) +#endif + + andl $7, %edx /* check for left overs */ +#ifdef USE_AS_MEMPCPY + jnz L(1) + + movq %rdi, %rax +#else + movq RETVAL (%rsp), %rax + jnz L(1) + + rep +#endif + retq /* exit */ + +#ifndef NOT_IN_libc /* none of the algorithms below for RTLD */ + + .p2align 4 + +L(fastafter): + +/* Handle large blocks smaller than 1/2 L2. */ + +L(pretry): /* first 1/2 L2 */ + movq __x86_64_shared_cache_size_half (%rip), %r8 + cmpq %rdx, %r8 /* calculate the lesser of */ + cmovaq %rdx, %r8 /* remaining bytes and 1/2 L2 */ + +L(pre): /* 64-byte with prefetching */ + movq %r8, %rcx + andq $-64, %r8 + shrq $6, %rcx + jz L(preskip) + + movq %r14, SAVE0 (%rsp) + cfi_rel_offset (%r14, SAVE0) + movq %r13, SAVE1 (%rsp) + cfi_rel_offset (%r13, SAVE1) + movq %r12, SAVE2 (%rsp) + cfi_rel_offset (%r12, SAVE2) + movq %rbx, SAVE3 (%rsp) + cfi_rel_offset (%rbx, SAVE3) + + cmpl $0, __x86_64_prefetchw (%rip) + jz L(preloop) /* check if PREFETCHW OK */ + + .p2align 4 + +/* ... when PREFETCHW is available (less cache-probe traffic in MP systems). */ + +L(prewloop): /* cache-line in state M */ + decq %rcx + + movq (%rsi), %rax + movq 8 (%rsi), %rbx + movq 16 (%rsi), %r9 + movq 24 (%rsi), %r10 + movq 32 (%rsi), %r11 + movq 40 (%rsi), %r12 + movq 48 (%rsi), %r13 + movq 56 (%rsi), %r14 + + prefetcht0 0 + 896 (%rsi) + prefetcht0 64 + 896 (%rsi) + + movq %rax, (%rdi) + movq %rbx, 8 (%rdi) + movq %r9, 16 (%rdi) + movq %r10, 24 (%rdi) + movq %r11, 32 (%rdi) + movq %r12, 40 (%rdi) + movq %r13, 48 (%rdi) + movq %r14, 56 (%rdi) + + leaq 64 (%rsi), %rsi + leaq 64 (%rdi), %rdi + + jz L(prebail) + + decq %rcx + + movq (%rsi), %rax + movq 8 (%rsi), %rbx + movq 16 (%rsi), %r9 + movq 24 (%rsi), %r10 + movq 32 (%rsi), %r11 + movq 40 (%rsi), %r12 + movq 48 (%rsi), %r13 + movq 56 (%rsi), %r14 + + movq %rax, (%rdi) + movq %rbx, 8 (%rdi) + movq %r9, 16 (%rdi) + movq %r10, 24 (%rdi) + movq %r11, 32 (%rdi) + movq %r12, 40 (%rdi) + movq %r13, 48 (%rdi) + movq %r14, 56 (%rdi) + + prefetchw 896 - 64 (%rdi) + prefetchw 896 - 0 (%rdi) + + leaq 64 (%rsi), %rsi + leaq 64 (%rdi), %rdi + + jnz L(prewloop) + jmp L(prebail) + + .p2align 4 + +/* ... when PREFETCHW is not available. */ + +L(preloop): /* cache-line in state E */ + decq %rcx + + movq (%rsi), %rax + movq 8 (%rsi), %rbx + movq 16 (%rsi), %r9 + movq 24 (%rsi), %r10 + movq 32 (%rsi), %r11 + movq 40 (%rsi), %r12 + movq 48 (%rsi), %r13 + movq 56 (%rsi), %r14 + + prefetcht0 896 + 0 (%rsi) + prefetcht0 896 + 64 (%rsi) + + movq %rax, (%rdi) + movq %rbx, 8 (%rdi) + movq %r9, 16 (%rdi) + movq %r10, 24 (%rdi) + movq %r11, 32 (%rdi) + movq %r12, 40 (%rdi) + movq %r13, 48 (%rdi) + movq %r14, 56 (%rdi) + + leaq 64 (%rsi), %rsi + leaq 64 (%rdi), %rdi + + jz L(prebail) + + decq %rcx + + movq (%rsi), %rax + movq 8 (%rsi), %rbx + movq 16 (%rsi), %r9 + movq 24 (%rsi), %r10 + movq 32 (%rsi), %r11 + movq 40 (%rsi), %r12 + movq 48 (%rsi), %r13 + movq 56 (%rsi), %r14 + + prefetcht0 896 - 64 (%rdi) + prefetcht0 896 - 0 (%rdi) + + movq %rax, (%rdi) + movq %rbx, 8 (%rdi) + movq %r9, 16 (%rdi) + movq %r10, 24 (%rdi) + movq %r11, 32 (%rdi) + movq %r12, 40 (%rdi) + movq %r13, 48 (%rdi) + movq %r14, 56 (%rdi) + + leaq 64 (%rsi), %rsi + leaq 64 (%rdi), %rdi + + jnz L(preloop) + +L(prebail): + movq SAVE3 (%rsp), %rbx + cfi_restore (%rbx) + movq SAVE2 (%rsp), %r12 + cfi_restore (%r12) + movq SAVE1 (%rsp), %r13 + cfi_restore (%r13) + movq SAVE0 (%rsp), %r14 + cfi_restore (%r14) + +/* .p2align 4 */ + +L(preskip): + subq %r8, %rdx /* check for more */ + testq $-64, %rdx + jnz L(preafter) + + andl $63, %edx /* check for left overs */ +#ifdef USE_AS_MEMPCPY + jnz L(1) + + movq %rdi, %rax +#else + movq RETVAL (%rsp), %rax + jnz L(1) + + rep +#endif + retq /* exit */ + + .p2align 4 + +L(preafter): + +/* Loop to handle huge blocks. */ + +L(NTtry): + +L(NT): /* non-temporal 128-byte */ + movq %rdx, %rcx + shrq $7, %rcx + jz L(NTskip) + + movq %r14, SAVE0 (%rsp) + cfi_rel_offset (%r14, SAVE0) + movq %r13, SAVE1 (%rsp) + cfi_rel_offset (%r13, SAVE1) + movq %r12, SAVE2 (%rsp) + cfi_rel_offset (%r12, SAVE2) + + .p2align 4 + +L(NTloop): + prefetchnta 768 (%rsi) + prefetchnta 832 (%rsi) + + decq %rcx + + movq (%rsi), %rax + movq 8 (%rsi), %r8 + movq 16 (%rsi), %r9 + movq 24 (%rsi), %r10 + movq 32 (%rsi), %r11 + movq 40 (%rsi), %r12 + movq 48 (%rsi), %r13 + movq 56 (%rsi), %r14 + + movntiq %rax, (%rdi) + movntiq %r8, 8 (%rdi) + movntiq %r9, 16 (%rdi) + movntiq %r10, 24 (%rdi) + movntiq %r11, 32 (%rdi) + movntiq %r12, 40 (%rdi) + movntiq %r13, 48 (%rdi) + movntiq %r14, 56 (%rdi) + + movq 64 (%rsi), %rax + movq 72 (%rsi), %r8 + movq 80 (%rsi), %r9 + movq 88 (%rsi), %r10 + movq 96 (%rsi), %r11 + movq 104 (%rsi), %r12 + movq 112 (%rsi), %r13 + movq 120 (%rsi), %r14 + + movntiq %rax, 64 (%rdi) + movntiq %r8, 72 (%rdi) + movntiq %r9, 80 (%rdi) + movntiq %r10, 88 (%rdi) + movntiq %r11, 96 (%rdi) + movntiq %r12, 104 (%rdi) + movntiq %r13, 112 (%rdi) + movntiq %r14, 120 (%rdi) + + leaq 128 (%rsi), %rsi + leaq 128 (%rdi), %rdi + + jnz L(NTloop) + + sfence /* serialize memory stores */ + + movq SAVE2 (%rsp), %r12 + cfi_restore (%r12) + movq SAVE1 (%rsp), %r13 + cfi_restore (%r13) + movq SAVE0 (%rsp), %r14 + cfi_restore (%r14) + +L(NTskip): + andl $127, %edx /* check for left overs */ +#ifdef USE_AS_MEMPCPY + jnz L(1) + + movq %rdi, %rax +#else + movq RETVAL (%rsp), %rax + jnz L(1) + + rep #endif - ret + retq /* exit */ + +#endif /* !NOT_IN_libc */ + +END(memcpy) -END (BP_SYM (memcpy)) -#if !MEMPCPY_P +#ifndef USE_AS_MEMPCPY libc_hidden_builtin_def (memcpy) #endif diff --git a/libc/sysdeps/x86_64/mempcpy.S b/libc/sysdeps/x86_64/mempcpy.S index 4558a1699..5cb256e65 100644 --- a/libc/sysdeps/x86_64/mempcpy.S +++ b/libc/sysdeps/x86_64/mempcpy.S @@ -1,3 +1,4 @@ +#define USE_AS_MEMPCPY #define memcpy __mempcpy #define __memcpy_chk __mempcpy_chk #include <sysdeps/x86_64/memcpy.S> diff --git a/libc/version.h b/libc/version.h index d70070f2a..2fc4a7b8d 100644 --- a/libc/version.h +++ b/libc/version.h @@ -1,4 +1,4 @@ /* This file just defines the current version number of libc. */ -#define RELEASE "stable" -#define VERSION "2.6" +#define RELEASE "development" +#define VERSION "2.6.90" diff --git a/ports/ChangeLog.arm b/ports/ChangeLog.arm index ebad07a9a..e733cb6fc 100644 --- a/ports/ChangeLog.arm +++ b/ports/ChangeLog.arm @@ -1,3 +1,25 @@ +2007-05-23 Joseph Myers <joseph@codesourcery.com> + + * sysdeps/unix/sysv/linux/arm/kernel-features.h + (__ASSUME_SIGFRAME_V2): Define for 2.6.18 and later. + * sysdeps/unix/sysv/linux/arm/eabi/sigrestorer.S + (__default_sa_restorer): Rename to __default_sa_restorer_v1. + Don't define if __ASSUME_SIGFRAME_V2. + (__default_rt_sa_restorer): Rename to + __default_rt_sa_restorer_v1. Don't define if + __ASSUME_SIGFRAME_V2. + (__default_sa_restorer_v2, __default_rt_sa_restorer_v2): New. + * sysdeps/unix/sysv/linux/arm/nptl/Versions + (__default_sa_restorer_v1, __default_rt_sa_restorer_v1, + __default_sa_restorer_v2, __default_rt_sa_restorer_v2): Add to + GLIBC_PRIVATE. + * sysdeps/unix/sysv/linux/arm/sigaction.c [__ARM_EABI__] + (__default_sa_restorer_v1, __default_sa_restorer_v2, + __default_rt_sa_restorer_v1, __default_rt_sa_restorer_v2): + Declare. + (__default_sa_restorer, __default_rt_sa_restorer): Define as + macros depending on kernel version. + 2007-01-23 Daniel Jacobowitz <dan@codesourcery.com> * sysdeps/unix/sysv/linux/arm/sysdep.h (PTR_MANGLE, PTR_DEMANGLE): diff --git a/ports/ChangeLog.hppa b/ports/ChangeLog.hppa index 7d38ab0fd..3ee76d9de 100644 --- a/ports/ChangeLog.hppa +++ b/ports/ChangeLog.hppa @@ -1,3 +1,18 @@ +2007-05-17 Carlos O'Donell <carlos@systemhalted.org> + + * sysdeps/unix/sysv/linux/hppa/nptl/bits/semaphore.h + (SEM_VALUE_MAX): Remove. + +2007-05-17 Carlos O'Donell <carlos@systemhalted.org> + + * sysdeps/unix/sysv/linux/hppa/sysdep.h (PIC_REG_DEF): Define. + (PIC_REG_USE): Define. + (INLINE_SYSCALL): Use PIC_REG_DEF, PIC_REG_USE. + (INTERNAL_SYSCALL): Likewise. + (INTERNAL_SYSCALL_NCS): Likewise. + * sysdeps/unix/sysv/linux/hppa/sysdep.c (syscall): Use + PIC_REG_DEF, PIC_REG_USE. + 2007-05-01 Carlos O'Donell <carlos@systemhalted.org> * sysdeps/unix/sysv/linux/hppa/linuxthreads/bits/pthreadtypes.h diff --git a/ports/ChangeLog.mips b/ports/ChangeLog.mips index 159a4c247..34e25614f 100644 --- a/ports/ChangeLog.mips +++ b/ports/ChangeLog.mips @@ -1,3 +1,32 @@ +2007-05-24 Atsushi Nemoto <anemo@mba.ocn.ne.jp> + + * sysdeps/unix/sysv/linux/mips/mips32/posix_fadvise.c + (posix_fadvise): Fix high word of len argument. + +2007-05-23 Atsushi Nemoto <anemo@mba.ocn.ne.jp> + + * sysdeps/unix/sysv/linux/mips/mips32/posix_fadvise.c: New file. + * sysdeps/unix/sysv/linux/mips/mips32/posix_fadvise64.c: New file. + * sysdeps/unix/sysv/linux/mips/mips32/readahead.c: New file. + * sysdeps/unix/sysv/linux/mips/mips32/sync_file_range.c: New file. + * sysdeps/unix/sysv/linux/mips/mips64/n32/posix_fadvise64.c: New file. + * sysdeps/unix/sysv/linux/mips/mips64/n32/syscalls.list: New file. + +2007-05-23 Joseph Myers <joseph@codesourcery.com> + + * sysdeps/mips/mips64/n32/Implies: Add mips/mips64/soft-fp. + * sysdeps/mips/mips64/n64/Implies: Likewise. + * sysdeps/mips/mips64/soft-fp/Makefile: New. + * sysdeps/mips/mips64/soft-fp/e_sqrtl.c: New. + * sysdeps/mips/mips64/soft-fp/sfp-machine.h: Include <fenv.h> and + <fpu_control.h>. Use hardware exception and rounding mode + settings. + +2007-05-23 Richard Sandiford <rsandifo@nildram.co.uk> + + * sysdeps/mips/dl-machine.h (elf_machine_reloc): Change type of + r_info argument to ElfW(Addr). + 2007-02-01 Joseph Myers <joseph@codesourcery.com> * sysdeps/mips/bits/mathdef.h (float_t): Change to float. diff --git a/ports/ChangeLog.powerpc b/ports/ChangeLog.powerpc index 015c95c9b..1ea6746b3 100644 --- a/ports/ChangeLog.powerpc +++ b/ports/ChangeLog.powerpc @@ -1,3 +1,9 @@ +2007-05-23 Steven Munroe <sjmunroe@us.ibm.com> + + * sysdeps/powerpc/nofpu/feholdexcpt.c (feholdexcept): Disable + exceptions. Use the updated env in fesetenv(). + Add libm_hidden_def. + 2007-01-23 Steven Munroe <sjmunroe@us.ibm.com> [BZ #2749] diff --git a/ports/sysdeps/powerpc/nofpu/feholdexcpt.c b/ports/sysdeps/powerpc/nofpu/feholdexcpt.c index 786c691a4..ade9d19f4 100644 --- a/ports/sysdeps/powerpc/nofpu/feholdexcpt.c +++ b/ports/sysdeps/powerpc/nofpu/feholdexcpt.c @@ -1,6 +1,6 @@ /* Store current floating-point environment and clear exceptions (soft-float edition). - Copyright (C) 2002 Free Software Foundation, Inc. + Copyright (C) 2002, 2007 Free Software Foundation, Inc. Contributed by Aldy Hernandez <aldyh@redhat.com>, 2002. This file is part of the GNU C Library. @@ -33,11 +33,12 @@ feholdexcept (fenv_t *envp) u.fenv = *envp; /* Clear everything except the rounding mode. */ u.l[0] &= 0x3; - - /* ?? Should we clear the disabled exceptions as well ?? */ + /* Disable exceptions */ + u.l[1] = FE_ALL_EXCEPT; /* Put the new state in effect. */ - fesetenv (envp); + fesetenv (&u.fenv); return 0; } +libm_hidden_def (feholdexcept) diff --git a/ports/sysdeps/unix/sysv/linux/hppa/nptl/bits/semaphore.h b/ports/sysdeps/unix/sysv/linux/hppa/nptl/bits/semaphore.h index 3d274eea2..270f3332c 100644 --- a/ports/sysdeps/unix/sysv/linux/hppa/nptl/bits/semaphore.h +++ b/ports/sysdeps/unix/sysv/linux/hppa/nptl/bits/semaphore.h @@ -20,17 +20,11 @@ # error "Never use <bits/semaphore.h> directly; include <semaphore.h> instead." #endif - #define __SIZEOF_SEM_T 16 - /* 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)) - - typedef union { char __size[__SIZEOF_SEM_T]; diff --git a/ports/sysdeps/unix/sysv/linux/hppa/sysdep.c b/ports/sysdeps/unix/sysv/linux/hppa/sysdep.c index 8637c513d..4a0bd2183 100644 --- a/ports/sysdeps/unix/sysv/linux/hppa/sysdep.c +++ b/ports/sysdeps/unix/sysv/linux/hppa/sysdep.c @@ -1,4 +1,5 @@ -/* Copyright (C) 1997, 1998, 2001, 2003 Free Software Foundation, Inc. +/* Copyright (C) 1997, 1998, 2001, 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 @@ -58,13 +59,14 @@ syscall (long int __sysno, ...) { register unsigned long int __res asm("r28"); + PIC_REG_DEF LOAD_ARGS_6 (arg0, arg1, arg2, arg3, arg4, arg5) asm volatile (SAVE_ASM_PIC " ble 0x100(%%sr2, %%r0) \n" " copy %1, %%r20 \n" LOAD_ASM_PIC : "=r" (__res) - : "r" (__sysno) ASM_ARGS_6 + : "r" (__sysno) PIC_REG_USE ASM_ARGS_6 : "memory", CALL_CLOB_REGS CLOB_ARGS_6); __sys_res = __res; } diff --git a/ports/sysdeps/unix/sysv/linux/hppa/sysdep.h b/ports/sysdeps/unix/sysv/linux/hppa/sysdep.h index 69ed7002c..96632a1c4 100644 --- a/ports/sysdeps/unix/sysv/linux/hppa/sysdep.h +++ b/ports/sysdeps/unix/sysv/linux/hppa/sysdep.h @@ -1,5 +1,6 @@ /* Assembler macros for PA-RISC. - Copyright (C) 1999, 2001, 2002, 2003 Free Software Foundation, Inc. + Copyright (C) 1999, 2001, 2002, 2003, 2007 + Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper, <drepper@cygnus.com>, August 1999. Linux/PA-RISC changes by Philipp Rumpf, <prumpf@tux.org>, March 2000. @@ -40,7 +41,9 @@ # define TREG_ASM "%r4" /* Cant clobber r3, it holds framemarker */ # define SAVE_ASM_PIC " copy %%r19, %" TREG_ASM "\n" # define LOAD_ASM_PIC " copy %" TREG_ASM ", %%r19\n" -# define USING_TREG TREG_ASM, +# define CLOB_TREG TREG_ASM , +# define PIC_REG_DEF register unsigned long __r19 asm("r19"); +# define PIC_REG_USE , "r" (__r19) #else # define TREG %r3 # define SAVE_PIC(SREG) nop ASM_LINE_SEP @@ -49,7 +52,9 @@ # define TREG_ASM # define SAVE_ASM_PIC "nop \n" # define LOAD_ASM_PIC "nop \n" -# define USING_TREG +# define CLOB_TREG +# define PIC_REG_DEF +# define PIC_REG_USE #endif #ifdef __ASSEMBLER__ @@ -344,7 +349,7 @@ L(pre_end): ASM_LINE_SEP \ TREG is clobbered and use that register to save/restore r19 across the syscall. */ -#define CALL_CLOB_REGS "%r1", "%r2", USING_TREG \ +#define CALL_CLOB_REGS "%r1", "%r2", CLOB_TREG \ "%r20", "%r29", "%r31" #undef INLINE_SYSCALL @@ -353,6 +358,7 @@ L(pre_end): ASM_LINE_SEP \ long __sys_res; \ { \ register unsigned long __res asm("r28"); \ + PIC_REG_DEF \ LOAD_ARGS_##nr(args) \ /* FIXME: HACK save/load r19 around syscall */ \ asm volatile( \ @@ -361,7 +367,7 @@ L(pre_end): ASM_LINE_SEP \ " ldi %1, %%r20\n" \ LOAD_ASM_PIC \ : "=r" (__res) \ - : "i" (SYS_ify(name)) ASM_ARGS_##nr \ + : "i" (SYS_ify(name)) PIC_REG_USE ASM_ARGS_##nr \ : "memory", CALL_CLOB_REGS CLOB_ARGS_##nr \ ); \ __sys_res = (long)__res; \ @@ -398,6 +404,7 @@ L(pre_end): ASM_LINE_SEP \ long __sys_res; \ { \ register unsigned long __res asm("r28"); \ + PIC_REG_DEF \ LOAD_ARGS_##nr(args) \ /* FIXME: HACK save/load r19 around syscall */ \ asm volatile( \ @@ -406,7 +413,7 @@ L(pre_end): ASM_LINE_SEP \ " ldi %1, %%r20\n" \ LOAD_ASM_PIC \ : "=r" (__res) \ - : "i" (SYS_ify(name)) ASM_ARGS_##nr \ + : "i" (SYS_ify(name)) PIC_REG_USE ASM_ARGS_##nr \ : "memory", CALL_CLOB_REGS CLOB_ARGS_##nr \ ); \ __sys_res = (long)__res; \ @@ -422,6 +429,7 @@ L(pre_end): ASM_LINE_SEP \ long __sys_res; \ { \ register unsigned long __res asm("r28"); \ + PIC_REG_DEF \ LOAD_ARGS_##nr(args) \ /* FIXME: HACK save/load r19 around syscall */ \ asm volatile( \ @@ -430,7 +438,7 @@ L(pre_end): ASM_LINE_SEP \ " copy %1, %%r20\n" \ LOAD_ASM_PIC \ : "=r" (__res) \ - : "r" (name) ASM_ARGS_##nr \ + : "r" (name) PIC_REG_USE ASM_ARGS_##nr \ : "memory", CALL_CLOB_REGS CLOB_ARGS_##nr \ ); \ __sys_res = (long)__res; \ diff --git a/ports/sysdeps/unix/sysv/linux/mips/mips32/posix_fadvise.c b/ports/sysdeps/unix/sysv/linux/mips/mips32/posix_fadvise.c new file mode 100644 index 000000000..04c952d2f --- /dev/null +++ b/ports/sysdeps/unix/sysv/linux/mips/mips32/posix_fadvise.c @@ -0,0 +1,42 @@ +/* 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 <errno.h> +#include <fcntl.h> +#include <sysdep.h> + +/* Advice the system about the expected behaviour of the application with + respect to the file associated with FD. */ + +int +posix_fadvise (int fd, off_t offset, off_t len, int advise) +{ +/* MIPS kernel only has NR_fadvise64 which acts as NR_fadvise64_64 */ +#ifdef __NR_fadvise64 + INTERNAL_SYSCALL_DECL (err); + int ret = INTERNAL_SYSCALL (fadvise64, err, 7, fd, 0, + __LONG_LONG_PAIR (offset >> 31, offset), + __LONG_LONG_PAIR (len >> 31, len), + advise); + if (INTERNAL_SYSCALL_ERROR_P (ret, err)) + return INTERNAL_SYSCALL_ERRNO (ret, err); + return 0; +#else + return ENOSYS; +#endif +} diff --git a/ports/sysdeps/unix/sysv/linux/mips/mips32/posix_fadvise64.c b/ports/sysdeps/unix/sysv/linux/mips/mips32/posix_fadvise64.c new file mode 100644 index 000000000..715d37e45 --- /dev/null +++ b/ports/sysdeps/unix/sysv/linux/mips/mips32/posix_fadvise64.c @@ -0,0 +1,61 @@ +/* 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 <errno.h> +#include <fcntl.h> +#include <sysdep.h> + +/* Advice the system about the expected behaviour of the application with + respect to the file associated with FD. */ + +int +__posix_fadvise64_l64 (int fd, off64_t offset, off64_t len, int advise) +{ +/* MIPS kernel only has NR_fadvise64 which acts as NR_fadvise64_64 */ +#ifdef __NR_fadvise64 + INTERNAL_SYSCALL_DECL (err); + 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), + advise); + if (INTERNAL_SYSCALL_ERROR_P (ret, err)) + return INTERNAL_SYSCALL_ERRNO (ret, err); + return 0; +#else + return ENOSYS; +#endif +} + +#include <shlib-compat.h> + +#if SHLIB_COMPAT(libc, GLIBC_2_2, GLIBC_2_3_3) + +int +attribute_compat_text_section +__posix_fadvise64_l32 (int fd, off64_t offset, size_t len, int advise) +{ + return __posix_fadvise64_l64 (fd, offset, len, advise); +} + +versioned_symbol (libc, __posix_fadvise64_l64, posix_fadvise64, GLIBC_2_3_3); +compat_symbol (libc, __posix_fadvise64_l32, posix_fadvise64, GLIBC_2_2); +#else +strong_alias (__posix_fadvise64_l64, posix_fadvise64); +#endif diff --git a/ports/sysdeps/unix/sysv/linux/mips/mips32/readahead.c b/ports/sysdeps/unix/sysv/linux/mips/mips32/readahead.c new file mode 100644 index 000000000..b5b967ce9 --- /dev/null +++ b/ports/sysdeps/unix/sysv/linux/mips/mips32/readahead.c @@ -0,0 +1 @@ +#include <sysdeps/unix/sysv/linux/arm/eabi/readahead.c> diff --git a/ports/sysdeps/unix/sysv/linux/mips/mips32/sync_file_range.c b/ports/sysdeps/unix/sysv/linux/mips/mips32/sync_file_range.c new file mode 100644 index 000000000..13a21b0da --- /dev/null +++ b/ports/sysdeps/unix/sysv/linux/mips/mips32/sync_file_range.c @@ -0,0 +1,47 @@ +/* Selective file content synch'ing. + 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. */ + +#include <errno.h> +#include <fcntl.h> +#include <sys/types.h> + +#include <sysdep.h> +#include <sys/syscall.h> + + +#ifdef __NR_sync_file_range +int +sync_file_range (int fd, __off64_t from, __off64_t to, unsigned int flags) +{ + return INLINE_SYSCALL (sync_file_range, 7, fd, 0, + __LONG_LONG_PAIR ((long) (from >> 32), (long) from), + __LONG_LONG_PAIR ((long) (to >> 32), (long) to), + flags); +} +#else +int +sync_file_range (int fd, __off64_t from, __off64_t to, unsigned int flags) +{ + __set_errno (ENOSYS); + return -1; +} +stub_warning (sync_file_range) + +# include <stub-tag.h> +#endif diff --git a/ports/sysdeps/unix/sysv/linux/mips/mips64/n32/posix_fadvise64.c b/ports/sysdeps/unix/sysv/linux/mips/mips64/n32/posix_fadvise64.c new file mode 100644 index 000000000..40bafdbac --- /dev/null +++ b/ports/sysdeps/unix/sysv/linux/mips/mips64/n32/posix_fadvise64.c @@ -0,0 +1,56 @@ +/* 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 <errno.h> +#include <fcntl.h> +#include <sysdep.h> + +/* Advice the system about the expected behaviour of the application with + respect to the file associated with FD. */ + +int +__posix_fadvise64_l64 (int fd, off64_t offset, off64_t len, int advise) +{ +/* MIPS kernel only has NR_fadvise64 which acts as NR_fadvise64_64 */ +#ifdef __NR_fadvise64 + INTERNAL_SYSCALL_DECL (err); + int ret = INTERNAL_SYSCALL (fadvise64, err, 4, fd, offset, len, advise); + if (INTERNAL_SYSCALL_ERROR_P (ret, err)) + return INTERNAL_SYSCALL_ERRNO (ret, err); + return 0; +#else + return ENOSYS; +#endif +} + +#include <shlib-compat.h> + +#if SHLIB_COMPAT(libc, GLIBC_2_2, GLIBC_2_3_3) + +int +attribute_compat_text_section +__posix_fadvise64_l32 (int fd, off64_t offset, size_t len, int advise) +{ + return __posix_fadvise64_l64 (fd, offset, len, advise); +} + +versioned_symbol (libc, __posix_fadvise64_l64, posix_fadvise64, GLIBC_2_3_3); +compat_symbol (libc, __posix_fadvise64_l32, posix_fadvise64, GLIBC_2_2); +#else +strong_alias (__posix_fadvise64_l64, posix_fadvise64); +#endif diff --git a/ports/sysdeps/unix/sysv/linux/mips/mips64/n32/syscalls.list b/ports/sysdeps/unix/sysv/linux/mips/mips64/n32/syscalls.list new file mode 100644 index 000000000..babdba0ca --- /dev/null +++ b/ports/sysdeps/unix/sysv/linux/mips/mips64/n32/syscalls.list @@ -0,0 +1,5 @@ +# File name Caller Syscall name # args Strong name Weak names + +readahead - readahead i:iii __readahead readahead +sync_file_range - sync_file_range i:iiii sync_file_range +posix_fadvise - fadvise64 i:iiii posix_fadvise |