aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog142
-rw-r--r--elf/Makefile12
-rw-r--r--elf/dl-close.c55
-rw-r--r--elf/rtld-Rules11
-rw-r--r--elf/unload6.c30
-rw-r--r--elf/unload6mod1.c16
-rw-r--r--elf/unload6mod2.c23
-rw-r--r--elf/unload6mod3.c23
-rw-r--r--fedora/branch.mk4
-rw-r--r--linuxthreads/ChangeLog5
-rw-r--r--linuxthreads/sysdeps/pthread/getcpuclockid.c69
-rw-r--r--localedata/ChangeLog7
-rw-r--r--localedata/locales/fa_IR211
-rw-r--r--malloc/Makefile7
-rw-r--r--malloc/hooks.c45
-rw-r--r--malloc/tst-mcheck.c91
-rw-r--r--nptl/ChangeLog22
-rw-r--r--nptl/Makefile4
-rw-r--r--nptl/old_pthread_cond_init.c12
-rw-r--r--nptl/pthread_cond_init.c4
-rw-r--r--nptl/sysdeps/i386/tls.h2
-rw-r--r--nptl/sysdeps/unix/sysv/linux/pthread_getcpuclockid.c111
-rw-r--r--nptl/sysdeps/unix/sysv/linux/timer_create.c13
-rw-r--r--nptl/tst-cancel17.c4
-rw-r--r--posix/unistd.h4
-rw-r--r--rt/Makefile4
-rw-r--r--rt/tst-cpuclock1.c307
-rw-r--r--rt/tst-cpuclock2.c332
-rw-r--r--rt/tst-cputimer1.c68
-rw-r--r--rt/tst-cputimer2.c83
-rw-r--r--rt/tst-cputimer3.c130
-rw-r--r--stdio-common/vfscanf.c19
-rw-r--r--stdlib/canonicalize.c7
-rw-r--r--stdlib/test-canon.c18
-rw-r--r--sunrpc/xdr.c4
-rw-r--r--sysdeps/posix/clock_getres.c111
-rw-r--r--sysdeps/sparc/sparc32/elf/start.S6
-rw-r--r--sysdeps/sparc/sparc64/elf/start.S6
-rw-r--r--sysdeps/unix/clock_gettime.c117
-rw-r--r--sysdeps/unix/sysv/linux/clock_getcpuclockid.c103
-rw-r--r--sysdeps/unix/sysv/linux/clock_getres.c175
-rw-r--r--sysdeps/unix/sysv/linux/clock_gettime.c176
-rw-r--r--sysdeps/unix/sysv/linux/clock_nanosleep.c21
-rw-r--r--sysdeps/unix/sysv/linux/ia64/clock_getcpuclockid.c23
-rw-r--r--sysdeps/unix/sysv/linux/kernel-posix-cpu-timers.h18
-rw-r--r--sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep.h2
-rw-r--r--time/Makefile4
-rw-r--r--time/strptime_l.c36
-rw-r--r--time/tst-strptime2.c59
-rw-r--r--timezone/Makefile30
50 files changed, 2453 insertions, 333 deletions
diff --git a/ChangeLog b/ChangeLog
index 2a1358023e..3179b70d25 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,145 @@
+2005-04-27 Roland McGrath <roland@redhat.com>
+
+ [BZ #877]
+ * posix/unistd.h: Remove __nonnull from acct decl.
+
+ * rt/tst-cpuclock1.c: New file.
+ * rt/tst-cpuclock2.c: New file.
+ * rt/tst-cputimer1.c: New file.
+ * rt/tst-cputimer2.c: New file.
+ * rt/tst-cputimer3.c: New file.
+ * rt/Makefile (tests): Add them.
+
+ * sysdeps/unix/sysv/linux/kernel-posix-cpu-timers.h: New file.
+ * sysdeps/unix/sysv/linux/clock_getcpuclockid.c: New file.
+ * sysdeps/unix/sysv/linux/ia64/clock_getcpuclockid.c
+ (HAS_CPUCLOCK): New macro.
+ (clock_getcpuclockid): Function removed.
+ #include the new linux file to define it instead.
+ * sysdeps/unix/clock_gettime.c [HP_TIMING_AVAIL] (hp_timing_gettime):
+ New function, broken out of ...
+ (clock_gettime) [HP_TIMING_AVAIL]: ... here. Call it.
+ (realtime_gettime): New function, broken out of ...
+ (clock_gettime) [! HANDLED_REALTIME]: ... here. Call it.
+ (clock_gettime) [SYSDEP_GETTIME_CPU]: Use new macro in default case.
+ * sysdeps/unix/sysv/linux/clock_gettime.c (SYSCALL_GETTIME): New macro.
+ (SYSDEP_GETTIME_CPUTIME): New macro.
+ (SYSDEP_GETTIME): Use both.
+ [! __ASSUME_POSIX_TIMERS] (maybe_syscall_gettime): New function, broken
+ out of ...
+ (SYSDEP_GETTIME): ... here. Use it.
+ [__NR_clock_gettime] (HANDLED_CPUTIME): Define it.
+ (SYSDEP_GETTIME_CPUTIME): New macro. Handle CPU timers by trying
+ kernel support and falling back to hp-timing code.
+ * sysdeps/posix/clock_getres.c
+ [HP_TIMING_AVAIL] (hp_timing_getres): New function, broken out of ...
+ (clock_getres) [HP_TIMING_AVAIL]: ... here. Call it.
+ (realtime_getres): New function, broken out of ...
+ (clock_getres) [! HANDLED_REALTIME]: ... here. Call it.
+ (clock_getres) [SYSDEP_GETRES_CPU]: Use new macro in default case.
+ * sysdeps/unix/sysv/linux/clock_getres.c (SYSCALL_GETRES): New macro.
+ (SYSDEP_GETRES_CPUTIME): New macro.
+ (SYSDEP_GETRES): Use both.
+ [! __ASSUME_POSIX_TIMERS] (maybe_syscall_getres): New function, broken
+ out of ...
+ (SYSDEP_GETRES): ... here. Use it.
+ [__NR_clock_getres] (HANDLED_CPUTIME): Define it.
+ (SYSDEP_GETRES_CPUTIME): New macro. Handle CPU timers by trying
+ kernel support and falling back to hp-timing code.
+ * sysdeps/unix/sysv/linux/clock_nanosleep.c: Handle
+ CLOCK_PROCESS_CPUTIME_ID and CLOCK_PROCESS_THREAD_ID specially,
+ translating to the kernel clockid_t for our own process/thread clock.
+
+2005-04-27 Ulrich Drepper <drepper@redhat.com>
+
+ * stdlib/test-canon.c: Make doesExist a directory and add more tests
+ for the new error case.
+
+2004-06-02 Dmitry V. Levin <ldv@altlinux.org>
+ Ranjani Murthy <ranmur@gmail.com>
+
+ * stdlib/canonicalize.c (__realpath): Change realpath(3) to
+ return NULL and set errno to ENOTDIR for such pathnames like
+ "/path/to/existing-non-directory/".
+
+2005-04-26 Ulrich Drepper <drepper@redhat.com>
+
+ * time/strptime_l.c (__strptime_internal): Handle 'z' to set
+ tm_gmtoff.
+ * time/Makefile (tests): Add tst-strptime2.
+ * time/tst-strptime2.c: New file.
+
+2005-04-26 Jakub Jelinek <jakub@redhat.com>
+
+ * elf/dl-close.c: Include stddef.h.
+ (_dl_close): If called recursively, just remember GC needs to be rerun
+ and decrease l_direct_opencount. Avoid GC if l_direct_opencount
+ decreased to 1. Rerun GC at the end if any destructor unloaded some
+ additional libraries.
+ * elf/Makefile: Add rules to build and run unload6 test.
+ * elf/unload6.c: New test.
+ * elf/unload6mod1.c: New file.
+ * elf/unload6mod2.c: New file.
+ * elf/unload6mod3.c: New file.
+
+ * malloc/hooks.c (mem2chunk_check): Add magic_p argument, set *magic_p
+ if magic_p is not NULL.
+ (top_check): Invoke MALLOC_FAILURE_ACTION if MORECORE failed.
+ (malloc_check): Fail if sz == -1.
+ (free_check): Adjust mem2chunk_check caller.
+ (realloc_check): Likewise. Fail if bytes == -1. If bytes == 0 and
+ oldmem != NULL, call free_check and return NULL. If reallocating
+ and returning NULL, invert magic byte again to make oldmem valid
+ region for further checking.
+ (memalign_check): Fail if bytes == -1.
+ * malloc/Makefile: Add rules to build and run tst-mcheck.
+ * malloc/tst-mcheck.c: New test.
+
+2005-04-26 Ulrich Drepper <drepper@redhat.com>
+
+ * stdio-common/vfscanf.c: Correctly account for characters of
+ decimal points right after +-.
+
+2005-04-26 Roland McGrath <roland@redhat.com>
+
+ * elf/rtld-Rules (rtld-all): Test ifndef rtld-modules instead of
+ ifeq ($(subdir),elf) to distinguish main driver from subdir runs.
+
+2005-04-25 Roland McGrath <roland@redhat.com>
+
+ * sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep.h
+ (INTERNAL_SYSCALL_ERROR_P): Fix typo in last change.
+
+ * sunrpc/xdr.c (xdr_u_int): Use `long' for L and cast where needed.
+
+ * elf/dl-load.c: Revert last change.
+
+2005-04-24 Ulrich Drepper <drepper@redhat.com>
+
+ * stdio-common/vfscanf.c: Fix parsing of decimal point after +-.
+ Patch by Hamed Malek <hamed@bamdad.org>.
+
+2005-04-21 Roland McGrath <roland@redhat.com>
+
+ * elf/dl-load.c (_dl_map_object_from_fd): Don't use MAP_DENYWRITE,
+ since Linux ignores it in user mmap calls.
+
+2005-04-17 David S. Miller <davem@davemloft.net>
+
+ * sysdeps/sparc/sparc32/elf/start.S: Define __data_start.
+ * sysdeps/sparc/sparc64/elf/start.S: Likewise.
+
+2005-04-15 Roland McGrath <roland@redhat.com>
+
+ * timezone/Makefile (zic-deps): New variable.
+ ($(testdata)/America/New_York): Use it instead of explicit deps.
+ ($(testdata)/Etc/UTC, $(testdata)/Australia/Melbourne): Likewise.
+ ($(testdata)/America/Sao_Paulo, $(testdata)/Asia/Tokyo): Likewise.
+ (%/UTC %/Universal): New pattern rule, replaces ...
+ ($(testdata)/UTC, $(testdata)/Universal): ... these removed targets.
+ ($(testdata)/%/Berlin $(testdata)/%/London): New pattern rule.
+ ($(testdata)/Europe/London, $(testdata)/Europe/Berlin): Removed.
+
2005-04-14 Roland McGrath <roland@redhat.com>
* MakeTAGS ($P/$(domain).pot): Depend on distinfo file as well.
diff --git a/elf/Makefile b/elf/Makefile
index c034b2ba6e..d988baca3b 100644
--- a/elf/Makefile
+++ b/elf/Makefile
@@ -86,7 +86,7 @@ distribute := rtld-Rules \
tst-deep1mod1.c tst-deep1mod2.c tst-deep1mod3.c \
unload3mod1.c unload3mod2.c unload3mod3.c unload3mod4.c \
unload4mod1.c unload4mod2.c unload4mod3.c unload4mod4.c \
- tst-auditmod1.c \
+ unload6mod1.c unload6mod2.c unload6mod3.c tst-auditmod1.c \
order2mod1.c order2mod2.c order2mod3.c order2mod4.c
CFLAGS-dl-runtime.c = -fexceptions -fasynchronous-unwind-tables
@@ -162,7 +162,7 @@ tests += loadtest restest1 preloadtest loadfail multiload origtest resolvfail \
tst-tls10 tst-tls11 tst-tls12 tst-tls13 tst-tls14 tst-tls15 tst-align \
tst-align2 $(tests-execstack-$(have-z-execstack)) tst-dlmodcount \
tst-dlopenrpath tst-deep1 tst-dlmopen1 tst-dlmopen2 tst-dlmopen3 \
- unload3 unload4 unload5 tst-audit1 tst-global1 order2
+ unload3 unload4 unload5 unload6 tst-audit1 tst-global1 order2
# reldep9
test-srcs = tst-pathopt
tests-vis-yes = vismain
@@ -201,6 +201,7 @@ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \
tst-dlmopen1mod tst-auditmod1 \
unload3mod1 unload3mod2 unload3mod3 unload3mod4 \
unload4mod1 unload4mod2 unload4mod3 unload4mod4 \
+ unload6mod1 unload6mod2 unload6mod3 \
order2mod1 order2mod2 order2mod3 order2mod4
ifeq (yes,$(have-initfini-array))
modules-names += tst-array2dep
@@ -438,6 +439,9 @@ $(objpfx)unload3mod2.so: $(objpfx)unload3mod3.so
$(objpfx)unload3mod3.so: $(objpfx)unload3mod4.so
$(objpfx)unload4mod1.so: $(objpfx)unload4mod2.so $(objpfx)unload4mod3.so
$(objpfx)unload4mod2.so: $(objpfx)unload4mod4.so $(objpfx)unload4mod3.so
+$(objpfx)unload6mod1.so: $(libdl)
+$(objpfx)unload6mod2.so: $(libdl)
+$(objpfx)unload6mod3.so: $(libdl)
LDFLAGS-tst-tlsmod5.so = -nostdlib
LDFLAGS-tst-tlsmod6.so = -nostdlib
@@ -710,6 +714,10 @@ $(objpfx)unload5: $(libdl)
$(objpfx)unload5.out: $(objpfx)unload3mod1.so $(objpfx)unload3mod2.so \
$(objpfx)unload3mod3.so $(objpfx)unload3mod4.so
+$(objpfx)unload6: $(libdl)
+$(objpfx)unload6.out: $(objpfx)unload6mod1.so $(objpfx)unload6mod2.so \
+ $(objpfx)unload6mod3.so
+
ifdef libdl
$(objpfx)tst-tls9-static: $(common-objpfx)dlfcn/libdl.a
$(objpfx)tst-tls9-static.out: $(objpfx)tst-tlsmod5.so $(objpfx)tst-tlsmod6.so
diff --git a/elf/dl-close.c b/elf/dl-close.c
index cd4fa7cfbe..754dd678fe 100644
--- a/elf/dl-close.c
+++ b/elf/dl-close.c
@@ -20,6 +20,7 @@
#include <assert.h>
#include <dlfcn.h>
#include <libintl.h>
+#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -105,10 +106,6 @@ _dl_close (void *_map)
struct link_map *map = _map;
Lmid_t ns = map->l_ns;
unsigned int i;
-#ifdef USE_TLS
- bool any_tls = false;
-#endif
-
/* First see whether we can remove the object at all. */
if (__builtin_expect (map->l_flags_1 & DF_1_NODELETE, 0)
&& map->l_init_called)
@@ -124,9 +121,17 @@ _dl_close (void *_map)
/* One less direct use. */
--map->l_direct_opencount;
- /* Decrement the reference count. */
- if (map->l_direct_opencount > 1 || map->l_type != lt_loaded)
+ /* If _dl_close is called recursively (some destructor call dlclose),
+ just record that the parent _dl_close will need to do garbage collection
+ again and return. */
+ static enum { not_pending, pending, rerun } dl_close_state;
+
+ if (map->l_direct_opencount > 0 || map->l_type != lt_loaded
+ || dl_close_state != not_pending)
{
+ if (map->l_direct_opencount == 0 && map->l_type == lt_loaded)
+ dl_close_state = rerun;
+
/* There are still references to this object. Do nothing more. */
if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_FILES, 0))
_dl_debug_printf ("\nclosing file=%s; direct_opencount=%u\n",
@@ -136,12 +141,18 @@ _dl_close (void *_map)
return;
}
+ retry:
+ dl_close_state = pending;
+
+#ifdef USE_TLS
+ bool any_tls = false;
+#endif
const unsigned int nloaded = GL(dl_ns)[ns]._ns_nloaded;
char used[nloaded];
char done[nloaded];
struct link_map *maps[nloaded];
- /* Run over the list and assign indeces to the link maps and enter
+ /* Run over the list and assign indexes to the link maps and enter
them into the MAPS array. */
int idx = 0;
for (struct link_map *l = GL(dl_ns)[ns]._ns_loaded; l != NULL; l = l->l_next)
@@ -302,7 +313,7 @@ _dl_close (void *_map)
if (imap->l_searchlist.r_list == NULL
&& imap->l_initfini != NULL)
{
- /* The object is still used. But the object we are
+ /* The object is still used. But one of the objects we are
unloading right now is responsible for loading it. If
the current object does not have it's own scope yet we
have to create one. This has to be done before running
@@ -318,15 +329,27 @@ _dl_close (void *_map)
imap->l_searchlist.r_nlist = cnt;
for (cnt = 0; imap->l_scope[cnt] != NULL; ++cnt)
- if (imap->l_scope[cnt] == &map->l_searchlist)
+ /* This relies on l_scope[] entries being always set either
+ to its own l_symbolic_searchlist address, or some other map's
+ l_searchlist address. */
+ if (imap->l_scope[cnt] != &imap->l_symbolic_searchlist)
{
- imap->l_scope[cnt] = &imap->l_searchlist;
- break;
+ struct link_map *tmap;
+
+ tmap = (struct link_map *) ((char *) imap->l_scope[cnt]
+ - offsetof (struct link_map,
+ l_searchlist));
+ assert (tmap->l_ns == ns);
+ if (tmap->l_idx != -1)
+ {
+ imap->l_scope[cnt] = &imap->l_searchlist;
+ break;
+ }
}
}
/* The loader is gone, so mark the object as not having one.
- Note: l_idx == -1 -> object will be removed. */
+ Note: l_idx != -1 -> object will be removed. */
if (imap->l_loader != NULL && imap->l_loader->l_idx != -1)
imap->l_loader = NULL;
@@ -583,8 +606,12 @@ _dl_close (void *_map)
r->r_state = RT_CONSISTENT;
_dl_debug_state ();
- /* Release the lock. */
+ /* Recheck if we need to retry, release the lock. */
out:
+ if (dl_close_state == rerun)
+ goto retry;
+
+ dl_close_state = not_pending;
__rtld_lock_unlock_recursive (GL(dl_load_lock));
}
@@ -654,7 +681,7 @@ libc_freeres_fn (free_mem)
free_slotinfo (&GL(dl_tls_dtv_slotinfo_list));
else
# endif
- /* The first element of the list does not have to be deallocated.
+ /* The first element of the list does not have to be deallocated.
It was allocated in the dynamic linker (i.e., with a different
malloc), and in the static library it's in .bss space. */
free_slotinfo (&GL(dl_tls_dtv_slotinfo_list)->next);
diff --git a/elf/rtld-Rules b/elf/rtld-Rules
index ac96f728d9..61143b180c 100644
--- a/elf/rtld-Rules
+++ b/elf/rtld-Rules
@@ -1,6 +1,6 @@
# Subroutine makefile for compiling libc modules linked into dynamic linker.
-# Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+# Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc.
# This file is part of the GNU C Library.
# The GNU C Library is free software; you can redistribute it and/or
@@ -28,7 +28,14 @@
rtld-all:
# When run from the elf/Makefile to build rtld-libc.a, $(subdir) is elf.
-ifeq ($(subdir),elf)
+ifneq ($(subdir),elf)
+ifndef rtld-modules
+error rtld-modules not set
+endif
+endif
+
+ifndef rtld-modules
+# Running to build rtld-libc.a, driving runs of $(rtld-subdir-make), below.
ifndef rtld-subdirs
error This makefile is a subroutine of elf/Makefile not to be used directly
diff --git a/elf/unload6.c b/elf/unload6.c
new file mode 100644
index 0000000000..1efc7eb841
--- /dev/null
+++ b/elf/unload6.c
@@ -0,0 +1,30 @@
+#include <dlfcn.h>
+#include <stdio.h>
+
+int
+main (void)
+{
+ void *h = dlopen ("unload6mod1.so", RTLD_LAZY);
+ if (h == NULL)
+ {
+ puts ("dlopen unload6mod1.so failed");
+ return 1;
+ }
+
+ int (*fn) (int);
+ fn = dlsym (h, "foo");
+ if (fn == NULL)
+ {
+ puts ("dlsym failed");
+ return 1;
+ }
+
+ int val = fn (16);
+ if (val != 24)
+ {
+ printf ("foo returned %d != 24\n", val);
+ return 1;
+ }
+
+ return 0;
+}
diff --git a/elf/unload6mod1.c b/elf/unload6mod1.c
new file mode 100644
index 0000000000..24f2e5a19a
--- /dev/null
+++ b/elf/unload6mod1.c
@@ -0,0 +1,16 @@
+#include <dlfcn.h>
+#include <stdio.h>
+
+int
+foo (int i)
+{
+ void *h = dlopen ("unload6mod2.so", RTLD_LAZY);
+ if (h == NULL)
+ {
+ puts ("dlopen unload6mod2.so failed");
+ return 1;
+ }
+
+ dlclose (h);
+ return i + 8;
+}
diff --git a/elf/unload6mod2.c b/elf/unload6mod2.c
new file mode 100644
index 0000000000..980efa4b0e
--- /dev/null
+++ b/elf/unload6mod2.c
@@ -0,0 +1,23 @@
+#include <dlfcn.h>
+#include <stdio.h>
+#include <unistd.h>
+
+static void *h;
+
+static void __attribute__((constructor))
+mod2init (void)
+{
+ h = dlopen ("unload6mod3.so", RTLD_LAZY);
+ if (h == NULL)
+ {
+ puts ("dlopen unload6mod3.so failed");
+ fflush (stdout);
+ _exit (1);
+ }
+}
+
+static void __attribute__((destructor))
+mod2fini (void)
+{
+ dlclose (h);
+}
diff --git a/elf/unload6mod3.c b/elf/unload6mod3.c
new file mode 100644
index 0000000000..7b29e1d626
--- /dev/null
+++ b/elf/unload6mod3.c
@@ -0,0 +1,23 @@
+#include <dlfcn.h>
+#include <stdio.h>
+#include <unistd.h>
+
+static void *h;
+
+static void __attribute__((constructor))
+mod3init (void)
+{
+ h = dlopen ("unload6mod1.so", RTLD_LAZY);
+ if (h == NULL)
+ {
+ puts ("dlopen unload6mod1.so failed");
+ fflush (stdout);
+ _exit (1);
+ }
+}
+
+static void __attribute__((destructor))
+mod3fini (void)
+{
+ dlclose (h);
+}
diff --git a/fedora/branch.mk b/fedora/branch.mk
index 5b5f55469d..222b4e6c51 100644
--- a/fedora/branch.mk
+++ b/fedora/branch.mk
@@ -1,5 +1,5 @@
# This file is updated automatically by Makefile.
glibc-branch := fedora
glibc-base := HEAD
-fedora-sync-date := 2005-04-15 09:09 UTC
-fedora-sync-tag := fedora-glibc-20050415T0909
+fedora-sync-date := 2005-04-27 10:43 UTC
+fedora-sync-tag := fedora-glibc-20050427T1043
diff --git a/linuxthreads/ChangeLog b/linuxthreads/ChangeLog
index 7ac85a142b..40b40da957 100644
--- a/linuxthreads/ChangeLog
+++ b/linuxthreads/ChangeLog
@@ -1,3 +1,8 @@
+2005-04-27 Roland McGrath <roland@redhat.com>
+
+ * sysdeps/pthread/getcpuclockid.c (pthread_getcpuclockid)
+ [__NR_clock_getres]: Use kernel-supplied CPU clocks if available.
+
2005-03-31 Jakub Jelinek <jakub@redhat.com>
* sysdeps/unix/sysv/linux/x86_64/sysdep-cancel.h: Use
diff --git a/linuxthreads/sysdeps/pthread/getcpuclockid.c b/linuxthreads/sysdeps/pthread/getcpuclockid.c
index 032caeb081..117c22dd37 100644
--- a/linuxthreads/sysdeps/pthread/getcpuclockid.c
+++ b/linuxthreads/sysdeps/pthread/getcpuclockid.c
@@ -1,4 +1,5 @@
-/* Copyright (C) 2000, 2001, 2004 Free Software Foundation, Inc.
+/* pthread_getcpuclockid -- Get POSIX clockid_t for a pthread_t. Linux version
+ Copyright (C) 2000, 2001, 2004 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -21,10 +22,76 @@
#include <sys/time.h>
#include <time.h>
#include <internals.h>
+#include "kernel-features.h"
+#include "posix-cpu-timers.h"
+
+
+#if !(__ASSUME_POSIX_CPU_TIMERS > 0)
+int __libc_missing_posix_cpu_timers attribute_hidden;
+#endif
+#if !(__ASSUME_POSIX_TIMERS > 0)
+int __libc_missing_posix_timers attribute_hidden;
+#endif
int
pthread_getcpuclockid (pthread_t thread_id, clockid_t *clock_id)
{
+#ifdef __NR_clock_getres
+ pthread_handle handle = thread_handle(thread_id);
+ int pid;
+
+ __pthread_lock (&handle->h_lock, NULL);
+ if (nonexisting_handle (handle, thread_id))
+ {
+ __pthread_unlock (&handle->h_lock);
+ return ESRCH;
+ }
+ pid = handle->h_descr->p_pid;
+ __pthread_unlock (&handle->h_lock);
+
+ /* The clockid_t value is a simple computation from the PID.
+ But we do a clock_getres call to validate it if we aren't
+ yet sure we have the kernel support. */
+
+ const clockid_t pidclock = MAKE_PROCESS_CPUCLOCK (pid, CPUCLOCK_SCHED);
+
+# if !(__ASSUME_POSIX_CPU_TIMERS > 0)
+# if !(__ASSUME_POSIX_TIMERS > 0)
+ if (__libc_missing_posix_timers && !__libc_missing_posix_cpu_timers)
+ __libc_missing_cpu_posix_timers = 1;
+# endif
+ if (!__libc_missing_posix_cpu_timers)
+ {
+ INTERNAL_SYSCALL_DECL (err);
+ int r = INTERNAL_SYSCALL (clock_getres, err, 2, tidclock, NULL);
+ if (!INTERNAL_SYSCALL_ERROR_P (r, err))
+# endif
+ {
+ *clock_id = pidclock;
+ return 0;
+ }
+
+# if !(__ASSUME_POSIX_CPU_TIMERS > 0)
+# if !(__ASSUME_POSIX_TIMERS > 0)
+ if (INTERNAL_SYSCALL_ERRNO (r, err) == ENOSYS)
+ {
+ /* The kernel doesn't support these calls at all. */
+ __libc_missing_posix_timers = 1;
+ __libc_missing_posix_cpu_timers = 1;
+ }
+ else
+# endif
+ if (INTERNAL_SYSCALL_ERRNO (r, err) == EINVAL)
+ {
+ /* The kernel doesn't support these clocks at all. */
+ __libc_missing_posix_cpu_timers = 1;
+ }
+ else
+ return INTERNAL_SYSCALL_ERRNO (r, err);
+ }
+# endif
+#endif
+
#ifdef CLOCK_THREAD_CPUTIME_ID
/* We need to store the thread ID in the CLOCKID variable together
with a number identifying the clock. We reserve the low 3 bits
diff --git a/localedata/ChangeLog b/localedata/ChangeLog
index e454cd0cfc..b0829cd181 100644
--- a/localedata/ChangeLog
+++ b/localedata/ChangeLog
@@ -1,5 +1,12 @@
+2005-04-26 Ulrich Drepper <drepper@redhat.com>
+
+ * locales/fa_IR: Add alt_digits, change date and time
+ representation, and various cleanups.
+ Patch by Hamed Malek <hamed@bamdad.org>.
+
2005-03-21 Jakub Jelinek <jakub@redhat.com>
+ [BZ #823]
* charmaps/WINDOWS-31J: Add % before alias keyword.
2005-02-27 Denis Barbier <barbier@debian.org>
diff --git a/localedata/locales/fa_IR b/localedata/locales/fa_IR
index 8f65b1edd8..15fb535640 100644
--- a/localedata/locales/fa_IR
+++ b/localedata/locales/fa_IR
@@ -10,8 +10,8 @@ escape_char /
% Fax: +98 21 6019568
% Language: fa
% Territory: IR
-% Revision: 2.4
-% Date: 2004-09-04
+% Revision: 3.0
+% Date: 2005-04-06
% Users: general
% Repertoiremap:
% Charset: UTF-8
@@ -28,28 +28,31 @@ tel "+98 21 6022372"
fax "+98 21 6019568"
language "Persian"
territory "Iran"
-revision "2.3"
-date "2004-03-16"
+revision "3.0"
+date "2005-04-06"
%
-category "fa_IR:2004";LC_IDENTIFICATION
-category "fa_IR:2004";LC_CTYPE
-category "fa_IR:2004";LC_COLLATE
-category "fa_IR:2004";LC_TIME
-category "fa_IR:2004";LC_NUMERIC
-category "fa_IR:2004";LC_MONETARY
-category "fa_IR:2004";LC_MESSAGES
-category "fa_IR:2004";LC_PAPER
-category "fa_IR:2004";LC_NAME
-category "fa_IR:2004";LC_ADDRESS
-category "fa_IR:2004";LC_TELEPHONE
+category "fa_IR:2005";LC_IDENTIFICATION
+category "fa_IR:2005";LC_CTYPE
+category "fa_IR:2005";LC_COLLATE
+category "fa_IR:2005";LC_TIME
+category "fa_IR:2005";LC_NUMERIC
+category "fa_IR:2005";LC_MONETARY
+category "fa_IR:2005";LC_MESSAGES
+category "fa_IR:2005";LC_PAPER
+category "fa_IR:2005";LC_NAME
+category "fa_IR:2005";LC_ADDRESS
+category "fa_IR:2005";LC_TELEPHONE
END LC_IDENTIFICATION
LC_CTYPE
copy "i18n"
+% Persian uses the alternate digits U+06F0..U+06F9
outdigit <U06F0>..<U06F9>
+% This is used in the scanf family of functions to read Persian numbers
+% using "%Id" and such.
map to_inpunct; /
(<U0030>,<U06F0>); /
(<U0031>,<U06F1>); /
@@ -64,6 +67,8 @@ map to_inpunct; /
(<U002E>,<U066B>); /
(<U002C>,<U066C>)
+% This is used in the printf family of functions to write Persian floating
+% point numbers using "%If" and such.
map to_outpunct; /
(<U002E>,<U066B>); /
(<U002C>,<U066C>)
@@ -76,7 +81,7 @@ copy "iso14651_t1"
% kinds), BEH, PEH, TEH, JEEM, TCHEH, HAH, KHAH, DAL, THAL, REH, ZAIN, JEH,
% SEEN, SHEEN, SAD, DAD, TAH, ZAH, AIN, GHAIN, FEH, QAF, KAF, GAF, LAM,
% MEEM, NOON, WAW, HEH, YEH.
-% The various kind of HAMZA are sorted as ALEF WITH HAMZA ABOVE, ALEF WITH
+% The various kinds of HAMZA are sorted as ALEF WITH HAMZA ABOVE, ALEF WITH
% HAMZA BELOW, WAW WITH HAMZA ABOVE, YEH WITH HAMZA ABOVE.
collating-symbol <AHY> % accent hamza over yeh
@@ -122,7 +127,7 @@ reorder-after <waw>
<heh>
<yeh>
-% Persian uses fatha, kasra, damma, fathatan, kasratan, dammatan order.
+% Persian uses this order: Fatha, Kasra, Damma, Fathatan, Kasratan, Dammatan.
reorder-after <U066D>
<U064E> IGNORE;IGNORE;IGNORE;<U064E> %<fatha_no>
@@ -148,7 +153,7 @@ reorder-after <UFE7F>
<U0655> IGNORE;IGNORE;IGNORE;<U0655> %<hamzabelow_no>
<U0670> IGNORE;IGNORE;IGNORE;<U0670> %<supalef_no>
-% Persian digits are sorted before Arabic ones: they are the basic forms.
+% The Persian digits are sorted before the Arabic ones: they are the basic forms.
reorder-after <U0660>
<U06F0> <0>;<BAS>;<MIN>;IGNORE
<U0660> <0>;<PCL>;<MIN>;IGNORE
@@ -292,14 +297,72 @@ grouping 3
END LC_NUMERIC
LC_TIME
-abday "<U06CC><U002E>";"<U062F><U002E>";"<U0633><U002E>";/
- "<U0686><U002E>";"<U067E><U002E>";"<U062C><U002E>";/
- "<U0634><U002E>"
-day "<U06CC><U06A9><U200C><U0634><U0646><U0628><U0647>";/
+% Alternative digits are used for Persian numerals in date and time. This is
+% a hack, until a new prefix is defined for alternative digits.
+alt_digits "<U06F0><U06F0>";"<U06F0><U06F1>";/
+ "<U06F0><U06F2>";"<U06F0><U06F3>";/
+ "<U06F0><U06F4>";"<U06F0><U06F5>";/
+ "<U06F0><U06F6>";"<U06F0><U06F7>";/
+ "<U06F0><U06F8>";"<U06F0><U06F9>";/
+ "<U06F1><U06F0>";"<U06F1><U06F1>";/
+ "<U06F1><U06F2>";"<U06F1><U06F3>";/
+ "<U06F1><U06F4>";"<U06F1><U06F5>";/
+ "<U06F1><U06F6>";"<U06F1><U06F7>";/
+ "<U06F1><U06F8>";"<U06F1><U06F9>";/
+ "<U06F2><U06F0>";"<U06F2><U06F1>";/
+ "<U06F2><U06F2>";"<U06F2><U06F3>";/
+ "<U06F2><U06F4>";"<U06F2><U06F5>";/
+ "<U06F2><U06F6>";"<U06F2><U06F7>";/
+ "<U06F2><U06F8>";"<U06F2><U06F9>";/
+ "<U06F3><U06F0>";"<U06F3><U06F1>";/
+ "<U06F3><U06F2>";"<U06F3><U06F3>";/
+ "<U06F3><U06F4>";"<U06F3><U06F5>";/
+ "<U06F3><U06F6>";"<U06F3><U06F7>";/
+ "<U06F3><U06F8>";"<U06F3><U06F9>";/
+ "<U06F4><U06F0>";"<U06F4><U06F1>";/
+ "<U06F4><U06F2>";"<U06F4><U06F3>";/
+ "<U06F4><U06F4>";"<U06F4><U06F5>";/
+ "<U06F4><U06F6>";"<U06F4><U06F7>";/
+ "<U06F4><U06F8>";"<U06F4><U06F9>";/
+ "<U06F5><U06F0>";"<U06F5><U06F1>";/
+ "<U06F5><U06F2>";"<U06F5><U06F3>";/
+ "<U06F5><U06F4>";"<U06F5><U06F5>";/
+ "<U06F5><U06F6>";"<U06F5><U06F7>";/
+ "<U06F5><U06F8>";"<U06F5><U06F9>";/
+ "<U06F6><U06F0>";"<U06F6><U06F1>";/
+ "<U06F6><U06F2>";"<U06F6><U06F3>";/
+ "<U06F6><U06F4>";"<U06F6><U06F5>";/
+ "<U06F6><U06F6>";"<U06F6><U06F7>";/
+ "<U06F6><U06F8>";"<U06F6><U06F9>";/
+ "<U06F7><U06F0>";"<U06F7><U06F1>";/
+ "<U06F7><U06F2>";"<U06F7><U06F3>";/
+ "<U06F7><U06F4>";"<U06F7><U06F5>";/
+ "<U06F7><U06F6>";"<U06F7><U06F7>";/
+ "<U06F7><U06F8>";"<U06F7><U06F9>";/
+ "<U06F8><U06F0>";"<U06F8><U06F1>";/
+ "<U06F8><U06F2>";"<U06F8><U06F3>";/
+ "<U06F8><U06F4>";"<U06F8><U06F5>";/
+ "<U06F8><U06F6>";"<U06F8><U06F7>";/
+ "<U06F8><U06F8>";"<U06F8><U06F9>";/
+ "<U06F9><U06F0>";"<U06F9><U06F1>";/
+ "<U06F9><U06F2>";"<U06F9><U06F3>";/
+ "<U06F9><U06F4>";"<U06F9><U06F5>";/
+ "<U06F9><U06F6>";"<U06F9><U06F7>";/
+ "<U06F9><U06F8>";"<U06F9><U06F9>"
+% Persian doesn't have abbreviations for weekdays and month names, so
+% "abday" is the same as "day" and "abmon" is the same as "mon"
+abday "<U06CC><U06A9><U0634><U0646><U0628><U0647>";/
"<U062F><U0648><U0634><U0646><U0628><U0647>";/
"<U0633><U0647><U200C><U0634><U0646><U0628><U0647>";/
"<U0686><U0647><U0627><U0631><U0634><U0646><U0628><U0647>";/
- "<U067E><U0646><U062C><U200C><U0634><U0646><U0628><U0647>";/
+ "<U067E><U0646><U062C><U0634><U0646><U0628><U0647>";/
+ "<U062C><U0645><U0639><U0647>";/
+ "<U0634><U0646><U0628><U0647>"
+day "<U06CC><U06A9><U0634><U0646><U0628><U0647>";/
+ "<U062F><U0648><U0634><U0646><U0628><U0647>";/
+ "<U0633><U0647><U200C><U0634><U0646><U0628><U0647>";/
+ "<U0686><U0647><U0627><U0631><U0634><U0646><U0628><U0647>";/
+ "<U067E><U0646><U062C><U0634><U0646><U0628><U0647>";/
"<U062C><U0645><U0639><U0647>";/
"<U0634><U0646><U0628><U0647>"
mon "<U0698><U0627><U0646><U0648><U06CC><U0647>";/
@@ -314,33 +377,68 @@ mon "<U0698><U0627><U0646><U0648><U06CC><U0647>";/
"<U0627><U0643><U062A><U0628><U0631>";/
"<U0646><U0648><U0627><U0645><U0628><U0631>";/
"<U062F><U0633><U0627><U0645><U0628><U0631>"
-abmon "<U0698><U0627><U0646>";"<U0641><U0648><U0631>";/
- "<U0645><U0627><U0631>";"<U0622><U0648><U0631>";/
- "<U0645><U0640><U0647>";"<U0698><U0648><U0646>";/
- "<U0698><U0648><U06CC>";"<U0627><U0648><U062A>";/
- "<U0633><U067E><U062A>";"<U0627><U0643><U062A>";/
- "<U0646><U0648><U0627>";"<U062F><U0633><U0627>"
-am_pm "<U0635><U0628><U062D>";"<U0639><U0635><U0631>"
-d_t_fmt "<U202B><U0025><U0041><U0020><U0025><U0065><U0020><U0025>/
-<U0042><U0020><U0025><U0059><U060C><U0020><U0025><U0049><U003A>/
-<U0025><U004D><U003A><U0025><U0053><U0020><U0025><U0070><U202C>"
-d_fmt "<U0025><U0059><U002F><U0025><U006D><U002F><U0025><U0064>"
-t_fmt "<U0025><U0048><U003A><U0025><U004D><U003A><U0025><U0053>"
-t_fmt_ampm "<U202B><U0025><U0049><U003A><U0025><U004D><U003A><U0025>/
-<U0053><U0020><U0025><U0070><U202C>"
-%date_fmt "<U0025><U0061><U0020><U0025><U0062><U0020><U0025><U0065><U0020>/
-%<U0025><U0048><U003A><U0025><U004D><U003A><U0025><U0053><U0020><U0025>/
-%<U005A><U0020><U0025><U0059>"
+abmon "<U0698><U0627><U0646><U0648><U06CC><U0647>";/
+ "<U0641><U0648><U0631><U06CC><U0647>";/
+ "<U0645><U0627><U0631><U0633>";/
+ "<U0622><U0648><U0631><U06CC><U0644>";/
+ "<U0645><U0647>";/
+ "<U0698><U0648><U0626><U0646>";/
+ "<U0698><U0648><U0626><U06CC><U0647>";/
+ "<U0627><U0648><U062A>";/
+ "<U0633><U067E><U062A><U0627><U0645><U0628><U0631>";/
+ "<U0627><U0643><U062A><U0628><U0631>";/
+ "<U0646><U0648><U0627><U0645><U0628><U0631>";/
+ "<U062F><U0633><U0627><U0645><U0628><U0631>"
+% Persian does not have the 12-hour format
+am_pm "";""
+t_fmt_ampm ""
+%
+% Appropriate date representation (%x)
+% "%Oy/%Om/%Od"
+d_fmt "<U0025><U004F><U0079><U002F>/
+<U0025><U004F><U006D><U002F>/
+<U0025><U004F><U0064>"
+%
+% Appropriate time representation (%X)
+% "%OH:%OM:%OS"
+t_fmt "<U0025><U004F><U0048><U003A>/
+<U0025><U004F><U004D><U003A>/
+<U0025><U004F><U0053>"
+%
+% FIXME: need to add "HAMZA ABOVE" after January, February, May, July when used
+% before a year
+%
+% Appropriate date and time representation (%c)
+% "<RLE>%A %Oe %B %Oy<ARABIC COMMA> %OH:%OM:%OS<PDF>"
+d_t_fmt "<U202B><U0025><U0041><U0020>/
+<U0025><U004F><U0065><U0020>/
+<U0025><U0042><U0020>/
+<U0025><U004F><U0079><U060C><U0020>/
+<U0025><U004F><U0048><U003A>/
+<U0025><U004F><U004D><U003A>/
+<U0025><U004F><U0053><U202C>"
+%
+% Appropriate date representation (date(1))
+% "<RLE>%A %Oe %B %Oy<ARABIC COMMA> <SEEN><ALEF><AIN><TEH> %OH:%OM:%OS (%Z)<PDF>"
+date_fmt "<U202B><U0025><U0041><U0020>/
+<U0025><U004F><U0065><U0020>/
+<U0025><U0042><U0020>/
+<U0025><U004F><U0079><U060C><U0020>/
+<U0633><U0627><U0639><U062A><U0020>/
+<U0025><U004F><U0048><U003A>/
+<U0025><U004F><U004D><U003A>/
+<U0025><U004F><U0053><U0020>/
+<U0028><U0025><U005A><U0029><U202C>"
first_weekday 7
first_workday 7
cal_direction 3
-%week 7;19971206;4
-%time_zone "???"
END LC_TIME
LC_MESSAGES
-yesexpr "<U005E><U005B><U0079><U0059><U0628><U0066><U005D><U002E><U002A>"
-noexpr "<U005E><U005B><U006E><U004E><U062E><U0646><U006F><U005D><U002E><U002A>"
+% This is "^[yY<ALEF MADDA><BEH>Hf].*"
+yesexpr "<U005E><U005B><U0079><U0059><U0622><U0628><U0048><U0066><U005D><U002E><U002A>"
+% This is "^[nN<KHAH><NOON>ok].*"
+noexpr "<U005E><U005B><U006E><U004E><U062E><U0646><U006F><U006B><U005D><U002E><U002A>"
END LC_MESSAGES
LC_PAPER
@@ -348,18 +446,6 @@ height 297
width 210
END LC_PAPER
-LC_TELEPHONE
-tel_int_fmt "<U202A><U002B><U0025><U0063><U0020><U0025><U0061><U0020>/
-<U0025><U006C><U202C>"
-tel_dom_fmt "<U202A><U0025><U0041><U2012><U0025><U006C><U202C>"
-int_select "<U0030><U0030>"
-int_prefix "<U0039><U0038>"
-END LC_TELEPHONE
-
-LC_MEASUREMENT
-measurement 1
-END LC_MEASUREMENT
-
LC_NAME
name_gen ""
name_miss "<U062E><U0627><U0646><U0645>"
@@ -371,7 +457,6 @@ name_fmt "<U0025><U0064><U0025><U0074><U0025><U0073><U0025><U0074>/
END LC_NAME
LC_ADDRESS
-% FIXME
postal_fmt "<U0025><U0066><U0025><U004E><U0025><U0061><U0025><U004E>/
<U0025><U0064><U0025><U004E><U0025><U0062><U0025><U004E><U0025><U0073>/
<U0020><U0025><U0068><U0020><U0025><U0065><U0020><U0025><U0072><U0025>/
@@ -388,3 +473,15 @@ lang_ab "<U0066><U0061>"
lang_term "<U0066><U0061><U0073>"
lang_lib "<U0070><U0065><U0072>"
END LC_ADDRESS
+
+LC_TELEPHONE
+tel_int_fmt "<U202A><U002B><U0025><U0063><U0020><U0025><U0061><U0020>/
+<U0025><U006C><U202C>"
+tel_dom_fmt "<U202A><U0025><U0041><U2012><U0025><U006C><U202C>"
+int_select "<U0030><U0030>"
+int_prefix "<U0039><U0038>"
+END LC_TELEPHONE
+
+LC_MEASUREMENT
+measurement 1
+END LC_MEASUREMENT
diff --git a/malloc/Makefile b/malloc/Makefile
index 45e8f59ab4..398dd2b031 100644
--- a/malloc/Makefile
+++ b/malloc/Makefile
@@ -1,4 +1,5 @@
-# Copyright (C) 1991-1999,2000,2001,2002,2003 Free Software Foundation, Inc.
+# Copyright (C) 1991-1999, 2000, 2001, 2002, 2003, 2005
+# Free Software Foundation, Inc.
# This file is part of the GNU C Library.
# The GNU C Library is free software; you can redistribute it and/or
@@ -26,7 +27,7 @@ all:
dist-headers := malloc.h
headers := $(dist-headers) obstack.h mcheck.h
tests := mallocbug tst-malloc tst-valloc tst-calloc tst-obstack \
- tst-mallocstate
+ tst-mallocstate tst-mcheck
test-srcs = tst-mtrace
distribute = thread-m.h mtrace.pl mcheck-init.c stackinfo.h memusage.h \
@@ -120,6 +121,8 @@ endif
endif
endif
+tst-mcheck-ENV = MALLOC_CHECK_=3
+
# Uncomment this for test releases. For public releases it is too expensive.
#CPPFLAGS-malloc.o += -DMALLOC_DEBUG=1
diff --git a/malloc/hooks.c b/malloc/hooks.c
index a5c97f3133..0f8f274e38 100644
--- a/malloc/hooks.c
+++ b/malloc/hooks.c
@@ -1,5 +1,5 @@
/* Malloc implementation for multiple threads without lock contention.
- Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+ Copyright (C) 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Wolfram Gloger <wg@malloc.de>, 2001.
@@ -146,9 +146,9 @@ mem2mem_check(ptr, sz) Void_t *ptr; size_t sz;
static mchunkptr
internal_function
#if __STD_C
-mem2chunk_check(Void_t* mem)
+mem2chunk_check(Void_t* mem, unsigned char **magic_p)
#else
-mem2chunk_check(mem) Void_t* mem;
+mem2chunk_check(mem, magic_p) Void_t* mem; unsigned char **magic_p;
#endif
{
mchunkptr p;
@@ -173,7 +173,6 @@ mem2chunk_check(mem) Void_t* mem;
for(sz += SIZE_SZ-1; (c = ((unsigned char*)p)[sz]) != magic; sz -= c) {
if(c<=0 || sz<(c+2*SIZE_SZ)) return NULL;
}
- ((unsigned char*)p)[sz] ^= 0xFF;
} else {
unsigned long offset, page_mask = malloc_getpagesize-1;
@@ -193,8 +192,10 @@ mem2chunk_check(mem) Void_t* mem;
for(sz -= 1; (c = ((unsigned char*)p)[sz]) != magic; sz -= c) {
if(c<=0 || sz<(c+2*SIZE_SZ)) return NULL;
}
- ((unsigned char*)p)[sz] ^= 0xFF;
}
+ ((unsigned char*)p)[sz] ^= 0xFF;
+ if (magic_p)
+ *magic_p = (unsigned char *)p + sz;
return p;
}
@@ -232,7 +233,11 @@ top_check()
sbrk_size = front_misalign + mp_.top_pad + MINSIZE;
sbrk_size += pagesz - ((unsigned long)(brk + sbrk_size) & (pagesz - 1));
new_brk = (char*)(MORECORE (sbrk_size));
- if (new_brk == (char*)(MORECORE_FAILURE)) return -1;
+ if (new_brk == (char*)(MORECORE_FAILURE))
+ {
+ MALLOC_FAILURE_ACTION;
+ return -1;
+ }
/* Call the `morecore' hook if necessary. */
if (__after_morecore_hook)
(*__after_morecore_hook) ();
@@ -253,6 +258,11 @@ malloc_check(sz, caller) size_t sz; const Void_t *caller;
{
Void_t *victim;
+ if (sz+1 == 0) {
+ MALLOC_FAILURE_ACTION;
+ return NULL;
+ }
+
(void)mutex_lock(&main_arena.mutex);
victim = (top_check() >= 0) ? _int_malloc(&main_arena, sz+1) : NULL;
(void)mutex_unlock(&main_arena.mutex);
@@ -270,7 +280,7 @@ free_check(mem, caller) Void_t* mem; const Void_t *caller;
if(!mem) return;
(void)mutex_lock(&main_arena.mutex);
- p = mem2chunk_check(mem);
+ p = mem2chunk_check(mem, NULL);
if(!p) {
(void)mutex_unlock(&main_arena.mutex);
@@ -302,10 +312,19 @@ realloc_check(oldmem, bytes, caller)
mchunkptr oldp;
INTERNAL_SIZE_T nb, oldsize;
Void_t* newmem = 0;
+ unsigned char *magic_p;
+ if (bytes+1 == 0) {
+ MALLOC_FAILURE_ACTION;
+ return NULL;
+ }
if (oldmem == 0) return malloc_check(bytes, NULL);
+ if (bytes == 0) {
+ free_check (oldmem, NULL);
+ return NULL;
+ }
(void)mutex_lock(&main_arena.mutex);
- oldp = mem2chunk_check(oldmem);
+ oldp = mem2chunk_check(oldmem, &magic_p);
(void)mutex_unlock(&main_arena.mutex);
if(!oldp) {
malloc_printerr(check_action, "realloc(): invalid pointer", oldmem);
@@ -357,6 +376,12 @@ realloc_check(oldmem, bytes, caller)
#if HAVE_MMAP
}
#endif
+
+ /* mem2chunk_check changed the magic byte in the old chunk.
+ If newmem is NULL, then the old chunk will still be used though,
+ so we need to invert that change here. */
+ if (newmem == NULL) *magic_p ^= 0xFF;
+
(void)mutex_unlock(&main_arena.mutex);
return mem2mem_check(newmem, bytes);
@@ -376,6 +401,10 @@ memalign_check(alignment, bytes, caller)
if (alignment <= MALLOC_ALIGNMENT) return malloc_check(bytes, NULL);
if (alignment < MINSIZE) alignment = MINSIZE;
+ if (bytes+1 == 0) {
+ MALLOC_FAILURE_ACTION;
+ return NULL;
+ }
checked_request2size(bytes+1, nb);
(void)mutex_lock(&main_arena.mutex);
mem = (top_check() >= 0) ? _int_memalign(&main_arena, alignment, bytes+1) :
diff --git a/malloc/tst-mcheck.c b/malloc/tst-mcheck.c
new file mode 100644
index 0000000000..16784912a9
--- /dev/null
+++ b/malloc/tst-mcheck.c
@@ -0,0 +1,91 @@
+/* Copyright (C) 2005 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Jakub Jelinek <jakub@redhat.com>, 2005.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+static int errors = 0;
+
+static void
+merror (const char *msg)
+{
+ ++errors;
+ printf ("Error: %s\n", msg);
+}
+
+int
+main (void)
+{
+ void *p, *q;
+
+ errno = 0;
+
+ p = malloc (-1);
+
+ if (p != NULL)
+ merror ("malloc (-1) succeeded.");
+ else if (errno != ENOMEM)
+ merror ("errno is not set correctly.");
+
+ p = malloc (10);
+ if (p == NULL)
+ merror ("malloc (10) failed.");
+
+ p = realloc (p, 0);
+ if (p != NULL)
+ merror ("realloc (p, 0) failed.");
+
+ p = malloc (0);
+ if (p == NULL)
+ merror ("malloc (0) failed.");
+
+ p = realloc (p, 0);
+ if (p != NULL)
+ merror ("realloc (p, 0) failed.");
+
+ q = malloc (256);
+ if (q == NULL)
+ merror ("malloc (256) failed.");
+
+ p = malloc (512);
+ if (p == NULL)
+ merror ("malloc (512) failed.");
+
+ if (realloc (p, -256) != NULL)
+ merror ("realloc (p, -256) succeeded.");
+ else if (errno != ENOMEM)
+ merror ("errno is not set correctly.");
+
+ free (p);
+
+ p = malloc (512);
+ if (p == NULL)
+ merror ("malloc (512) failed.");
+
+ if (realloc (p, -1) != NULL)
+ merror ("realloc (p, -1) succeeded.");
+ else if (errno != ENOMEM)
+ merror ("errno is not set correctly.");
+
+ free (p);
+ free (q);
+
+ return errors != 0;
+}
diff --git a/nptl/ChangeLog b/nptl/ChangeLog
index e608d136ce..790ceb01d0 100644
--- a/nptl/ChangeLog
+++ b/nptl/ChangeLog
@@ -1,3 +1,25 @@
+2005-04-27 Ulrich Drepper <drepper@redhat.com>
+
+ * tst-cancel17.c (do_test): Add arbitrary factor to make sure
+ aio_write blocks.
+
+2005-04-27 Roland McGrath <roland@redhat.com>
+
+ * Makefile (tests): Remove tst-clock2.
+
+ * sysdeps/unix/sysv/linux/timer_create.c (timer_create): Handle
+ CLOCK_PROCESS_CPUTIME_ID and CLOCK_PROCESS_THREAD_ID specially,
+ translating to the kernel clockid_t for our own process/thread clock.
+
+ * sysdeps/unix/sysv/linux/pthread_getcpuclockid.c: New file.
+
+2005-04-15 Jakub Jelinek <jakub@redhat.com>
+
+ * old_pthread_cond_init.c: Include <errno.h>.
+ (__pthread_cond_init_2_0): Fail with EINVAL if COND_ATTR is
+ process shared or uses clock other than CLOCK_REALTIME.
+ * pthread_cond_init.c (__pthread_cond_init): Remove bogus comment.
+
2005-04-13 David S. Miller <davem@davemloft.net>
* sysdeps/sparc/sparc64/jmpbuf-unwind.h: New file.
diff --git a/nptl/Makefile b/nptl/Makefile
index 8d18946e6f..2acb8d01b7 100644
--- a/nptl/Makefile
+++ b/nptl/Makefile
@@ -1,4 +1,4 @@
-# Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+# Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
# This file is part of the GNU C Library.
# The GNU C Library is free software; you can redistribute it and/or
@@ -235,7 +235,7 @@ tests = tst-attr1 tst-attr2 tst-attr3 \
tst-locale1 tst-locale2 \
tst-umask1 \
tst-popen1 \
- tst-clock1 tst-clock2 \
+ tst-clock1 \
tst-context1 \
tst-sched1 \
tst-backtrace1 \
diff --git a/nptl/old_pthread_cond_init.c b/nptl/old_pthread_cond_init.c
index 21bc856a02..47e68b000d 100644
--- a/nptl/old_pthread_cond_init.c
+++ b/nptl/old_pthread_cond_init.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+/* Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
@@ -17,6 +17,7 @@
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
+#include <errno.h>
#include "pthreadP.h"
#include <shlib-compat.h>
@@ -27,15 +28,18 @@ __pthread_cond_init_2_0 (cond, cond_attr)
pthread_cond_2_0_t *cond;
const pthread_condattr_t *cond_attr;
{
- /* Note that we don't need the COND-ATTR. It contains only the
- PSHARED flag which is unimportant here since conditional
- variables are always usable in multiple processes. */
+ struct pthread_condattr *icond_attr = (struct pthread_condattr *) cond_attr;
/* The type of the first argument is actually that of the old, too
small pthread_cond_t. We use only the first word of it, as a
pointer. */
cond->cond = NULL;
+ /* We can't support PSHARED condvars in the old pthread_cond_*
+ functions and neither clocks other than CLOCK_REALTIME. */
+ if (icond_attr != NULL && icond_attr->value)
+ return EINVAL;
+
return 0;
}
compat_symbol (libpthread, __pthread_cond_init_2_0, pthread_cond_init,
diff --git a/nptl/pthread_cond_init.c b/nptl/pthread_cond_init.c
index 03ac59dbd2..5e2e6704a9 100644
--- a/nptl/pthread_cond_init.c
+++ b/nptl/pthread_cond_init.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+/* Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
@@ -26,8 +26,6 @@ __pthread_cond_init (cond, cond_attr)
pthread_cond_t *cond;
const pthread_condattr_t *cond_attr;
{
- /* Note that we don't need the PSHARED information from COND-ATTR.
- Conditional variables are always usable in multiple processes. */
struct pthread_condattr *icond_attr = (struct pthread_condattr *) cond_attr;
cond->__data.__lock = LLL_MUTEX_LOCK_INITIALIZER;
diff --git a/nptl/sysdeps/i386/tls.h b/nptl/sysdeps/i386/tls.h
index e243f8b2cf..06def42a5b 100644
--- a/nptl/sysdeps/i386/tls.h
+++ b/nptl/sysdeps/i386/tls.h
@@ -43,7 +43,7 @@ typedef union dtv
typedef struct
{
- void *tcb; /* Pointer to the TCB. Not necessary the
+ void *tcb; /* Pointer to the TCB. Not necessarily the
thread descriptor used by libpthread. */
dtv_t *dtv;
void *self; /* Pointer to the thread descriptor. */
diff --git a/nptl/sysdeps/unix/sysv/linux/pthread_getcpuclockid.c b/nptl/sysdeps/unix/sysv/linux/pthread_getcpuclockid.c
new file mode 100644
index 0000000000..088b3392bc
--- /dev/null
+++ b/nptl/sysdeps/unix/sysv/linux/pthread_getcpuclockid.c
@@ -0,0 +1,111 @@
+/* pthread_getcpuclockid -- Get POSIX clockid_t for a pthread_t. Linux version
+ Copyright (C) 2000,2001,2002,2003,2004 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#include <errno.h>
+#include <pthreadP.h>
+#include <sys/time.h>
+#include <tls.h>
+#include "kernel-features.h"
+#include "kernel-posix-cpu-timers.h"
+
+
+#if !(__ASSUME_POSIX_CPU_TIMERS > 0)
+int __libc_missing_posix_cpu_timers attribute_hidden;
+#endif
+#if !(__ASSUME_POSIX_TIMERS > 0)
+int __libc_missing_posix_timers attribute_hidden;
+#endif
+
+int
+pthread_getcpuclockid (threadid, clockid)
+ pthread_t threadid;
+ clockid_t *clockid;
+{
+ struct pthread *pd = (struct pthread *) threadid;
+
+ /* Make sure the descriptor is valid. */
+ if (INVALID_TD_P (pd))
+ /* Not a valid thread handle. */
+ return ESRCH;
+
+#ifdef __NR_clock_getres
+ /* The clockid_t value is a simple computation from the TID.
+ But we do a clock_getres call to validate it if we aren't
+ yet sure we have the kernel support. */
+
+ const clockid_t tidclock = MAKE_THREAD_CPUCLOCK (pd->tid, CPUCLOCK_SCHED);
+
+# if !(__ASSUME_POSIX_CPU_TIMERS > 0)
+# if !(__ASSUME_POSIX_TIMERS > 0)
+ if (__libc_missing_posix_timers && !__libc_missing_posix_cpu_timers)
+ __libc_missing_posix_cpu_timers = 1;
+# endif
+ if (!__libc_missing_posix_cpu_timers)
+ {
+ INTERNAL_SYSCALL_DECL (err);
+ int r = INTERNAL_SYSCALL (clock_getres, err, 2, tidclock, NULL);
+ if (!INTERNAL_SYSCALL_ERROR_P (r, err))
+# endif
+ {
+ *clockid = tidclock;
+ return 0;
+ }
+
+# if !(__ASSUME_POSIX_CPU_TIMERS > 0)
+# if !(__ASSUME_POSIX_TIMERS > 0)
+ if (INTERNAL_SYSCALL_ERRNO (r, err) == ENOSYS)
+ {
+ /* The kernel doesn't support these calls at all. */
+ __libc_missing_posix_timers = 1;
+ __libc_missing_posix_cpu_timers = 1;
+ }
+ else
+# endif
+ if (INTERNAL_SYSCALL_ERRNO (r, err) == EINVAL)
+ {
+ /* The kernel doesn't support these clocks at all. */
+ __libc_missing_posix_cpu_timers = 1;
+ }
+ else
+ return INTERNAL_SYSCALL_ERRNO (r, err);
+ }
+# endif
+#endif
+
+#ifdef CLOCK_THREAD_CPUTIME_ID
+ /* We need to store the thread ID in the CLOCKID variable together
+ with a number identifying the clock. We reserve the low 3 bits
+ for the clock ID and the rest for the thread ID. This is
+ problematic if the thread ID is too large. But 29 bits should be
+ fine.
+
+ If some day more clock IDs are needed the ID part can be
+ enlarged. The IDs are entirely internal. */
+ if (pd->tid >= 1 << (8 * sizeof (*clockid) - CLOCK_IDFIELD_SIZE))
+ return ERANGE;
+
+ /* Store the number. */
+ *clockid = CLOCK_THREAD_CPUTIME_ID | (pd->tid << CLOCK_IDFIELD_SIZE);
+
+ return 0;
+#else
+ /* We don't have a timer for that. */
+ return ENOENT;
+#endif
+}
diff --git a/nptl/sysdeps/unix/sysv/linux/timer_create.c b/nptl/sysdeps/unix/sysv/linux/timer_create.c
index ca6ff6c7ef..5e99513950 100644
--- a/nptl/sysdeps/unix/sysv/linux/timer_create.c
+++ b/nptl/sysdeps/unix/sysv/linux/timer_create.c
@@ -28,6 +28,7 @@
#include <internaltypes.h>
#include <nptl/pthreadP.h>
#include "kernel-posix-timers.h"
+#include "kernel-posix-cpu-timers.h"
#ifdef __NR_timer_create
@@ -58,6 +59,12 @@ timer_create (clock_id, evp, timerid)
if (__no_posix_timers >= 0)
# endif
{
+ clockid_t syscall_clockid = (clock_id == CLOCK_PROCESS_CPUTIME_ID
+ ? MAKE_PROCESS_CPUCLOCK (0, CPUCLOCK_SCHED)
+ : clock_id == CLOCK_THREAD_CPUTIME_ID
+ ? MAKE_THREAD_CPUCLOCK (0, CPUCLOCK_SCHED)
+ : clock_id);
+
/* If the user wants notification via a thread we need to handle
this special. */
if (evp == NULL
@@ -88,7 +95,7 @@ timer_create (clock_id, evp, timerid)
}
kernel_timer_t ktimerid;
- int retval = INLINE_SYSCALL (timer_create, 3, clock_id, evp,
+ int retval = INLINE_SYSCALL (timer_create, 3, syscall_clockid, evp,
&ktimerid);
# ifndef __ASSUME_POSIX_TIMERS
@@ -196,8 +203,8 @@ timer_create (clock_id, evp, timerid)
/* Create the timer. */
INTERNAL_SYSCALL_DECL (err);
int res;
- res = INTERNAL_SYSCALL (timer_create, err, 3, clock_id, &sev,
- &newp->ktimerid);
+ res = INTERNAL_SYSCALL (timer_create, err, 3,
+ syscall_clockid, &sev, &newp->ktimerid);
if (! INTERNAL_SYSCALL_ERROR_P (res, err))
{
*timerid = (timer_t) newp;
diff --git a/nptl/tst-cancel17.c b/nptl/tst-cancel17.c
index 9fb089ac83..2a8c951afe 100644
--- a/nptl/tst-cancel17.c
+++ b/nptl/tst-cancel17.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2003 Free Software Foundation, Inc.
+/* Copyright (C) 2003, 2005 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 2003.
@@ -228,7 +228,7 @@ do_test (void)
size_t len2 = fpathconf (fds[1], _PC_PIPE_BUF);
size_t page_size = sysconf (_SC_PAGESIZE);
- len2 = (len2 < page_size ? page_size : len2) + sizeof (mem) + 1;
+ len2 = 20 * (len2 < page_size ? page_size : len2) + sizeof (mem) + 1;
char *mem2 = malloc (len2);
if (mem2 == NULL)
{
diff --git a/posix/unistd.h b/posix/unistd.h
index d6cd152b46..b0fba33417 100644
--- a/posix/unistd.h
+++ b/posix/unistd.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991-2003, 2004, 2005 Free Software Foundation, Inc.
+/* Copyright (C) 1991-2002,2003,2004,2005 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -840,7 +840,7 @@ extern int profil (unsigned short int *__sample_buffer, size_t __size,
/* Turn accounting on if NAME is an existing file. The system will then write
a record for each process as it terminates, to this file. If NAME is NULL,
turn accounting off. This call is restricted to the super-user. */
-extern int acct (__const char *__name) __THROW __nonnull ((1));
+extern int acct (__const char *__name) __THROW;
/* Successive calls return the shells listed in `/etc/shells'. */
diff --git a/rt/Makefile b/rt/Makefile
index 407cc99897..cc01cb95c9 100644
--- a/rt/Makefile
+++ b/rt/Makefile
@@ -45,7 +45,9 @@ tests := tst-shm tst-clock tst-clock_nanosleep tst-timer tst-timer2 \
tst-aio tst-aio64 tst-aio2 tst-aio3 tst-aio4 tst-aio5 tst-aio6 \
tst-aio7 tst-mqueue1 tst-mqueue2 tst-mqueue3 tst-mqueue4 \
tst-mqueue5 tst-mqueue6 tst-mqueue7 tst-mqueue8 tst-mqueue9 \
- tst-timer3 tst-timer4 tst-timer5
+ tst-timer3 tst-timer4 tst-timer5 \
+ tst-cpuclock1 tst-cpuclock2 \
+ tst-cputimer1 tst-cputimer2 tst-cputimer3
extra-libs := librt
extra-libs-others := $(extra-libs)
diff --git a/rt/tst-cpuclock1.c b/rt/tst-cpuclock1.c
new file mode 100644
index 0000000000..024df63141
--- /dev/null
+++ b/rt/tst-cpuclock1.c
@@ -0,0 +1,307 @@
+/* Test program for process CPU clocks.
+ Copyright (C) 2004 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <errno.h>
+#include <signal.h>
+#include <sys/wait.h>
+
+/* This function is intended to rack up both user and system time. */
+static void
+chew_cpu (void)
+{
+ while (1)
+ {
+ static volatile char buf[4096];
+ for (int i = 0; i < 100; ++i)
+ for (size_t j = 0; j < sizeof buf; ++j)
+ buf[j] = 0xaa;
+ int nullfd = open ("/dev/null", O_WRONLY);
+ for (int i = 0; i < 100; ++i)
+ for (size_t j = 0; j < sizeof buf; ++j)
+ buf[j] = 0xbb;
+ write (nullfd, (char *) buf, sizeof buf);
+ close (nullfd);
+ if (getppid () == 1)
+ _exit (2);
+ }
+}
+
+static int
+do_test (void)
+{
+ int result = 0;
+ clockid_t cl;
+ int e;
+ pid_t dead_child, child;
+
+ /* Fork a child and let it die, to give us a PID known not be valid
+ (assuming PIDs don't wrap around during the test). */
+ {
+ dead_child = fork ();
+ if (dead_child == 0)
+ _exit (0);
+ if (dead_child < 0)
+ {
+ perror ("fork");
+ return 1;
+ }
+ int x;
+ if (wait (&x) != dead_child)
+ {
+ perror ("wait");
+ return 2;
+ }
+ }
+
+ /* POSIX says we should get ESRCH for this. */
+ e = clock_getcpuclockid (dead_child, &cl);
+ if (e != ENOSYS && e != ESRCH && e != EPERM)
+ {
+ printf ("clock_getcpuclockid on dead PID %d => %s\n",
+ dead_child, strerror (e));
+ result = 1;
+ }
+
+ /* Now give us a live child eating up CPU time. */
+ child = fork ();
+ if (child == 0)
+ {
+ chew_cpu ();
+ _exit (1);
+ }
+ if (child < 0)
+ {
+ perror ("fork");
+ return 1;
+ }
+
+ e = clock_getcpuclockid (child, &cl);
+ if (e == EPERM)
+ {
+ puts ("clock_getcpuclockid does not support other processes");
+ goto done;
+ }
+ if (e != 0)
+ {
+ printf ("clock_getcpuclockid on live PID %d => %s\n",
+ child, strerror (e));
+ result = 1;
+ goto done;
+ }
+
+ const clockid_t child_clock = cl;
+ struct timespec res;
+ if (clock_getres (child_clock, &res) < 0)
+ {
+ printf ("clock_getres on live PID %d clock %lx => %s\n",
+ child, (unsigned long int) child_clock, strerror (errno));
+ result = 1;
+ goto done;
+ }
+ printf ("live PID %d clock %lx resolution %lu.%.9lu\n",
+ child, (unsigned long int) child_clock, res.tv_sec, res.tv_nsec);
+
+ struct timespec before, after;
+ if (clock_gettime (child_clock, &before) < 0)
+ {
+ printf ("clock_gettime on live PID %d clock %lx => %s\n",
+ child, (unsigned long int) child_clock, strerror (errno));
+ result = 1;
+ goto done;
+ }
+ printf ("live PID %d before sleep => %lu.%.9lu\n",
+ child, before.tv_sec, before.tv_nsec);
+
+ struct timespec sleeptime = { .tv_nsec = 500000000 };
+ nanosleep (&sleeptime, NULL);
+
+ if (clock_gettime (child_clock, &after) < 0)
+ {
+ printf ("clock_gettime on live PID %d clock %lx => %s\n",
+ child, (unsigned long int) child_clock, strerror (errno));
+ result = 1;
+ goto done;
+ }
+ printf ("live PID %d after sleep => %lu.%.9lu\n",
+ child, after.tv_sec, after.tv_nsec);
+
+ struct timespec diff = { .tv_sec = after.tv_sec - before.tv_sec,
+ .tv_nsec = after.tv_nsec - before.tv_nsec };
+ if (diff.tv_nsec < 0)
+ {
+ --diff.tv_sec;
+ diff.tv_nsec += 1000000000;
+ }
+ if (diff.tv_sec != 0
+ || diff.tv_nsec > 600000000
+ || diff.tv_nsec < 100000000)
+ {
+ printf ("before - after %lu.%.9lu outside reasonable range\n",
+ diff.tv_sec, diff.tv_nsec);
+ result = 1;
+ }
+
+ sleeptime.tv_nsec = 100000000;
+ e = clock_nanosleep (child_clock, 0, &sleeptime, NULL);
+ if (e == EINVAL || e == ENOTSUP || e == ENOSYS)
+ {
+ printf ("clock_nanosleep not supported for other process clock: %s\n",
+ strerror (e));
+ }
+ else if (e != 0)
+ {
+ printf ("clock_nanosleep on other process clock: %s\n", strerror (e));
+ result = 1;
+ }
+ else
+ {
+ struct timespec afterns;
+ if (clock_gettime (child_clock, &afterns) < 0)
+ {
+ printf ("clock_gettime on live PID %d clock %lx => %s\n",
+ child, (unsigned long int) child_clock, strerror (errno));
+ result = 1;
+ }
+ else
+ {
+ struct timespec d = { .tv_sec = afterns.tv_sec - after.tv_sec,
+ .tv_nsec = afterns.tv_nsec - after.tv_nsec };
+ if (d.tv_nsec < 0)
+ {
+ --d.tv_sec;
+ d.tv_nsec += 1000000000;
+ }
+ if (d.tv_sec > 0
+ || d.tv_nsec < sleeptime.tv_nsec
+ || d.tv_nsec > sleeptime.tv_nsec * 2)
+ {
+ printf ("nanosleep time %lu.%.9lu outside reasonable range\n",
+ d.tv_sec, d.tv_nsec);
+ result = 1;
+ }
+ }
+ }
+
+ if (kill (child, SIGKILL) != 0)
+ {
+ perror ("kill");
+ result = 2;
+ goto done;
+ }
+
+ /* Wait long enough to let the child finish dying. */
+
+ sleeptime.tv_nsec = 200000000;
+ nanosleep (&sleeptime, NULL);
+
+ struct timespec dead;
+ if (clock_gettime (child_clock, &dead) < 0)
+ {
+ printf ("clock_gettime on dead PID %d clock %lx => %s\n",
+ child, (unsigned long int) child_clock, strerror (errno));
+ result = 1;
+ goto done;
+ }
+ printf ("dead PID %d => %lu.%.9lu\n",
+ child, dead.tv_sec, dead.tv_nsec);
+
+ diff.tv_sec = dead.tv_sec - after.tv_sec;
+ diff.tv_nsec = dead.tv_nsec - after.tv_nsec;
+ if (diff.tv_nsec < 0)
+ {
+ --diff.tv_sec;
+ diff.tv_nsec += 1000000000;
+ }
+ if (diff.tv_sec != 0 || diff.tv_nsec > 200000000)
+ {
+ printf ("dead - after %lu.%.9lu outside reasonable range\n",
+ diff.tv_sec, diff.tv_nsec);
+ result = 1;
+ }
+
+ /* Now reap the child and verify that its clock is no longer valid. */
+ {
+ int x;
+ if (waitpid (child, &x, 0) != child)
+ {
+ perror ("waitpid");
+ result = 1;
+ }
+ }
+
+ if (clock_gettime (child_clock, &dead) == 0)
+ {
+ printf ("clock_gettime on reaped PID %d clock %lx => %lu%.9lu\n",
+ child, (unsigned long int) child_clock,
+ dead.tv_sec, dead.tv_nsec);
+ result = 1;
+ }
+ else
+ {
+ if (errno != EINVAL)
+ result = 1;
+ printf ("clock_gettime on reaped PID %d clock %lx => %s\n",
+ child, (unsigned long int) child_clock, strerror (errno));
+ }
+
+ if (clock_getres (child_clock, &dead) == 0)
+ {
+ printf ("clock_getres on reaped PID %d clock %lx => %lu%.9lu\n",
+ child, (unsigned long int) child_clock,
+ dead.tv_sec, dead.tv_nsec);
+ result = 1;
+ }
+ else
+ {
+ if (errno != EINVAL)
+ result = 1;
+ printf ("clock_getres on reaped PID %d clock %lx => %s\n",
+ child, (unsigned long int) child_clock, strerror (errno));
+ }
+
+ return result;
+
+ done:
+ {
+ if (kill (child, SIGKILL) != 0 && errno != ESRCH)
+ {
+ perror ("kill");
+ return 2;
+ }
+ int x;
+ if (waitpid (child, &x, 0) != child && errno != ECHILD)
+ {
+ perror ("waitpid");
+ return 2;
+ }
+ }
+
+ return result;
+}
+
+
+#define TIMEOUT 5
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/rt/tst-cpuclock2.c b/rt/tst-cpuclock2.c
new file mode 100644
index 0000000000..d1621f3d01
--- /dev/null
+++ b/rt/tst-cpuclock2.c
@@ -0,0 +1,332 @@
+/* Test program for process and thread CPU clocks.
+ Copyright (C) 2005 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include <unistd.h>
+
+#if (_POSIX_THREADS - 0) <= 0
+
+# define TEST_FUNCTION 0
+
+#else
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <fcntl.h>
+#include <string.h>
+#include <errno.h>
+#include <pthread.h>
+
+static pthread_barrier_t barrier;
+
+/* This function is intended to rack up both user and system time. */
+static void *
+chew_cpu (void *arg)
+{
+ pthread_barrier_wait (&barrier);
+
+ while (1)
+ {
+ static volatile char buf[4096];
+ for (int i = 0; i < 100; ++i)
+ for (size_t j = 0; j < sizeof buf; ++j)
+ buf[j] = 0xaa;
+ int nullfd = open ("/dev/null", O_WRONLY);
+ for (int i = 0; i < 100; ++i)
+ for (size_t j = 0; j < sizeof buf; ++j)
+ buf[j] = 0xbb;
+ write (nullfd, (char *) buf, sizeof buf);
+ close (nullfd);
+ }
+
+ return NULL;
+}
+
+static unsigned long long int
+tsdiff (const struct timespec *before, const struct timespec *after)
+{
+ struct timespec diff = { .tv_sec = after->tv_sec - before->tv_sec,
+ .tv_nsec = after->tv_nsec - before->tv_nsec };
+ while (diff.tv_nsec < 0)
+ {
+ --diff.tv_sec;
+ diff.tv_nsec += 1000000000;
+ }
+ return diff.tv_sec * 1000000000ULL + diff.tv_nsec;
+}
+
+static unsigned long long int
+test_nanosleep (clockid_t clock, const char *which,
+ const struct timespec *before, int *bad)
+{
+ const struct timespec sleeptime = { .tv_nsec = 100000000 };
+ int e = clock_nanosleep (clock, 0, &sleeptime, NULL);
+ if (e == EINVAL || e == ENOTSUP || e == ENOSYS)
+ {
+ printf ("clock_nanosleep not supported for %s CPU clock: %s\n",
+ which, strerror (e));
+ return 0;
+ }
+ if (e != 0)
+ {
+ printf ("clock_nanosleep on %s CPU clock: %s\n", which, strerror (e));
+ *bad = 1;
+ return 0;
+ }
+
+ struct timespec after;
+ if (clock_gettime (clock, &after) < 0)
+ {
+ printf ("clock_gettime on %s CPU clock %lx => %s\n",
+ which, (unsigned long int) clock, strerror (errno));
+ *bad = 1;
+ return 0;
+ }
+
+ unsigned long long int diff = tsdiff (before, &after);
+ if (diff < sleeptime.tv_nsec || diff > sleeptime.tv_nsec * 2)
+ {
+ printf ("clock_nanosleep on %s slept %llu (outside reasonable range)\n",
+ which, diff);
+ *bad = 1;
+ return diff;
+ }
+
+ struct timespec sleeptimeabs = sleeptime;
+ sleeptimeabs.tv_sec += after.tv_sec;
+ sleeptimeabs.tv_nsec += after.tv_nsec;
+ while (sleeptimeabs.tv_nsec > 1000000000)
+ {
+ ++sleeptimeabs.tv_sec;
+ sleeptimeabs.tv_nsec -= 1000000000;
+ }
+ e = clock_nanosleep (clock, TIMER_ABSTIME, &sleeptimeabs, NULL);
+ if (e != 0)
+ {
+ printf ("absolute clock_nanosleep on %s CPU clock: %s\n",
+ which, strerror (e));
+ *bad = 1;
+ return diff;
+ }
+
+ struct timespec afterabs;
+ if (clock_gettime (clock, &afterabs) < 0)
+ {
+ printf ("clock_gettime on %s CPU clock %lx => %s\n",
+ which, (unsigned long int) clock, strerror (errno));
+ *bad = 1;
+ return diff;
+ }
+
+ unsigned long long int sleepdiff = tsdiff (&sleeptimeabs, &afterabs);
+ if (sleepdiff > sleeptime.tv_nsec)
+ {
+ printf ("\
+absolute clock_nanosleep on %s %llu past target (outside reasonable range)\n",
+ which, sleepdiff);
+ *bad = 1;
+ }
+
+ unsigned long long int diffabs = tsdiff (&after, &afterabs);
+ if (diffabs < sleeptime.tv_nsec || diffabs > sleeptime.tv_nsec * 2)
+ {
+ printf ("\
+absolute clock_nanosleep on %s slept %llu (outside reasonable range)\n",
+ which, diffabs);
+ *bad = 1;
+ }
+
+ return diff + diffabs;
+}
+
+
+
+static int
+do_test (void)
+{
+ int result = 0;
+ clockid_t process_clock, th_clock, my_thread_clock;
+ int e;
+ pthread_t th;
+
+ e = clock_getcpuclockid (0, &process_clock);
+ if (e != 0)
+ {
+ printf ("clock_getcpuclockid on self => %s\n", strerror (e));
+ return 1;
+ }
+
+ e = pthread_getcpuclockid (pthread_self (), &my_thread_clock);
+ if (e != 0)
+ {
+ printf ("pthread_getcpuclockid on self => %s\n", strerror (e));
+ return 1;
+ }
+
+ /* This is a kludge. This test fails if the semantics of thread and
+ process clocks are wrong. The old code using hp-timing without kernel
+ support has bogus semantics if there are context switches. We don't
+ fail to report failure when the proper functionality is not available
+ in the kernel. It so happens that Linux kernels without correct CPU
+ clock support also lack CPU timer support, so we use use that to guess
+ that we are using the bogus code and not test it. */
+ timer_t t;
+ if (timer_create (my_thread_clock, NULL, &t) != 0)
+ {
+ printf ("timer_create: %m\n");
+ puts ("No support for CPU clocks with good semantics, skipping test");
+ return 0;
+ }
+ timer_delete (t);
+
+
+ pthread_barrier_init (&barrier, NULL, 2);
+
+ e = pthread_create (&th, NULL, chew_cpu, NULL);
+ if (e != 0)
+ {
+ printf ("pthread_create: %s\n", strerror (e));
+ return 1;
+ }
+
+ e = pthread_getcpuclockid (th, &th_clock);
+ if (e == ENOENT || e == ENOSYS || e == ENOTSUP)
+ {
+ puts ("pthread_getcpuclockid does not support other threads");
+ return 1;
+ }
+
+ pthread_barrier_wait (&barrier);
+
+ struct timespec res;
+ if (clock_getres (th_clock, &res) < 0)
+ {
+ printf ("clock_getres on thread clock %lx => %s\n",
+ (unsigned long int) th_clock, strerror (errno));
+ result = 1;
+ return 1;
+ }
+ printf ("live thread clock %lx resolution %lu.%.9lu\n",
+ (unsigned long int) th_clock, res.tv_sec, res.tv_nsec);
+
+ struct timespec process_before, process_after;
+ if (clock_gettime (process_clock, &process_before) < 0)
+ {
+ printf ("clock_gettime on process clock %lx => %s\n",
+ (unsigned long int) th_clock, strerror (errno));
+ return 1;
+ }
+
+ struct timespec before, after;
+ if (clock_gettime (th_clock, &before) < 0)
+ {
+ printf ("clock_gettime on live thread clock %lx => %s\n",
+ (unsigned long int) th_clock, strerror (errno));
+ return 1;
+ }
+ printf ("live thread before sleep => %lu.%.9lu\n",
+ before.tv_sec, before.tv_nsec);
+
+ struct timespec me_before, me_after;
+ if (clock_gettime (my_thread_clock, &me_before) < 0)
+ {
+ printf ("clock_gettime on live thread clock %lx => %s\n",
+ (unsigned long int) th_clock, strerror (errno));
+ return 1;
+ }
+ printf ("self thread before sleep => %lu.%.9lu\n",
+ me_before.tv_sec, me_before.tv_nsec);
+
+ struct timespec sleeptime = { .tv_nsec = 500000000 };
+ nanosleep (&sleeptime, NULL);
+
+ if (clock_gettime (th_clock, &after) < 0)
+ {
+ printf ("clock_gettime on live thread clock %lx => %s\n",
+ (unsigned long int) th_clock, strerror (errno));
+ return 1;
+ }
+ printf ("live thread after sleep => %lu.%.9lu\n",
+ after.tv_sec, after.tv_nsec);
+
+ if (clock_gettime (process_clock, &process_after) < 0)
+ {
+ printf ("clock_gettime on process clock %lx => %s\n",
+ (unsigned long int) th_clock, strerror (errno));
+ return 1;
+ }
+
+ if (clock_gettime (my_thread_clock, &me_after) < 0)
+ {
+ printf ("clock_gettime on live thread clock %lx => %s\n",
+ (unsigned long int) th_clock, strerror (errno));
+ return 1;
+ }
+ printf ("self thread after sleep => %lu.%.9lu\n",
+ me_after.tv_sec, me_after.tv_nsec);
+
+ unsigned long long int th_diff = tsdiff (&before, &after);
+ unsigned long long int pdiff = tsdiff (&process_before, &process_after);
+ unsigned long long int my_diff = tsdiff (&me_before, &me_after);
+
+ if (th_diff < 100000000 || th_diff > 600000000)
+ {
+ printf ("thread before - after %llu outside reasonable range\n",
+ th_diff);
+ result = 1;
+ }
+
+ if (my_diff > 100000000)
+ {
+ printf ("self thread before - after %llu outside reasonable range\n",
+ my_diff);
+ result = 1;
+ }
+
+ if (pdiff < th_diff)
+ {
+ printf ("process before - after %llu outside reasonable range (%llu)\n",
+ pdiff, th_diff);
+ result = 1;
+ }
+
+ process_after.tv_nsec += test_nanosleep (th_clock, "thread",
+ &after, &result);
+ process_after.tv_nsec += test_nanosleep (process_clock, "process",
+ &process_after, &result);
+ test_nanosleep (CLOCK_PROCESS_CPUTIME_ID,
+ "PROCESS_CPUTIME_ID", &process_after, &result);
+
+ pthread_cancel (th);
+
+ e = clock_nanosleep (CLOCK_THREAD_CPUTIME_ID, 0, &sleeptime, NULL);
+ if (e != EINVAL)
+ {
+ printf ("clock_nanosleep CLOCK_THREAD_CPUTIME_ID: %s\n",
+ strerror (e));
+ result = 1;
+ }
+
+ return result;
+}
+# define TIMEOUT 8
+# define TEST_FUNCTION do_test ()
+#endif
+
+#include "../test-skeleton.c"
diff --git a/rt/tst-cputimer1.c b/rt/tst-cputimer1.c
new file mode 100644
index 0000000000..8f5dd76cf2
--- /dev/null
+++ b/rt/tst-cputimer1.c
@@ -0,0 +1,68 @@
+/* Tests for POSIX timer implementation using process CPU clock. */
+
+#include <unistd.h>
+
+#if _POSIX_THREADS && defined _POSIX_CPUTIME
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <time.h>
+#include <pthread.h>
+
+#define TEST_CLOCK CLOCK_PROCESS_CPUTIME_ID
+#define TEST_CLOCK_MISSING(clock) \
+ (setup_test () ? "process CPU clock timer support" : NULL)
+
+/* This function is intended to rack up both user and system time. */
+static void *
+chew_cpu (void *arg)
+{
+ while (1)
+ {
+ static volatile char buf[4096];
+ for (int i = 0; i < 100; ++i)
+ for (size_t j = 0; j < sizeof buf; ++j)
+ buf[j] = 0xaa;
+ int nullfd = open ("/dev/null", O_WRONLY);
+ for (int i = 0; i < 100; ++i)
+ for (size_t j = 0; j < sizeof buf; ++j)
+ buf[j] = 0xbb;
+ write (nullfd, (char *) buf, sizeof buf);
+ close (nullfd);
+ }
+
+ return NULL;
+}
+
+static int
+setup_test (void)
+{
+ /* Test timers on our own process CPU clock by having a worker thread
+ eating CPU. First make sure we can make such timers at all. */
+
+ timer_t t;
+ if (timer_create (TEST_CLOCK, NULL, &t) != 0)
+ {
+ printf ("timer_create: %m\n");
+ return 1;
+ }
+ timer_delete (t);
+
+ pthread_t th;
+ int e = pthread_create (&th, NULL, chew_cpu, NULL);
+ if (e != 0)
+ {
+ printf ("pthread_create: %s\n", strerror (e));
+ exit (1);
+ }
+
+ return 0;
+}
+
+#else
+# define TEST_CLOCK_MISSING(clock) "process clocks"
+#endif
+
+#include "tst-timer4.c"
diff --git a/rt/tst-cputimer2.c b/rt/tst-cputimer2.c
new file mode 100644
index 0000000000..397d7998c0
--- /dev/null
+++ b/rt/tst-cputimer2.c
@@ -0,0 +1,83 @@
+/* Tests for POSIX timer implementation using thread CPU clock. */
+
+#include <unistd.h>
+
+#if _POSIX_THREADS && defined _POSIX_CPUTIME
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <time.h>
+#include <pthread.h>
+
+static clockid_t worker_thread_clock;
+
+#define TEST_CLOCK worker_thread_clock
+#define TEST_CLOCK_MISSING(clock) \
+ (setup_test () ? "thread CPU clock timer support" : NULL)
+
+/* This function is intended to rack up both user and system time. */
+static void *
+chew_cpu (void *arg)
+{
+ while (1)
+ {
+ static volatile char buf[4096];
+ for (int i = 0; i < 100; ++i)
+ for (size_t j = 0; j < sizeof buf; ++j)
+ buf[j] = 0xaa;
+ int nullfd = open ("/dev/null", O_WRONLY);
+ for (int i = 0; i < 100; ++i)
+ for (size_t j = 0; j < sizeof buf; ++j)
+ buf[j] = 0xbb;
+ write (nullfd, (char *) buf, sizeof buf);
+ close (nullfd);
+ }
+
+ return NULL;
+}
+
+static int
+setup_test (void)
+{
+ /* Test timers on a thread CPU clock by having a worker thread eating
+ CPU. First make sure we can make such timers at all. */
+
+ pthread_t th;
+ int e = pthread_create (&th, NULL, chew_cpu, NULL);
+ if (e != 0)
+ {
+ printf ("pthread_create: %s\n", strerror (e));
+ exit (1);
+ }
+
+ e = pthread_getcpuclockid (th, &worker_thread_clock);
+ if (e == EPERM || e == ENOENT || e == ENOTSUP)
+ {
+ puts ("pthread_getcpuclockid does not support other threads");
+ return 1;
+ }
+ if (e != 0)
+ {
+ printf ("pthread_getcpuclockid: %s\n", strerror (e));
+ exit (1);
+ }
+
+ timer_t t;
+ if (timer_create (TEST_CLOCK, NULL, &t) != 0)
+ {
+ printf ("timer_create: %m\n");
+ return 1;
+ }
+ timer_delete (t);
+
+ return 0;
+}
+
+#else
+# define TEST_CLOCK_MISSING(clock) "process clocks"
+#endif
+
+#include "tst-timer4.c"
diff --git a/rt/tst-cputimer3.c b/rt/tst-cputimer3.c
new file mode 100644
index 0000000000..056766a377
--- /dev/null
+++ b/rt/tst-cputimer3.c
@@ -0,0 +1,130 @@
+/* Tests for POSIX timer implementation using another process's CPU clock. */
+
+#include <unistd.h>
+
+#if _POSIX_THREADS && defined _POSIX_CPUTIME
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <time.h>
+#include <signal.h>
+#include <sys/wait.h>
+
+static clockid_t child_clock;
+
+#define TEST_CLOCK child_clock
+#define TEST_CLOCK_MISSING(clock) \
+ (setup_test () ? "other-process CPU clock timer support" : NULL)
+
+/* This function is intended to rack up both user and system time. */
+static void
+chew_cpu (void)
+{
+ while (1)
+ {
+ static volatile char buf[4096];
+ for (int i = 0; i < 100; ++i)
+ for (size_t j = 0; j < sizeof buf; ++j)
+ buf[j] = 0xaa;
+ int nullfd = open ("/dev/null", O_WRONLY);
+ for (int i = 0; i < 100; ++i)
+ for (size_t j = 0; j < sizeof buf; ++j)
+ buf[j] = 0xbb;
+ write (nullfd, (char *) buf, sizeof buf);
+ close (nullfd);
+ if (getppid () == 1)
+ _exit (2);
+ }
+}
+
+static pid_t child;
+static void
+cleanup_child (void)
+{
+ if (child <= 0)
+ return;
+ if (kill (child, SIGKILL) < 0 && errno != ESRCH)
+ printf ("cannot kill child %d: %m\n", child);
+ else
+ {
+ int status;
+ errno = 0;
+ if (waitpid (child, &status, 0) != child)
+ printf ("waitpid %d: %m\n", child);
+ }
+}
+#define CLEANUP_HANDLER cleanup_child ()
+
+static int
+setup_test (void)
+{
+ /* Test timers on a process CPU clock by having a child process eating
+ CPU. First make sure we can make such timers at all. */
+
+ int pipefd[2];
+ if (pipe (pipefd) < 0)
+ {
+ printf ("pipe: %m\n");
+ exit (1);
+ }
+
+ child = fork ();
+
+ if (child == 0)
+ {
+ char c;
+ close (pipefd[1]);
+ if (read (pipefd[0], &c, 1) == 1)
+ chew_cpu ();
+ _exit (1);
+ }
+
+ if (child < 0)
+ {
+ printf ("fork: %m\n");
+ exit (1);
+ }
+
+ atexit (&cleanup_child);
+
+ close (pipefd[0]);
+
+ int e = clock_getcpuclockid (child, &child_clock);
+ if (e == EPERM)
+ {
+ puts ("clock_getcpuclockid does not support other processes");
+ return 1;
+ }
+ if (e != 0)
+ {
+ printf ("clock_getcpuclockid: %s\n", strerror (e));
+ exit (1);
+ }
+
+ timer_t t;
+ if (timer_create (TEST_CLOCK, NULL, &t) != 0)
+ {
+ printf ("timer_create: %m\n");
+ return 1;
+ }
+ timer_delete (t);
+
+ /* Get the child started chewing. */
+ if (write (pipefd[1], "x", 1) != 1)
+ {
+ printf ("write to pipe: %m\n");
+ return 1;
+ }
+ close (pipefd[1]);
+
+ return 0;
+}
+
+#else
+# define TEST_CLOCK_MISSING(clock) "process clocks"
+#endif
+
+#include "tst-timer4.c"
diff --git a/stdio-common/vfscanf.c b/stdio-common/vfscanf.c
index c641d2d371..be008dc687 100644
--- a/stdio-common/vfscanf.c
+++ b/stdio-common/vfscanf.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991-2002, 2003, 2004 Free Software Foundation, Inc.
+/* Copyright (C) 1991-2002, 2003, 2004, 2005 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -1602,6 +1602,8 @@ _IO_vfscanf (s, format, argptr, errp)
if (c == EOF)
input_error ();
+ got_dot = got_e = 0;
+
/* Check for a sign. */
if (c == L_('-') || c == L_('+'))
{
@@ -1629,14 +1631,13 @@ _IO_vfscanf (s, format, argptr, errp)
const char *cmpp = decimal;
int avail = width > 0 ? width : INT_MAX;
- while ((unsigned char) *cmpp == c && avail > 0)
+ while ((unsigned char) *cmpp == c && avail-- > 0)
if (*++cmpp == '\0')
break;
else
{
if (inchar () == EOF)
break;
- --avail;
}
if (*cmpp != '\0')
@@ -1652,6 +1653,17 @@ _IO_vfscanf (s, format, argptr, errp)
conv_error ();
}
+ else
+ {
+ /* Add all the characters. */
+ for (cmpp = decimal; *cmpp != '\0'; ++cmpp)
+ ADDW ((unsigned char) *cmpp);
+ if (width > 0)
+ width = avail;
+ got_dot = 1;
+
+ c = inchar ();
+ }
if (width > 0)
width = avail;
#endif
@@ -1759,7 +1771,6 @@ _IO_vfscanf (s, format, argptr, errp)
}
}
- got_dot = got_e = 0;
do
{
if (ISDIGIT (c))
diff --git a/stdlib/canonicalize.c b/stdlib/canonicalize.c
index 2168bbd90e..9fc24b7d92 100644
--- a/stdlib/canonicalize.c
+++ b/stdlib/canonicalize.c
@@ -1,5 +1,5 @@
/* Return the canonical absolute name of a given file.
- Copyright (C) 1996-2001, 2002, 2004 Free Software Foundation, Inc.
+ Copyright (C) 1996-2002, 2004, 2005 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -199,6 +199,11 @@ __realpath (const char *name, char *resolved)
if (dest > rpath + 1)
while ((--dest)[-1] != '/');
}
+ else if (!S_ISDIR (st.st_mode) && *end != '\0')
+ {
+ __set_errno (ENOTDIR);
+ goto error;
+ }
}
}
if (dest > rpath + 1 && dest[-1] == '/')
diff --git a/stdlib/test-canon.c b/stdlib/test-canon.c
index f070df74a0..54267465b8 100644
--- a/stdlib/test-canon.c
+++ b/stdlib/test-canon.c
@@ -1,5 +1,5 @@
/* Test program for returning the canonical absolute name of a given file.
- Copyright (C) 1996, 1997, 2000, 2002, 2004 Free Software Foundation, Inc.
+ Copyright (C) 1996,1997,2000,2002,2004,2005 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by David Mosberger <davidm@azstarnet.com>.
@@ -89,7 +89,10 @@ struct {
{"SYMLINK_5", 0, "./doesNotExist", ENOENT},
{"SYMLINK_5/foobar", 0, "./doesNotExist", ENOENT},
{"doesExist/../../stdlib/doesExist", "./doesExist"},
- {"doesExist/.././../stdlib/.", "."}
+ {"doesExist/.././../stdlib/.", "."},
+ /* 30 */
+ {"./doesExist/someFile/", 0, "./doesExist/someFile", ENOTDIR},
+ {"./doesExist/someFile/..", 0, "./doesExist/someFile", ENOTDIR},
};
@@ -118,7 +121,7 @@ int
do_test (int argc, char ** argv)
{
char * result;
- int fd, i, errors = 0;
+ int i, errors = 0;
char buf[PATH_MAX];
getcwd (cwd, sizeof(buf));
@@ -154,7 +157,9 @@ do_test (int argc, char ** argv)
for (i = 0; i < (int) (sizeof (symlinks) / sizeof (symlinks[0])); ++i)
symlink (symlinks[i].value, symlinks[i].name);
- fd = open("doesExist", O_CREAT | O_EXCL, 0777);
+ int has_dir = mkdir ("doesExist", 0777) == 0;
+
+ int fd = has_dir ? creat ("doesExist/someFile", 0777) : -1;
for (i = 0; i < (int) (sizeof (tests) / sizeof (tests[0])); ++i)
{
@@ -208,7 +213,10 @@ do_test (int argc, char ** argv)
}
if (fd >= 0)
- unlink("doesExist");
+ unlink ("doesExist/someFile");
+
+ if (has_dir)
+ rmdir ("doesExist");
for (i = 0; i < (int) (sizeof (symlinks) / sizeof (symlinks[0])); ++i)
unlink (symlinks[i].name);
diff --git a/sunrpc/xdr.c b/sunrpc/xdr.c
index 2f894fbba7..411cbe1ab1 100644
--- a/sunrpc/xdr.c
+++ b/sunrpc/xdr.c
@@ -131,7 +131,7 @@ bool_t
xdr_u_int (XDR *xdrs, u_int *up)
{
#if UINT_MAX < ULONG_MAX
- u_long l;
+ long l;
switch (xdrs->x_op)
{
@@ -144,7 +144,7 @@ xdr_u_int (XDR *xdrs, u_int *up)
{
return FALSE;
}
- *up = (u_int) l;
+ *up = (u_int) (u_long) l;
case XDR_FREE:
return TRUE;
}
diff --git a/sysdeps/posix/clock_getres.c b/sysdeps/posix/clock_getres.c
index a2d466607e..f4dc21f8af 100644
--- a/sysdeps/posix/clock_getres.c
+++ b/sysdeps/posix/clock_getres.c
@@ -1,4 +1,5 @@
-/* Copyright (C) 1999, 2000, 2001, 2003 Free Software Foundation, Inc.
+/* clock_getres -- Get the resolution of a POSIX clockid_t.
+ Copyright (C) 1999, 2000, 2001, 2003, 2004 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -24,11 +25,55 @@
#include <libc-internal.h>
-#if HP_TIMING_AVAIL && !defined HANDLED_CPUTIME
-/* Clock frequency of the processor. */
-static long int nsec;
+#if HP_TIMING_AVAIL
+static long int nsec; /* Clock frequency of the processor. */
+
+static inline int
+hp_timing_getres (struct timespec *res)
+{
+ if (__builtin_expect (nsec == 0, 0))
+ {
+ hp_timing_t freq;
+
+ /* This can only happen if we haven't initialized the `nsec'
+ variable yet. Do this now. We don't have to protect this
+ code against multiple execution since all of them should
+ lead to the same result. */
+ freq = __get_clockfreq ();
+ if (__builtin_expect (freq == 0, 0))
+ /* Something went wrong. */
+ return -1;
+
+ nsec = MAX (UINT64_C (1000000000) / freq, 1);
+ }
+
+ /* Fill in the values.
+ The seconds are always zero (unless we have a 1Hz machine). */
+ res->tv_sec = 0;
+ res->tv_nsec = nsec;
+
+ return 0;
+}
#endif
+static inline int
+realtime_getres (struct timespec *res)
+{
+ long int clk_tck = sysconf (_SC_CLK_TCK);
+
+ if (__builtin_expect (clk_tck != -1, 1))
+ {
+ /* This implementation assumes that the realtime clock has a
+ resolution higher than 1 second. This is the case for any
+ reasonable implementation. */
+ res->tv_sec = 0;
+ res->tv_nsec = 1000000000 / clk_tck;
+ return 0;
+ }
+
+ return -1;
+}
+
/* Get resolution of clock. */
int
@@ -38,69 +83,33 @@ clock_getres (clockid_t clock_id, struct timespec *res)
switch (clock_id)
{
-#define HANDLE_REALTIME \
- do { \
- long int clk_tck = sysconf (_SC_CLK_TCK); \
- \
- if (__builtin_expect (clk_tck != -1, 1)) \
- { \
- /* This implementation assumes that the realtime clock has a \
- resolution higher than 1 second. This is the case for any \
- reasonable implementation. */ \
- res->tv_sec = 0; \
- res->tv_nsec = 1000000000 / clk_tck; \
- \
- retval = 0; \
- } \
- } while (0)
-
#ifdef SYSDEP_GETRES
SYSDEP_GETRES;
#endif
#ifndef HANDLED_REALTIME
case CLOCK_REALTIME:
- HANDLE_REALTIME;
+ retval = realtime_getres (res);
break;
#endif /* handled REALTIME */
default:
+#ifdef SYSDEP_GETRES_CPU
+ SYSDEP_GETRES_CPU;
+#endif
#if HP_TIMING_AVAIL
if ((clock_id & ((1 << CLOCK_IDFIELD_SIZE) - 1))
- != CLOCK_THREAD_CPUTIME_ID)
+ == CLOCK_THREAD_CPUTIME_ID)
+ retval = hp_timing_getres (res);
+ else
#endif
- {
- __set_errno (EINVAL);
- break;
- }
+ __set_errno (EINVAL);
+ break;
#if HP_TIMING_AVAIL && !defined HANDLED_CPUTIME
- /* FALLTHROUGH. */
case CLOCK_PROCESS_CPUTIME_ID:
- {
- if (__builtin_expect (nsec == 0, 0))
- {
- hp_timing_t freq;
-
- /* This can only happen if we haven't initialized the `freq'
- variable yet. Do this now. We don't have to protect this
- code against multiple execution since all of them should
- lead to the same result. */
- freq = __get_clockfreq ();
- if (__builtin_expect (freq == 0, 0))
- /* Something went wrong. */
- break;
-
- nsec = MAX (UINT64_C (1000000000) / freq, 1);
- }
-
- /* File in the values. The seconds are always zero (unless we
- have a 1Hz machine). */
- res->tv_sec = 0;
- res->tv_nsec = nsec;
-
- retval = 0;
- }
+ case CLOCK_THREAD_CPUTIME_ID:
+ retval = hp_timing_getres (res);
break;
#endif
}
diff --git a/sysdeps/sparc/sparc32/elf/start.S b/sysdeps/sparc/sparc32/elf/start.S
index 2787fd27f8..4c7fb5bd23 100644
--- a/sysdeps/sparc/sparc32/elf/start.S
+++ b/sysdeps/sparc/sparc32/elf/start.S
@@ -92,3 +92,9 @@ _start:
unimp
.size _start, .-_start
+
+/* Define a symbol for the first piece of initialized data. */
+ .data
+ .globl __data_start
+__data_start:
+weak_alias (__data_start, data_start)
diff --git a/sysdeps/sparc/sparc64/elf/start.S b/sysdeps/sparc/sparc64/elf/start.S
index b0ef9d355d..c008c6cea0 100644
--- a/sysdeps/sparc/sparc64/elf/start.S
+++ b/sysdeps/sparc/sparc64/elf/start.S
@@ -93,3 +93,9 @@ _start:
illtrap 0
.size _start, .-_start
+
+/* Define a symbol for the first piece of initialized data. */
+ .data
+ .globl __data_start
+__data_start:
+weak_alias (__data_start, data_start)
diff --git a/sysdeps/unix/clock_gettime.c b/sysdeps/unix/clock_gettime.c
index 7a3db29744..b7b0428e0b 100644
--- a/sysdeps/unix/clock_gettime.c
+++ b/sysdeps/unix/clock_gettime.c
@@ -1,4 +1,5 @@
-/* Copyright (C) 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+/* clock_gettime -- Get the current time from a POSIX clockid_t. Unix version.
+ Copyright (C) 1999,2000,2001,2002,2003,2004 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -35,9 +36,58 @@ static hp_timing_t freq;
extern int __pthread_clock_gettime (clockid_t clock_id, hp_timing_t freq,
struct timespec *tp)
__attribute__ ((__weak__));
+
+static int
+hp_timing_gettime (clockid_t clock_id, struct timespec *tp)
+{
+ hp_timing_t tsc;
+
+ if (__builtin_expect (freq == 0, 0))
+ {
+ /* This can only happen if we haven't initialized the `freq'
+ variable yet. Do this now. We don't have to protect this
+ code against multiple execution since all of them should
+ lead to the same result. */
+ freq = __get_clockfreq ();
+ if (__builtin_expect (freq == 0, 0))
+ /* Something went wrong. */
+ return -1;
+ }
+
+ if (clock_id != CLOCK_PROCESS_CPUTIME_ID
+ && __pthread_clock_gettime != NULL)
+ return __pthread_clock_gettime (clock_id, freq, tp);
+
+ /* Get the current counter. */
+ HP_TIMING_NOW (tsc);
+
+ /* Compute the offset since the start time of the process. */
+ tsc -= GL(dl_cpuclock_offset);
+
+ /* Compute the seconds. */
+ tp->tv_sec = tsc / freq;
+
+ /* And the nanoseconds. This computation should be stable until
+ we get machines with about 16GHz frequency. */
+ tp->tv_nsec = ((tsc % freq) * UINT64_C (1000000000)) / freq;
+
+ return 0;
+}
#endif
+static inline int
+realtime_gettime (struct timespec *tp)
+{
+ struct timeval tv;
+ int retval = gettimeofday (&tv, NULL);
+ if (retval == 0)
+ /* Convert into `timespec'. */
+ TIMEVAL_TO_TIMESPEC (&tv, tp);
+ return retval;
+}
+
+
/* Get current value of CLOCK and store it in TP. */
int
clock_gettime (clockid_t clock_id, struct timespec *tp)
@@ -46,15 +96,6 @@ clock_gettime (clockid_t clock_id, struct timespec *tp)
switch (clock_id)
{
-#define HANDLE_REALTIME \
- do { \
- struct timeval tv; \
- retval = gettimeofday (&tv, NULL); \
- if (retval == 0) \
- /* Convert into `timespec'. */ \
- TIMEVAL_TO_TIMESPEC (&tv, tp); \
- } while (0)
-
#ifdef SYSDEP_GETTIME
SYSDEP_GETTIME;
#endif
@@ -66,56 +107,22 @@ clock_gettime (clockid_t clock_id, struct timespec *tp)
#endif
default:
+#ifdef SYSDEP_GETTIME_CPU
+ SYSDEP_GETTIME_CPU;
+#endif
#if HP_TIMING_AVAIL
if ((clock_id & ((1 << CLOCK_IDFIELD_SIZE) - 1))
- != CLOCK_THREAD_CPUTIME_ID)
+ == CLOCK_THREAD_CPUTIME_ID)
+ retval = hp_timing_gettime (clock_id, tp);
+ else
#endif
- {
- __set_errno (EINVAL);
- break;
- }
+ __set_errno (EINVAL);
+ break;
-#if HP_TIMING_AVAIL
- /* FALLTHROUGH. */
+#if HP_TIMING_AVAIL && !defined HANDLED_CPUTIME
case CLOCK_PROCESS_CPUTIME_ID:
- {
- hp_timing_t tsc;
-
- if (__builtin_expect (freq == 0, 0))
- {
- /* This can only happen if we haven't initialized the `freq'
- variable yet. Do this now. We don't have to protect this
- code against multiple execution since all of them should
- lead to the same result. */
- freq = __get_clockfreq ();
- if (__builtin_expect (freq == 0, 0))
- /* Something went wrong. */
- break;
- }
-
- if (clock_id != CLOCK_PROCESS_CPUTIME_ID
- && __pthread_clock_gettime != NULL)
- {
- retval = __pthread_clock_gettime (clock_id, freq, tp);
- break;
- }
-
- /* Get the current counter. */
- HP_TIMING_NOW (tsc);
-
- /* Compute the offset since the start time of the process. */
- tsc -= GL(dl_cpuclock_offset);
-
- /* Compute the seconds. */
- tp->tv_sec = tsc / freq;
-
- /* And the nanoseconds. This computation should be stable until
- we get machines with about 16GHz frequency. */
- tp->tv_nsec = ((tsc % freq) * UINT64_C (1000000000)) / freq;
-
- retval = 0;
- }
- break;
+ retval = hp_timing_gettime (clock_id, tp);
+ break;
#endif
}
diff --git a/sysdeps/unix/sysv/linux/clock_getcpuclockid.c b/sysdeps/unix/sysv/linux/clock_getcpuclockid.c
new file mode 100644
index 0000000000..ac893c0a77
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/clock_getcpuclockid.c
@@ -0,0 +1,103 @@
+/* clock_getcpuclockid -- Get a clockid_t for process CPU time. Linux version.
+ Copyright (C) 2004 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include <errno.h>
+#include <time.h>
+#include <unistd.h>
+#include "kernel-features.h"
+#include "kernel-posix-cpu-timers.h"
+
+#ifndef HAS_CPUCLOCK
+# define HAS_CPUCLOCK 1
+#endif
+
+int
+clock_getcpuclockid (pid_t pid, clockid_t *clock_id)
+{
+#ifdef __NR_clock_getres
+ /* The clockid_t value is a simple computation from the PID.
+ But we do a clock_getres call to validate it. */
+
+ const clockid_t pidclock = MAKE_PROCESS_CPUCLOCK (pid, CPUCLOCK_SCHED);
+
+# if !(__ASSUME_POSIX_CPU_TIMERS > 0)
+ extern int __libc_missing_posix_cpu_timers attribute_hidden;
+# if !(__ASSUME_POSIX_TIMERS > 0)
+ extern int __libc_missing_posix_timers attribute_hidden;
+ if (__libc_missing_posix_timers && !__libc_missing_posix_cpu_timers)
+ __libc_missing_posix_cpu_timers = 1;
+# endif
+ if (!__libc_missing_posix_cpu_timers)
+# endif
+ {
+ INTERNAL_SYSCALL_DECL (err);
+ int r = INTERNAL_SYSCALL (clock_getres, err, 2, pidclock, NULL);
+ if (!INTERNAL_SYSCALL_ERROR_P (r, err))
+ {
+ *clock_id = pidclock;
+ return 0;
+ }
+
+# if !(__ASSUME_POSIX_TIMERS > 0)
+ if (INTERNAL_SYSCALL_ERRNO (r, err) == ENOSYS)
+ {
+ /* The kernel doesn't support these calls at all. */
+ __libc_missing_posix_timers = 1;
+ __libc_missing_posix_cpu_timers = 1;
+ }
+ else
+# endif
+ if (INTERNAL_SYSCALL_ERRNO (r, err) == EINVAL)
+ {
+# if !(__ASSUME_POSIX_CPU_TIMERS > 0)
+ if (pidclock == MAKE_PROCESS_CPUCLOCK (0, CPUCLOCK_SCHED)
+ || INTERNAL_SYSCALL_ERROR_P (INTERNAL_SYSCALL
+ (clock_getres, err, 2,
+ MAKE_PROCESS_CPUCLOCK
+ (0, CPUCLOCK_SCHED), NULL),
+ err))
+ /* The kernel doesn't support these clocks at all. */
+ __libc_missing_posix_cpu_timers = 1;
+ else
+# endif
+ /* The clock_getres system call checked the PID for us. */
+ return ESRCH;
+ }
+ else
+ return INTERNAL_SYSCALL_ERRNO (r, err);
+ }
+# endif
+
+ /* We don't allow any process ID but our own. */
+ if (pid != 0 && pid != getpid ())
+ return EPERM;
+
+#ifdef CLOCK_PROCESS_CPUTIME_ID
+ if (HAS_CPUCLOCK)
+ {
+ /* Store the number. */
+ *clock_id = CLOCK_PROCESS_CPUTIME_ID;
+
+ return 0;
+ }
+#else
+ /* We don't have a timer for that. */
+ return ENOENT;
+#endif
+}
diff --git a/sysdeps/unix/sysv/linux/clock_getres.c b/sysdeps/unix/sysv/linux/clock_getres.c
index 442fbd5705..610738f7bb 100644
--- a/sysdeps/unix/sysv/linux/clock_getres.c
+++ b/sysdeps/unix/sysv/linux/clock_getres.c
@@ -1,4 +1,5 @@
-/* Copyright (C) 2003 Free Software Foundation, Inc.
+/* clock_getres -- Get the resolution of a POSIX clockid_t. Linux version.
+ Copyright (C) 2003, 2004 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -17,60 +18,168 @@
02111-1307 USA. */
#include <sysdep.h>
+#include <errno.h>
+#include "kernel-posix-cpu-timers.h"
#include "kernel-features.h"
+#define SYSCALL_GETRES \
+ retval = INLINE_SYSCALL (clock_getres, 2, clock_id, res); \
+ break
+
#ifdef __ASSUME_POSIX_TIMERS
+
/* This means the REALTIME and MONOTONIC clock are definitely
supported in the kernel. */
-# define SYSDEP_GETRES \
+# define SYSDEP_GETRES \
+ SYSDEP_GETRES_CPUTIME \
case CLOCK_REALTIME: \
case CLOCK_MONOTONIC: \
- retval = INLINE_SYSCALL (clock_getres, 2, clock_id, res); \
- break
+ SYSCALL_GETRES
+
+# define __libc_missing_posix_timers 0
#elif defined __NR_clock_getres
/* Is the syscall known to exist? */
extern int __libc_missing_posix_timers attribute_hidden;
+static inline int
+maybe_syscall_getres (clockid_t clock_id, struct timespec *res)
+{
+ int e = EINVAL;
+
+ if (!__libc_missing_posix_timers)
+ {
+ INTERNAL_SYSCALL_DECL (err);
+ int r = INTERNAL_SYSCALL (clock_getres, err, 2, clock_id, res);
+ if (!INTERNAL_SYSCALL_ERROR_P (r, err))
+ return 0;
+
+ e = INTERNAL_SYSCALL_ERRNO (r, err);
+ if (e == ENOSYS)
+ {
+ __libc_missing_posix_timers = 1;
+ e = EINVAL;
+ }
+ }
+
+ return e;
+}
+
/* The REALTIME and MONOTONIC clock might be available. Try the
syscall first. */
-# define SYSDEP_GETRES \
+# define SYSDEP_GETRES \
+ SYSDEP_GETRES_CPUTIME \
case CLOCK_REALTIME: \
case CLOCK_MONOTONIC: \
- { \
- int e = EINVAL; \
- \
- if (!__libc_missing_posix_timers) \
- { \
- INTERNAL_SYSCALL_DECL (err); \
- int r = INTERNAL_SYSCALL (clock_getres, err, 2, clock_id, res); \
- if (!INTERNAL_SYSCALL_ERROR_P (r, err)) \
- { \
- retval = 0; \
- break; \
- } \
- \
- e = INTERNAL_SYSCALL_ERRNO (r, err); \
- if (e == ENOSYS) \
- { \
- __libc_missing_posix_timers = 1; \
- e = EINVAL; \
- } \
- } \
- \
- /* Fallback code. */ \
- if (e == EINVAL && clock_id == CLOCK_REALTIME) \
- HANDLE_REALTIME; \
- else \
- __set_errno (e); \
- } \
- break
+ retval = maybe_syscall_getres (clock_id, res); \
+ if (retval == 0) \
+ break; \
+ /* Fallback code. */ \
+ if (retval == EINVAL && clock_id == CLOCK_REALTIME) \
+ retval = realtime_getres (res); \
+ else \
+ { \
+ __set_errno (retval); \
+ retval = -1; \
+ } \
+ break;
#endif
#ifdef __NR_clock_getres
/* We handled the REALTIME clock here. */
# define HANDLED_REALTIME 1
+# define HANDLED_CPUTIME 1
+
+# if __ASSUME_POSIX_CPU_TIMERS > 0
+
+# define SYSDEP_GETRES_CPU SYSCALL_GETRES
+# define SYSDEP_GETRES_CPUTIME /* Default catches them too. */
+
+# else
+
+extern int __libc_missing_posix_cpu_timers attribute_hidden;
+
+static int
+maybe_syscall_getres_cpu (clockid_t clock_id, struct timespec *res)
+{
+ int e = EINVAL;
+
+ if (!__libc_missing_posix_cpu_timers)
+ {
+ INTERNAL_SYSCALL_DECL (err);
+ int r = INTERNAL_SYSCALL (clock_getres, err, 2, clock_id, res);
+ if (!INTERNAL_SYSCALL_ERROR_P (r, err))
+ return 0;
+
+ e = INTERNAL_SYSCALL_ERRNO (r, err);
+# ifndef __ASSUME_POSIX_TIMERS
+ if (e == ENOSYS)
+ {
+ __libc_missing_posix_timers = 1;
+ __libc_missing_posix_cpu_timers = 1;
+ e = EINVAL;
+ }
+ else
+# endif
+ {
+ if (e == EINVAL)
+ {
+ /* Check whether the kernel supports CPU clocks at all.
+ If not, record it for the future. */
+ r = INTERNAL_SYSCALL (clock_getres, err, 2,
+ MAKE_PROCESS_CPUCLOCK (0, CPUCLOCK_SCHED),
+ NULL);
+ if (INTERNAL_SYSCALL_ERROR_P (r, err))
+ __libc_missing_posix_cpu_timers = 1;
+ }
+ }
+ }
+
+ return e;
+}
+
+# define SYSDEP_GETRES_CPU \
+ retval = maybe_syscall_getres_cpu (clock_id, res); \
+ if (retval == 0) \
+ break; \
+ if (retval != EINVAL || !__libc_missing_posix_cpu_timers) \
+ { \
+ __set_errno (retval); \
+ retval = -1; \
+ break; \
+ } \
+ retval = -1 /* Otherwise continue on to the HP_TIMING version. */;
+
+static inline int
+maybe_syscall_getres_cputime (clockid_t clock_id, struct timespec *res)
+{
+ return maybe_syscall_getres_cpu
+ (clock_id == CLOCK_THREAD_CPUTIME_ID
+ ? MAKE_THREAD_CPUCLOCK (0, CPUCLOCK_SCHED)
+ : MAKE_PROCESS_CPUCLOCK (0, CPUCLOCK_SCHED),
+ res);
+}
+
+# define SYSDEP_GETRES_CPUTIME \
+ case CLOCK_PROCESS_CPUTIME_ID: \
+ case CLOCK_THREAD_CPUTIME_ID: \
+ retval = maybe_syscall_getres_cputime (clock_id, res); \
+ if (retval == 0) \
+ break; \
+ if (retval != EINVAL || !__libc_missing_posix_cpu_timers) \
+ { \
+ __set_errno (retval); \
+ retval = -1; \
+ break; \
+ } \
+ retval = hp_timing_getres (res); \
+ break;
+# if !HP_TIMING_AVAIL
+# define hp_timing_getres(res) (__set_errno (EINVAL), -1)
+# endif
+
+# endif
#endif
#include <sysdeps/posix/clock_getres.c>
diff --git a/sysdeps/unix/sysv/linux/clock_gettime.c b/sysdeps/unix/sysv/linux/clock_gettime.c
index 522fac32a7..41fbbde1cc 100644
--- a/sysdeps/unix/sysv/linux/clock_gettime.c
+++ b/sysdeps/unix/sysv/linux/clock_gettime.c
@@ -1,4 +1,5 @@
-/* Copyright (C) 2003 Free Software Foundation, Inc.
+/* clock_gettime -- Get current time from a POSIX clockid_t. Linux version.
+ Copyright (C) 2003, 2004 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -17,60 +18,167 @@
02111-1307 USA. */
#include <sysdep.h>
-
+#include <errno.h>
+#include "kernel-posix-cpu-timers.h"
#include "kernel-features.h"
+#define SYSCALL_GETTIME \
+ retval = INLINE_SYSCALL (clock_gettime, 2, clock_id, tp); \
+ break
+
#ifdef __ASSUME_POSIX_TIMERS
+
/* This means the REALTIME and MONOTONIC clock are definitely
supported in the kernel. */
-# define SYSDEP_GETTIME \
+# define SYSDEP_GETTIME \
+ SYSDEP_GETTIME_CPUTIME \
case CLOCK_REALTIME: \
case CLOCK_MONOTONIC: \
- retval = INLINE_SYSCALL (clock_gettime, 2, clock_id, tp); \
- break
+ SYSCALL_GETTIME
+
+# define __libc_missing_posix_timers 0
#elif defined __NR_clock_gettime
/* Is the syscall known to exist? */
int __libc_missing_posix_timers attribute_hidden;
+static inline int
+maybe_syscall_gettime (clockid_t clock_id, struct timespec *tp)
+{
+ int e = EINVAL;
+
+ if (!__libc_missing_posix_timers)
+ {
+ INTERNAL_SYSCALL_DECL (err);
+ int r = INTERNAL_SYSCALL (clock_gettime, err, 2, clock_id, tp);
+ if (!INTERNAL_SYSCALL_ERROR_P (r, err))
+ return 0;
+
+ e = INTERNAL_SYSCALL_ERRNO (r, err);
+ if (e == ENOSYS)
+ {
+ __libc_missing_posix_timers = 1;
+ e = EINVAL;
+ }
+ }
+
+ return e;
+}
+
/* The REALTIME and MONOTONIC clock might be available. Try the
syscall first. */
-# define SYSDEP_GETTIME \
+# define SYSDEP_GETTIME \
+ SYSDEP_GETTIME_CPUTIME \
case CLOCK_REALTIME: \
case CLOCK_MONOTONIC: \
- { \
- int e = EINVAL; \
- \
- if (!__libc_missing_posix_timers) \
- { \
- INTERNAL_SYSCALL_DECL (err); \
- int r = INTERNAL_SYSCALL (clock_gettime, err, 2, clock_id, tp); \
- if (!INTERNAL_SYSCALL_ERROR_P (r, err)) \
- { \
- retval = 0; \
- break; \
- } \
- \
- e = INTERNAL_SYSCALL_ERRNO (r, err); \
- if (e == ENOSYS) \
- { \
- __libc_missing_posix_timers = 1; \
- e = EINVAL; \
- } \
- } \
- \
- /* Fallback code. */ \
- if (e == EINVAL && clock_id == CLOCK_REALTIME) \
- HANDLE_REALTIME; \
- else \
- __set_errno (e); \
- } \
- break
+ retval = maybe_syscall_gettime (clock_id, tp); \
+ if (retval == 0) \
+ break; \
+ /* Fallback code. */ \
+ if (retval == EINVAL && clock_id == CLOCK_REALTIME) \
+ retval = realtime_gettime (tp); \
+ else \
+ { \
+ __set_errno (retval); \
+ retval = -1; \
+ } \
+ break;
#endif
#ifdef __NR_clock_gettime
/* We handled the REALTIME clock here. */
# define HANDLED_REALTIME 1
+# define HANDLED_CPUTIME 1
+
+# if __ASSUME_POSIX_CPU_TIMERS > 0
+
+# define SYSDEP_GETTIME_CPU SYSCALL_GETTIME
+# define SYSDEP_GETTIME_CPUTIME /* Default catches them too. */
+
+# else
+
+int __libc_missing_posix_cpu_timers attribute_hidden;
+
+static int
+maybe_syscall_gettime_cpu (clockid_t clock_id, struct timespec *tp)
+{
+ int e = EINVAL;
+
+ if (!__libc_missing_posix_cpu_timers)
+ {
+ INTERNAL_SYSCALL_DECL (err);
+ int r = INTERNAL_SYSCALL (clock_gettime, err, 2, clock_id, tp);
+ if (!INTERNAL_SYSCALL_ERROR_P (r, err))
+ return 0;
+
+ e = INTERNAL_SYSCALL_ERRNO (r, err);
+# ifndef __ASSUME_POSIX_TIMERS
+ if (e == ENOSYS)
+ {
+ __libc_missing_posix_timers = 1;
+ __libc_missing_posix_cpu_timers = 1;
+ e = EINVAL;
+ }
+ else
+# endif
+ {
+ if (e == EINVAL)
+ {
+ /* Check whether the kernel supports CPU clocks at all.
+ If not, record it for the future. */
+ r = INTERNAL_SYSCALL (clock_getres, err, 2,
+ MAKE_PROCESS_CPUCLOCK (0, CPUCLOCK_SCHED),
+ NULL);
+ if (INTERNAL_SYSCALL_ERROR_P (r, err))
+ __libc_missing_posix_cpu_timers = 1;
+ }
+ }
+ }
+
+ return e;
+}
+
+# define SYSDEP_GETTIME_CPU \
+ retval = maybe_syscall_gettime_cpu (clock_id, tp); \
+ if (retval == 0) \
+ break; \
+ if (retval != EINVAL || !__libc_missing_posix_cpu_timers) \
+ { \
+ __set_errno (retval); \
+ retval = -1; \
+ break; \
+ } \
+ retval = -1 /* Otherwise continue on to the HP_TIMING version. */;
+
+static inline int
+maybe_syscall_gettime_cputime (clockid_t clock_id, struct timespec *tp)
+{
+ return maybe_syscall_gettime_cpu
+ (clock_id == CLOCK_THREAD_CPUTIME_ID
+ ? MAKE_THREAD_CPUCLOCK (0, CPUCLOCK_SCHED)
+ : MAKE_PROCESS_CPUCLOCK (0, CPUCLOCK_SCHED),
+ tp);
+}
+
+# define SYSDEP_GETTIME_CPUTIME \
+ case CLOCK_PROCESS_CPUTIME_ID: \
+ case CLOCK_THREAD_CPUTIME_ID: \
+ retval = maybe_syscall_gettime_cputime (clock_id, tp); \
+ if (retval == 0) \
+ break; \
+ if (retval != EINVAL || !__libc_missing_posix_cpu_timers) \
+ { \
+ __set_errno (retval); \
+ retval = -1; \
+ break; \
+ } \
+ retval = hp_timing_gettime (clock_id, tp); \
+ break;
+# if !HP_TIMING_AVAIL
+# define hp_timing_gettime(clock_id, tp) (__set_errno (EINVAL), -1)
+# endif
+
+# endif
#endif
#include <sysdeps/unix/clock_gettime.c>
diff --git a/sysdeps/unix/sysv/linux/clock_nanosleep.c b/sysdeps/unix/sysv/linux/clock_nanosleep.c
index 2a3dd411a1..3fb14b48aa 100644
--- a/sysdeps/unix/sysv/linux/clock_nanosleep.c
+++ b/sysdeps/unix/sysv/linux/clock_nanosleep.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2003 Free Software Foundation, Inc.
+/* Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -17,9 +17,11 @@
02111-1307 USA. */
#include <time.h>
+#include <errno.h>
#include <sysdep-cancel.h>
#include "kernel-features.h"
+#include "kernel-posix-cpu-timers.h"
#ifdef __ASSUME_POSIX_TIMERS
@@ -32,6 +34,11 @@ clock_nanosleep (clockid_t clock_id, int flags, const struct timespec *req,
INTERNAL_SYSCALL_DECL (err);
int r;
+ if (clock_id == CLOCK_THREAD_CPUTIME_ID)
+ return EINVAL;
+ if (clock_id == CLOCK_PROCESS_CPUTIME_ID)
+ clock_id = MAKE_PROCESS_CPUCLOCK (0, CPUCLOCK_SCHED);
+
if (SINGLE_THREAD_P)
r = INTERNAL_SYSCALL (clock_nanosleep, err, 4, clock_id, flags, req, rem);
else
@@ -58,12 +65,20 @@ extern int __libc_missing_posix_timers attribute_hidden;
# define SYSDEP_NANOSLEEP \
if (!__libc_missing_posix_timers) \
{ \
+ clockid_t syscall_clockid; \
INTERNAL_SYSCALL_DECL (err); \
\
+ if (clock_id == CLOCK_THREAD_CPUTIME_ID) \
+ return EINVAL; \
+ if (clock_id == CLOCK_PROCESS_CPUTIME_ID) \
+ syscall_clockid = MAKE_PROCESS_CPUCLOCK (0, CPUCLOCK_SCHED); \
+ else \
+ syscall_clockid = clock_id; \
+ \
int oldstate = LIBC_CANCEL_ASYNC (); \
\
- int r = INTERNAL_SYSCALL (clock_nanosleep, err, 4, clock_id, flags, \
- req, rem); \
+ int r = INTERNAL_SYSCALL (clock_nanosleep, err, 4, \
+ syscall_clockid, flags, req, rem); \
\
LIBC_CANCEL_RESET (oldstate); \
\
diff --git a/sysdeps/unix/sysv/linux/ia64/clock_getcpuclockid.c b/sysdeps/unix/sysv/linux/ia64/clock_getcpuclockid.c
index d2c45a560a..2f39851535 100644
--- a/sysdeps/unix/sysv/linux/ia64/clock_getcpuclockid.c
+++ b/sysdeps/unix/sysv/linux/ia64/clock_getcpuclockid.c
@@ -1,4 +1,5 @@
-/* Copyright (C) 2000, 2001, 2003, 2004 Free Software Foundation, Inc.
+/* clock_getcpuclockid -- Get a clockid_t for process CPU time. Linux/IA64
+ Copyright (C) 2000,2001,2003,2004 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -26,22 +27,6 @@
#include "has_cpuclock.c"
+#define HAS_CPUCLOCK (has_cpuclock () > 0)
-int
-clock_getcpuclockid (pid_t pid, clockid_t *clock_id)
-{
- /* We don't allow any process ID but our own. */
- if (pid != 0 && pid != getpid ())
- return EPERM;
-
- int retval = ENOENT;
-
- if (has_cpuclock () > 0)
- {
- /* Store the number. */
- *clock_id = CLOCK_PROCESS_CPUTIME_ID;
- retval = 0;
- }
-
- return retval;
-}
+#include <sysdeps/unix/sysv/linux/clock_getcpuclockid.c>
diff --git a/sysdeps/unix/sysv/linux/kernel-posix-cpu-timers.h b/sysdeps/unix/sysv/linux/kernel-posix-cpu-timers.h
new file mode 100644
index 0000000000..164a90ddeb
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/kernel-posix-cpu-timers.h
@@ -0,0 +1,18 @@
+/* Parameters for the Linux kernel ABI for CPU clocks. */
+
+#define CPUCLOCK_PID(clock) ((pid_t) ~((clock) >> 3))
+#define CPUCLOCK_PERTHREAD(clock) \
+ (((clock) & (clockid_t) CPUCLOCK_PERTHREAD_MASK) != 0)
+#define CPUCLOCK_PID_MASK 7
+#define CPUCLOCK_PERTHREAD_MASK 4
+#define CPUCLOCK_WHICH(clock) ((clock) & (clockid_t) CPUCLOCK_CLOCK_MASK)
+#define CPUCLOCK_CLOCK_MASK 3
+#define CPUCLOCK_PROF 0
+#define CPUCLOCK_VIRT 1
+#define CPUCLOCK_SCHED 2
+#define CPUCLOCK_MAX 3
+
+#define MAKE_PROCESS_CPUCLOCK(pid, clock) \
+ ((~(clockid_t) (pid) << 3) | (clockid_t) (clock))
+#define MAKE_THREAD_CPUCLOCK(tid, clock) \
+ MAKE_PROCESS_CPUCLOCK((tid), (clock) | CPUCLOCK_PERTHREAD_MASK)
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep.h b/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep.h
index 17bfa9014f..c3463f7431 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep.h
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep.h
@@ -122,7 +122,7 @@
#undef INTERNAL_SYSCALL_ERROR_P
#define INTERNAL_SYSCALL_ERROR_P(val, err) \
- ((void) (err), __builtin_expect ((err) & (1 << 28), 0))
+ ((void) (val), __builtin_expect ((err) & (1 << 28), 0))
#undef INTERNAL_SYSCALL_ERRNO
#define INTERNAL_SYSCALL_ERRNO(val, err) (val)
diff --git a/time/Makefile b/time/Makefile
index 7acc964fdc..14313563eb 100644
--- a/time/Makefile
+++ b/time/Makefile
@@ -1,4 +1,4 @@
-# Copyright (C) 1991-2002,2003,2004 Free Software Foundation, Inc.
+# Copyright (C) 1991-2003, 2004, 2005 Free Software Foundation, Inc.
# This file is part of the GNU C Library.
# The GNU C Library is free software; you can redistribute it and/or
@@ -35,7 +35,7 @@ distribute := datemsk
tests := test_time clocktest tst-posixtz tst-strptime tst_wcsftime \
tst-getdate tst-mktime tst-mktime2 tst-ftime_l tst-strftime \
- tst-mktime3
+ tst-mktime3 tst-strptime2
include ../Rules
diff --git a/time/strptime_l.c b/time/strptime_l.c
index 01c4f8282a..dc0cc686fd 100644
--- a/time/strptime_l.c
+++ b/time/strptime_l.c
@@ -687,6 +687,42 @@ __strptime_internal (rp, fmt, tm, decided, era_cnt LOCALE_PARAM)
case 'Z':
/* XXX How to handle this? */
break;
+ case 'z':
+ /* We recognize two formats: if two digits are given, these
+ specify hours. If fours digits are used, minutes are
+ also specified. */
+ {
+ val = 0;
+ while (*rp == ' ')
+ ++rp;
+ if (*rp != '+' && *rp != '-')
+ return NULL;
+ bool neg = *rp++ == '-';
+ int n = 0;
+ while (n < 4 && *rp >= '0' && *rp <= '9')
+ {
+ val = val * 10 + *rp++ - '0';
+ ++n;
+ }
+ if (n == 2)
+ val *= 100;
+ else if (n != 4)
+ /* Only two or four digits recognized. */
+ return NULL;
+ else
+ {
+ /* We have to convert the minutes into decimal. */
+ if (val % 100 >= 60)
+ return NULL;
+ val = (val / 100) * 100 + ((val % 100) * 50) / 30;
+ }
+ if (val > 1200)
+ return NULL;
+ tm->tm_gmtoff = (val * 3600) / 100;
+ if (neg)
+ tm->tm_gmtoff = -tm->tm_gmtoff;
+ }
+ break;
case 'E':
#ifdef _NL_CURRENT
switch (*fmt++)
diff --git a/time/tst-strptime2.c b/time/tst-strptime2.c
new file mode 100644
index 0000000000..73552bb8f8
--- /dev/null
+++ b/time/tst-strptime2.c
@@ -0,0 +1,59 @@
+#include <limits.h>
+#include <stdio.h>
+#include <time.h>
+
+
+static const struct
+{
+ const char *fmt;
+ long int gmtoff;
+} tests[] =
+ {
+ { "1113472456 +1000", 36000 },
+ { "1113472456 -1000", -36000 },
+ { "1113472456 +10", 36000 },
+ { "1113472456 -10", -36000 },
+ { "1113472456 +1030", 37800 },
+ { "1113472456 -1030", -37800 },
+ { "1113472456 +0030", 1800 },
+ { "1113472456 -0030", -1800 },
+ { "1113472456 -1330", LONG_MAX },
+ { "1113472456 +1330", LONG_MAX },
+ { "1113472456 -1060", LONG_MAX },
+ { "1113472456 +1060", LONG_MAX },
+ { "1113472456 1030", LONG_MAX },
+ };
+#define ntests (sizeof (tests) / sizeof (tests[0]))
+
+
+int
+main (void)
+{
+ int result = 0;
+
+ for (int i = 0; i < ntests; ++i)
+ {
+ struct tm tm;
+
+ if (strptime (tests[i].fmt, "%s %z", &tm) == NULL)
+ {
+ if (tests[i].gmtoff != LONG_MAX)
+ {
+ printf ("round %d: strptime unexpectedly failed\n", i);
+ result = 1;
+ }
+ continue;
+ }
+
+ if (tm.tm_gmtoff != tests[i].gmtoff)
+ {
+ printf ("round %d: tm_gmtoff is %ld\n", i, (long int) tm.tm_gmtoff);
+ result = 1;
+ }
+ }
+
+ if (result == 0)
+ puts ("all OK");
+
+ return 0;
+}
diff --git a/timezone/Makefile b/timezone/Makefile
index cf2c7d7f42..9947d45b17 100644
--- a/timezone/Makefile
+++ b/timezone/Makefile
@@ -1,4 +1,4 @@
-# Copyright (C) 1998, 1999, 2000, 2002 Free Software Foundation, Inc.
+# Copyright (C) 1998,1999,2000,2002,2005 Free Software Foundation, Inc.
# This file is part of the GNU C Library.
# The GNU C Library is free software; you can redistribute it and/or
@@ -190,28 +190,24 @@ $(objpfx)tst-timezone.out: $(addprefix $(testdata)/, \
test-tz-ENV = TZDIR=$(testdata)
tst-timezone-ENV = TZDIR=$(testdata)
-$(testdata)/America/New_York: northamerica $(objpfx)zic $(leapseconds) \
- yearistype
- $(build-testdata)
-$(testdata)/Etc/UTC: etcetera $(objpfx)zic $(leapseconds) yearistype
- $(build-testdata)
-$(testdata)/UTC: simplebackw $(objpfx)zic $(testdata)/Etc/UTC \
- $(leapseconds) yearistype
+# Note this must come second in the deps list for $(built-program-cmd) to work.
+zic-deps = $(objpfx)zic $(leapseconds) yearistype
+
+$(testdata)/America/New_York: northamerica $(zic-deps)
$(build-testdata)
-$(testdata)/Europe/Berlin: europe $(objpfx)zic $(leapseconds) yearistype
+$(testdata)/Etc/UTC: etcetera $(zic-deps)
$(build-testdata)
-$(testdata)/Universal: simplebackw $(objpfx)zic $(testdata)/Etc/UTC \
- $(leapseconds) yearistype
+# Use a pattern rule to indicate the command produces both targets at once.
+# Two separate targets built separately can collide if in parallel.
+%/UTC %/Universal: simplebackw $(zic-deps) %/Etc/UTC
$(build-testdata)
-$(testdata)/Australia/Melbourne: australasia $(objpfx)zic $(leapseconds) \
- yearistype
+$(testdata)/%/Berlin $(testdata)/%/London: europe $(zic-deps)
$(build-testdata)
-$(testdata)/America/Sao_Paulo: southamerica $(objpfx)zic $(leapseconds) \
- yearistype
+$(testdata)/Australia/Melbourne: australasia $(zic-deps)
$(build-testdata)
-$(testdata)/Asia/Tokyo: asia $(objpfx)zic $(leapseconds) yearistype
+$(testdata)/America/Sao_Paulo: southamerica $(zic-deps)
$(build-testdata)
-$(testdata)/Europe/London: europe $(objpfx)zic $(leapseconds) yearistype
+$(testdata)/Asia/Tokyo: asia $(zic-deps)
$(build-testdata)