]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
Updated to fedora-glibc-20050427T1043
authorJakub Jelinek <jakub@redhat.com>
Wed, 27 Apr 2005 11:31:41 +0000 (11:31 +0000)
committerJakub Jelinek <jakub@redhat.com>
Wed, 27 Apr 2005 11:31:41 +0000 (11:31 +0000)
50 files changed:
ChangeLog
elf/Makefile
elf/dl-close.c
elf/rtld-Rules
elf/unload6.c [new file with mode: 0644]
elf/unload6mod1.c [new file with mode: 0644]
elf/unload6mod2.c [new file with mode: 0644]
elf/unload6mod3.c [new file with mode: 0644]
fedora/branch.mk
linuxthreads/ChangeLog
linuxthreads/sysdeps/pthread/getcpuclockid.c
localedata/ChangeLog
localedata/locales/fa_IR
malloc/Makefile
malloc/hooks.c
malloc/tst-mcheck.c [new file with mode: 0644]
nptl/ChangeLog
nptl/Makefile
nptl/old_pthread_cond_init.c
nptl/pthread_cond_init.c
nptl/sysdeps/i386/tls.h
nptl/sysdeps/unix/sysv/linux/pthread_getcpuclockid.c [new file with mode: 0644]
nptl/sysdeps/unix/sysv/linux/timer_create.c
nptl/tst-cancel17.c
posix/unistd.h
rt/Makefile
rt/tst-cpuclock1.c [new file with mode: 0644]
rt/tst-cpuclock2.c [new file with mode: 0644]
rt/tst-cputimer1.c [new file with mode: 0644]
rt/tst-cputimer2.c [new file with mode: 0644]
rt/tst-cputimer3.c [new file with mode: 0644]
stdio-common/vfscanf.c
stdlib/canonicalize.c
stdlib/test-canon.c
sunrpc/xdr.c
sysdeps/posix/clock_getres.c
sysdeps/sparc/sparc32/elf/start.S
sysdeps/sparc/sparc64/elf/start.S
sysdeps/unix/clock_gettime.c
sysdeps/unix/sysv/linux/clock_getcpuclockid.c [new file with mode: 0644]
sysdeps/unix/sysv/linux/clock_getres.c
sysdeps/unix/sysv/linux/clock_gettime.c
sysdeps/unix/sysv/linux/clock_nanosleep.c
sysdeps/unix/sysv/linux/ia64/clock_getcpuclockid.c
sysdeps/unix/sysv/linux/kernel-posix-cpu-timers.h [new file with mode: 0644]
sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep.h
time/Makefile
time/strptime_l.c
time/tst-strptime2.c [new file with mode: 0644]
timezone/Makefile

index 2a1358023eb1238b488bbfa719877e8d4ee6749b..3179b70d2572cc1d043ed3f8415eb02cece1859c 100644 (file)
--- 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.
index c034b2ba6e2d1d1257055a2e9225a262a2a64194..d988baca3bd9174108670ad8c9c22de7151a2bf1 100644 (file)
@@ -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
index cd4fa7cfbe1049567da214f2a2c1b1adccaeb04f..754dd678fe64a6d3d72b9a3d25fca6ef2752458b 100644 (file)
@@ -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);
index ac96f728d9e29cf2b005342b70bd8da73580c6d7..61143b180c057a0258ba58537bc6eb020aeddf13 100644 (file)
@@ -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
 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 (file)
index 0000000..1efc7eb
--- /dev/null
@@ -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 (file)
index 0000000..24f2e5a
--- /dev/null
@@ -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 (file)
index 0000000..980efa4
--- /dev/null
@@ -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 (file)
index 0000000..7b29e1d
--- /dev/null
@@ -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);
+}
index 5b5f55469d68d85f32428366e95da137feb7f4c9..222b4e6c51457e355d348ee2af19d23ef29ee3cb 100644 (file)
@@ -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
index 7ac85a142bd796f0a0a76a6dd4c4760fb74ec5ae..40b40da957b4bab40d02c36d8aa63fc12f421a29 100644 (file)
@@ -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
index 032caeb081f05b4138218ddce8aed6dfbf657496..117c22dd375443a2402fda356ae963702274a7e3 100644 (file)
@@ -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
 #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
index e454cd0cfc7a2ebf0f2a8f189da775a8932af412..b0829cd181d6df79129a651c9e27bc80cacea630 100644 (file)
@@ -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>
index 8f65b1edd89f02ce1abc9a0bb4da9b11a8c43c5e..15fb535640c53f321160d676c12232c0b0d4375b 100644 (file)
@@ -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
index 45e8f59ab4d84cb4afab4daf8ac8f6855e7e67e4..398dd2b03162b1bb3f18ffcc5c9305b84801d565 100644 (file)
@@ -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
 
index a5c97f3133f364c02657fad35a1d07b7cc0b8ba4..0f8f274e38a51a59124f9bf1a156a9814dd84799 100644 (file)
@@ -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 (file)
index 0000000..1678491
--- /dev/null
@@ -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;
+}
index e608d136ceab729d13b1e0e299b083a68cd4d968..790ceb01d0321013469e584a3bdf215efda90999 100644 (file)
@@ -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.
index 8d18946e6fb0426ee2b7959b1b52416eac70c7ef..2acb8d01b7cbc00e02180f5a26f20c403f167274 100644 (file)
@@ -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 \
index 21bc856a02a024c2a2e18559592f0d4d7f8ce430..47e68b000d296cf981352d60933ed382239986c7 100644 (file)
@@ -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,
index 03ac59dbd26d0be7575e227197e393b66fa6954d..5e2e6704a90ac2d0b5f426c5cf252d2c0464d99b 100644 (file)
@@ -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;
index e243f8b2cf9db557e93baa9dc91d85f1885bc47c..06def42a5bf75645a0248365aa4a449c18e551cc 100644 (file)
@@ -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 (file)
index 0000000..088b339
--- /dev/null
@@ -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
+}
index ca6ff6c7ef3722b431f4a68ef72b6e8f8ecfb6b4..5e99513950fe6fe9d343abeff780e9974a01b94e 100644 (file)
@@ -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;
index 9fb089ac839020530925d2fa1311d411f84c960a..2a8c951afe9b2620442f5ed16062479af4bf08ce 100644 (file)
@@ -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)
     {
index d6cd152b46ebaf7f435f88e5d31c431b3956400c..b0fba33417c571bf60c66581f53732c923cff098 100644 (file)
@@ -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'.  */
index 407cc99897a63eca09fa10de02bb7e4b55ef4a5c..cc01cb95c9ee0a72cb1289fddad133c353a69c29 100644 (file)
@@ -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 (file)
index 0000000..024df63
--- /dev/null
@@ -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 (file)
index 0000000..d1621f3
--- /dev/null
@@ -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 (file)
index 0000000..8f5dd76
--- /dev/null
@@ -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 (file)
index 0000000..397d799
--- /dev/null
@@ -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 (file)
index 0000000..056766a
--- /dev/null
@@ -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"
index c641d2d37104c89847de88fb4749db13407d56f7..be008dc6879c322dd9e3bc833bafc99faae7cb76 100644 (file)
@@ -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))
index 2168bbd90ed0f944ddceb92a8517025a50da6e2d..9fc24b7d92d90e2e3018fe1760b504a72d131a03 100644 (file)
@@ -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] == '/')
index f070df74a026e260c19668886b83a7399ac08c71..54267465b81df29c9080284125ca54d0eefa509b 100644 (file)
@@ -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);
index 2f894fbba7e8070c364dc2475ed430f2cb0155aa..411cbe1ab1534efd04068a2506c4f9e79328474b 100644 (file)
@@ -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;
     }
index a2d466607e3ff0042bcb4a6dd4bc51238ae9ed7f..f4dc21f8af38040f5f2f0d351e593ee74d90c31e 100644 (file)
@@ -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
 #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
     }
index 2787fd27f8161135a8e12fd2731d042e4424e8a4..4c7fb5bd232c362d354ff691e519ab4ef49f48e1 100644 (file)
@@ -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)
index b0ef9d355dfa713d2ab3ffbabc97a134c56d5f38..c008c6cea0cf7ee0f7e17b7f9620945d0bd3b70a 100644 (file)
@@ -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)
index 7a3db297442b3c8244855d91c20e3bcbee57507c..b7b0428e0b10842e6a2b3084543cbd3d5ec537d5 100644 (file)
@@ -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 (file)
index 0000000..ac893c0
--- /dev/null
@@ -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
+}
index 442fbd57058501c0e48d0e8867abaab2d365c364..610738f7bbdd103a31a3b764f0da63b20f38dd49 100644 (file)
@@ -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
    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>
index 522fac32a7e611b76a0ce23739a9d20ae673b7ea..41fbbde1cc3354096ee431b92c1dbd0854b80f6a 100644 (file)
@@ -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
    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>
index 2a3dd411a12b4edc5d6a4a82dcc96e44a5480dde..3fb14b48aab5f5abae566e3dae57737eda010350 100644 (file)
@@ -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
    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);                                          \
                                                                              \
index d2c45a560a14173c104c8ecf8be96283764a590f..2f3985153552e3d7b3340ea5a1b3c8ed14566407 100644 (file)
@@ -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
 
 #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 (file)
index 0000000..164a90d
--- /dev/null
@@ -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)
index 17bfa9014fb30b707d4e5486d5b1905ab8268b2c..c3463f743158aec19b7a8dcf52465714beaee697 100644 (file)
 
 #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)
index 7acc964fdc24d0000e0ac7fe16b9c47d31216501..14313563eb86b6a6beaa9a4ad3a36c5147a79a53 100644 (file)
@@ -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
 
index 01c4f8282a8b6bab9280e4e05c86d0e24206a125..dc0cc686fd45736b591ec45125f75c86e0889c61 100644 (file)
@@ -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 (file)
index 0000000..73552bb
--- /dev/null
@@ -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;
+}
index cf2c7d7f424684b08b346dfdefb899a31fcdcd4e..9947d45b17b59c553decc33eba5fb247527b7c97 100644 (file)
@@ -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)