]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
Updated to fedora-glibc-20060815T0533
authorJakub Jelinek <jakub@redhat.com>
Tue, 15 Aug 2006 05:53:50 +0000 (05:53 +0000)
committerJakub Jelinek <jakub@redhat.com>
Tue, 15 Aug 2006 05:53:50 +0000 (05:53 +0000)
54 files changed:
ChangeLog
NEWS
fedora/branch.mk
libio/Makefile
libio/bug-memstream1.c [new file with mode: 0644]
libio/bug-wmemstream1.c [new file with mode: 0644]
libio/memstream.c
libio/strops.c
libio/vasprintf.c
libio/wmemstream.c
libio/wstrops.c
locale/programs/ld-ctype.c
locale/programs/ld-time.c
localedata/ChangeLog
localedata/SUPPORTED
localedata/locales/fy_NL [new file with mode: 0644]
localedata/locales/or_IN
localedata/locales/pa_IN
login/utmpname.c
math/gen-libm-test.pl
misc/error.c
nptl/ChangeLog
nptl/Makefile
nptl/descr.h
nptl/pthreadP.h
nptl/pthread_create.c
nptl/pthread_join.c
nptl/pthread_mutex_getprioceiling.c
nptl/pthread_mutex_init.c
nptl/pthread_mutex_lock.c
nptl/pthread_mutex_setprioceiling.c
nptl/pthread_mutex_timedlock.c
nptl/pthread_mutex_trylock.c
nptl/pthread_mutex_unlock.c
nptl/pthread_mutexattr_getprioceiling.c
nptl/pthread_mutexattr_setprioceiling.c
nptl/pthread_setschedparam.c
nptl/pthread_setschedprio.c
nptl/sysdeps/unix/sysv/linux/bits/posix_opt.h
nptl/tpp.c [new file with mode: 0644]
nptl/tst-join5.c
nptl/tst-join6.c [new file with mode: 0644]
nptl/tst-mutex1.c
nptl/tst-mutex6.c
nptl/tst-mutexpp1.c [new file with mode: 0644]
nptl/tst-mutexpp10.c [new file with mode: 0644]
nptl/tst-mutexpp6.c [new file with mode: 0644]
nptl/tst-tpp.h [new file with mode: 0644]
sysdeps/generic/stdint.h
sysdeps/powerpc/powerpc32/dl-trampoline.S
sysdeps/unix/clock_settime.c
sysdeps/unix/nice.c
sysdeps/unix/sysv/linux/clock_settime.c
sysdeps/unix/sysv/linux/sparc/sparc64/pause.c

index a356c15e3d5fbff4da7757f40646a4e0682a7a2b..e54bd15b9363d2040b90180f1e465c163ecec2f3 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,82 @@
+2006-08-15  Jakub Jelinek  <jakub@redhat.com>
+
+       * sysdeps/unix/sysv/linux/sparc/sparc64/pause.c: Use
+       sysdeps/posix/pause.c implementation instead.
+
+2006-08-09  Jakub Jelinek  <jakub@redhat.com>
+
+       * sysdeps/unix/nice.c (nice): Transform EACCES errno from setpriority
+       to EPERM.
+
+2006-08-13  Andreas Schwab  <schwab@suse.de>
+
+       * sysdeps/powerpc/powerpc32/dl-trampoline.S (_dl_runtime_resolve):
+       Don't clobber caller's LRSAVE.
+       (_dl_prof_resolve): Likewise.
+
+2006-08-14  Ulrich Drepper  <drepper@redhat.com>
+
+       [BZ #1996]
+       * libio/memstream.c (open_memstream): Allocate initial buffer with
+       calloc.
+       * libio/wmemstream.c (open_wmemstream): Likewise.
+       * libio/strops.c: Pretty printing.
+       (_IO_str_overflow): Clear uninitialized part of the new buffer.
+       (enlarge_userbuf): New function.
+       (_IO_str_seekoff): Call it if seek position is larger than current
+       buffer.
+       * libio/wstrops.c: Likewise.
+       * libio/vasprintf.c: Add comment as to why we do not have to use
+       calloc instead of malloc to allocate initial buffer.
+       * libio/Makefile (tests): Add bug-memstream1 and bug-wmemstream1.
+       * libio/bug-memstream1.c: New file.
+       * libio/bug-wmemstream1.c: New file.
+
+2006-08-13  Ulrich Drepper  <drepper@redhat.com>
+
+       * libio/wstrops.c: Remove dead macro definitions and comments.
+       * libio/strops.c: Likewise.
+
+       [BZ #2764]
+       * login/utmpname.c (__utmpname): Remove unnecessary test.
+
+2006-06-08  Joseph Myers  <jsm28@gcc.gnu.org>
+
+       [BZ #2832]
+       * math/gen-libm-test.pl (clean_up_number): Do not remove trailing
+       0s from integers.
+
+2006-08-13  Ulrich Drepper  <drepper@redhat.com>
+
+       [BZ #2987]
+       * sysdeps/unix/sysv/linux/clock_settime.c: Add code to use syscall
+       for CPU clocks.
+       * sysdeps/unix/clock_settime.c: Add support for platform-specific
+       setting of CPU clocks.
+
+2006-06-23  Paul Eggert  <eggert@cs.ucla.edu>
+
+       [BZ #2841]
+       * sysdeps/generic/stdint.h (UINT8_C, UINT16_C): Don't append 'U',
+       since C99 requires the result to promote to 'int' when uint_least8_t
+       and uint_least16_t promote to 'int'.
+
+2006-08-12  Ulrich Drepper  <drepper@redhat.com>
+
+       [BZ #3013]
+       * locale/programs/ld-ctype.c (ctype_output): Adjust alignments, fix
+       lenght of one output field, correct bitmask creation.
+       * locale/programs/ld-time.c: Add alignment.
+
+       [BZ #2997]
+       * misc/error.c: Add space between program name and message if file
+       name is missing.
+
+2006-08-03  Eric Blake <ebb9@byu.net>
+
+       [BZ #2998]
+       * misc/error.c (error_tail) [_LIBC]: Avoid invalid free.
+
 2006-08-09  Ulrich Drepper  <drepper@redhat.com>
 
        * malloc/memusagestat.c: Silence warnings.
diff --git a/NEWS b/NEWS
index 55855ad81a27c1499ce1f583d576c4f230cfafc9..14abed47820305e7f60ce903c06cf21d5148ffd4 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,4 +1,4 @@
-GNU C Library NEWS -- history of user-visible changes.  2006-07-28
+GNU C Library NEWS -- history of user-visible changes.  2006-08-14
 Copyright (C) 1992-2002,2003,2004,2005,2006 Free Software Foundation, Inc.
 See the end for copying conditions.
 
@@ -36,6 +36,8 @@ Version 2.5
 * Support for priority inheritance mutexes added by Jakub Jelinek and
   Ulrich Drepper.
 
+* Support for priority protected mutexes added by Jakub Jelinek.
+
 \f
 Version 2.4
 
index 4a26c92c8ec05e2dfff894edf2d563945d45d2a0..2416955f13d78150a37435e30fa53320a5d93ca6 100644 (file)
@@ -3,5 +3,5 @@ glibc-branch := fedora
 glibc-base := HEAD
 DIST_BRANCH := devel
 COLLECTION := dist-fc4
-fedora-sync-date := 2006-08-10 06:27 UTC
-fedora-sync-tag := fedora-glibc-20060810T0627
+fedora-sync-date := 2006-08-15 05:33 UTC
+fedora-sync-tag := fedora-glibc-20060815T0533
index e9c1d522fd0a12103d5e86adf293149bd6026998..0529744e3d4796b6fcb2c3925b8218831da96a06 100644 (file)
@@ -56,7 +56,8 @@ tests = tst_swprintf tst_wprintf tst_swscanf tst_wscanf tst_getwc tst_putwc   \
        tst-mmap2-eofsync tst-mmap-offend bug-fopena+ bug-wfflush \
        bug-ungetc2 bug-ftell bug-ungetc3 bug-ungetc4 tst-fopenloc2 \
        tst-memstream1 tst-memstream2 \
-       tst-wmemstream1 tst-wmemstream2
+       tst-wmemstream1 tst-wmemstream2 \
+       bug-memstream1 bug-wmemstream1
 test-srcs = test-freopen
 
 all: # Make this the default target; it will be defined in Rules.
diff --git a/libio/bug-memstream1.c b/libio/bug-memstream1.c
new file mode 100644 (file)
index 0000000..8af36fe
--- /dev/null
@@ -0,0 +1,133 @@
+#include <stdio.h>
+#include <string.h>
+
+
+static int
+do_test (void)
+{
+  size_t size;
+  char *buf;
+  FILE *fp = open_memstream (&buf, &size);
+  if (fp == NULL)
+    {
+      puts ("open_memstream failed");
+      return 1;
+    }
+
+  off64_t off = ftello64 (fp);
+  if (off != 0)
+    {
+      puts ("initial position wrong");
+      return 1;
+    }
+
+  if (fseek (fp, 32768, SEEK_SET) != 0)
+    {
+      puts ("fseek failed");
+      return 1;
+    }
+
+  if (fputs ("foo", fp) == EOF)
+    {
+      puts ("fputs failed");
+      return 1;
+    }
+
+  if (fclose (fp) == EOF)
+    {
+      puts ("fclose failed");
+      return 1;
+    }
+
+  if (size != 32768 + 3)
+    {
+      printf ("expected size %d, got %zu\n", 32768 + 3, size);
+      return 1;
+    }
+
+  for (int i = 0; i < 32768; ++i)
+    if (buf[i] != '\0')
+      {
+       printf ("byte at offset %d is %#hhx\n", i, buf[i]);
+       return 1;
+      }
+
+  if (memcmp (buf + 32768, "foo", 3) != 0)
+    {
+      puts ("written string incorrect");
+      return 1;
+    }
+
+  /* Mark the buffer.  */
+  memset (buf, 'A', size);
+  free (buf);
+
+  /* Try again, this time with write mode enabled before the seek.  */
+  fp = open_memstream (&buf, &size);
+  if (fp == NULL)
+    {
+      puts ("2nd open_memstream failed");
+      return 1;
+    }
+
+  off = ftello64 (fp);
+  if (off != 0)
+    {
+      puts ("2nd initial position wrong");
+      return 1;
+    }
+
+  if (fputs ("bar", fp) == EOF)
+    {
+      puts ("2nd fputs failed");
+      return 1;
+    }
+
+  if (fseek (fp, 32768, SEEK_SET) != 0)
+    {
+      puts ("2nd fseek failed");
+      return 1;
+    }
+
+  if (fputs ("foo", fp) == EOF)
+    {
+      puts ("3rd fputs failed");
+      return 1;
+    }
+
+  if (fclose (fp) == EOF)
+    {
+      puts ("2nd fclose failed");
+      return 1;
+    }
+
+  if (size != 32768 + 3)
+    {
+      printf ("2nd expected size %d, got %zu\n", 32768 + 3, size);
+      return 1;
+    }
+
+  if (memcmp (buf, "bar", 3) != 0)
+    {
+      puts ("initial string incorrect in 2nd try");
+      return 1;
+    }
+
+  for (int i = 3; i < 32768; ++i)
+    if (buf[i] != '\0')
+      {
+       printf ("byte at offset %d is %#hhx in 2nd try\n", i, buf[i]);
+       return 1;
+      }
+
+  if (memcmp (buf + 32768, "foo", 3) != 0)
+    {
+      puts ("written string incorrect in 2nd try");
+      return 1;
+    }
+
+  return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/libio/bug-wmemstream1.c b/libio/bug-wmemstream1.c
new file mode 100644 (file)
index 0000000..2190593
--- /dev/null
@@ -0,0 +1,135 @@
+#include <stdio.h>
+#include <string.h>
+
+
+static int
+do_test (void)
+{
+  size_t size;
+  wchar_t *buf;
+  FILE *fp = open_wmemstream (&buf, &size);
+  if (fp == NULL)
+    {
+      puts ("open_wmemstream failed");
+      return 1;
+    }
+
+  off64_t off = ftello64 (fp);
+  if (off != 0)
+    {
+      puts ("initial position wrong");
+      return 1;
+    }
+
+  if (fseek (fp, 32768, SEEK_SET) != 0)
+    {
+      puts ("fseek failed");
+      return 1;
+    }
+
+  if (fputws (L"foo", fp) == EOF)
+    {
+      puts ("fputws failed");
+      return 1;
+    }
+
+  if (fclose (fp) == EOF)
+    {
+      puts ("fclose failed");
+      return 1;
+    }
+
+  if (size != 32768 + 3)
+    {
+      printf ("expected size %d, got %zu\n", 32768 + 3, size);
+      return 1;
+    }
+
+  for (int i = 0; i < 32768; ++i)
+    if (buf[i] != L'\0')
+      {
+       printf ("wide character at offset %d is %#x\n",
+               i, (unsigned int) buf[i]);
+       return 1;
+      }
+
+  if (wmemcmp (buf + 32768, L"foo", 3) != 0)
+    {
+      puts ("written string incorrect");
+      return 1;
+    }
+
+  /* Mark the buffer.  */
+  wmemset (buf, L'A', size);
+  free (buf);
+
+  /* Try again, this time with write mode enabled before the seek.  */
+  fp = open_wmemstream (&buf, &size);
+  if (fp == NULL)
+    {
+      puts ("2nd open_wmemstream failed");
+      return 1;
+    }
+
+  off = ftello64 (fp);
+  if (off != 0)
+    {
+      puts ("2nd initial position wrong");
+      return 1;
+    }
+
+  if (fputws (L"bar", fp) == EOF)
+    {
+      puts ("2nd fputws failed");
+      return 1;
+    }
+
+  if (fseek (fp, 32768, SEEK_SET) != 0)
+    {
+      puts ("2nd fseek failed");
+      return 1;
+    }
+
+  if (fputws (L"foo", fp) == EOF)
+    {
+      puts ("3rd fputws failed");
+      return 1;
+    }
+
+  if (fclose (fp) == EOF)
+    {
+      puts ("2nd fclose failed");
+      return 1;
+    }
+
+  if (size != 32768 + 3)
+    {
+      printf ("2nd expected size %d, got %zu\n", 32768 + 3, size);
+      return 1;
+    }
+
+  if (wmemcmp (buf, L"bar", 3) != 0)
+    {
+      puts ("initial string incorrect in 2nd try");
+      return 1;
+    }
+
+  for (int i = 3; i < 32768; ++i)
+    if (buf[i] != L'\0')
+      {
+       printf ("wide character at offset %d is %#x in 2nd try\n",
+               i, (unsigned int) buf[i]);
+       return 1;
+      }
+
+  if (wmemcmp (buf + 32768, L"foo", 3) != 0)
+    {
+      puts ("written string incorrect in 2nd try");
+      return 1;
+    }
+
+  return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
index 742da740ef30d7cc6bcc2287ed569b6fc2edc944..877383f3a80d738121008ab0ac448a84e823920b 100644 (file)
@@ -83,7 +83,7 @@ open_memstream (bufloc, sizeloc)
   new_f->fp._sf._sbf._f._lock = &new_f->lock;
 #endif
 
-  buf = malloc (_IO_BUFSIZ);
+  buf = calloc (1, _IO_BUFSIZ);
   if (buf == NULL)
     return NULL;
   INTUSE(_IO_init) (&new_f->fp._sf._sbf._f, 0);
index 2de83403a2a06ea792f3e55cfaca1935c5dbb288..05270ce4073e46870a41cac64797f56bc22bb32d 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 1993, 1997-2003, 2004 Free Software Foundation, Inc.
+/* Copyright (C) 1993, 1997-2003, 2004, 2006 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
    This exception applies to code released by its copyright holders
    in files containing the exception.  */
 
+#include <assert.h>
 #include "strfile.h"
 #include "libioP.h"
 #include <string.h>
 #include <stdio_ext.h>
 
-#if 0
-/* The following definitions are for exposition only.
-   They map the terminology used in the ANSI/ISO C++ draft standard
-   to the implementation. */
-
-/* allocated:  set  when a dynamic array object has been allocated, and
-   hence should be freed by the destructor for the strstreambuf object. */
-#define ALLOCATED(FP) ((FP)->_f._IO_buf_base && DYNAMIC(FP))
-
-/* constant:  set when the array object has const elements,
-   so the output sequence cannot be written. */
-#define CONSTANT(FP) ((FP)->_f._IO_file_flags & _IO_NO_WRITES)
-
-/* alsize:  the suggested minimum size for a dynamic array object. */
-#define ALSIZE(FP) ??? /* not stored */
-
-/* palloc: points to the function to call to allocate a dynamic array object.*/
-#define PALLOC(FP) \
-  ((FP)->_s._allocate_buffer == default_alloc ? 0 : (FP)->_s._allocate_buffer)
-
-/* pfree: points  to  the  function  to call to free a dynamic array object. */
-#define PFREE(FP) \
-  ((FP)->_s._free_buffer == default_free ? 0 : (FP)->_s._free_buffer)
-
-#endif
-
-#ifdef TODO
-/* An "unbounded buffer" is when a buffer is supplied, but with no
-   specified length.  An example is the buffer argument to sprintf.
-   */
-#endif
-
 void
 _IO_str_init_static_internal (sf, ptr, size, pstart)
      _IO_strfile *sf;
@@ -134,7 +103,7 @@ _IO_str_overflow (fp, c)
       fp->_IO_write_ptr = fp->_IO_read_ptr;
       fp->_IO_read_ptr = fp->_IO_read_end;
     }
-  pos =  fp->_IO_write_ptr - fp->_IO_write_base;
+  pos = fp->_IO_write_ptr - fp->_IO_write_base;
   if (pos >= (_IO_size_t) (_IO_blen (fp) + flush_only))
     {
       if (fp->_flags & _IO_USER_BUF) /* not allowed to enlarge */
@@ -143,7 +112,10 @@ _IO_str_overflow (fp, c)
        {
          char *new_buf;
          char *old_buf = fp->_IO_buf_base;
-         _IO_size_t new_size = 2 * _IO_blen (fp) + 100;
+         size_t old_blen = _IO_blen (fp);
+         _IO_size_t new_size = 2 * old_blen + 100;
+         if (new_size < old_blen)
+           return EOF;
          new_buf
            = (char *) (*((_IO_strfile *) fp)->_s._allocate_buffer) (new_size);
          if (new_buf == NULL)
@@ -153,15 +125,13 @@ _IO_str_overflow (fp, c)
            }
          if (old_buf)
            {
-             memcpy (new_buf, old_buf, _IO_blen (fp));
+             memcpy (new_buf, old_buf, old_blen);
              (*((_IO_strfile *) fp)->_s._free_buffer) (old_buf);
              /* Make sure _IO_setb won't try to delete _IO_buf_base. */
              fp->_IO_buf_base = NULL;
            }
-#if 0
-         if (lenp == &LEN(fp)) /* use '\0'-filling */
-             memset (new_buf + pos, 0, blen() - pos);
-#endif
+         memset (new_buf + old_blen, '\0', new_size - old_blen);
+
          INTUSE(_IO_setb) (fp, new_buf, new_buf + new_size, 1);
          fp->_IO_read_base = new_buf + (fp->_IO_read_base - old_buf);
          fp->_IO_read_ptr = new_buf + (fp->_IO_read_ptr - old_buf);
@@ -211,6 +181,71 @@ _IO_str_count (fp)
          - fp->_IO_read_base);
 }
 
+
+static int
+enlarge_userbuf (_IO_FILE *fp, _IO_off64_t offset, int reading)
+{
+  if ((_IO_ssize_t) offset <= _IO_blen (fp))
+    return 0;
+
+  _IO_ssize_t oldend = fp->_IO_write_end - fp->_IO_write_base;
+
+  /* Try to enlarge the buffer.  */
+  if (fp->_flags & _IO_USER_BUF)
+    /* User-provided buffer.  */
+    return 1;
+
+  _IO_size_t newsize = offset + 100;
+  char *oldbuf = fp->_IO_buf_base;
+  char *newbuf
+    = (char *) (*((_IO_strfile *) fp)->_s._allocate_buffer) (newsize);
+  if (newbuf == NULL)
+    return 1;
+
+  if (oldbuf != NULL)
+    {
+      memcpy (newbuf, oldbuf, _IO_blen (fp));
+      (*((_IO_strfile *) fp)->_s._free_buffer) (oldbuf);
+      /* Make sure _IO_setb won't try to delete
+        _IO_buf_base. */
+      fp->_IO_buf_base = NULL;
+    }
+
+  INTUSE(_IO_setb) (fp, newbuf, newbuf + newsize, 1);
+
+  if (reading)
+    {
+      fp->_IO_write_base = newbuf + (fp->_IO_write_base - oldbuf);
+      fp->_IO_write_ptr = newbuf + (fp->_IO_write_ptr - oldbuf);
+      fp->_IO_write_end = newbuf + (fp->_IO_write_end - oldbuf);
+      fp->_IO_read_ptr = newbuf + (fp->_IO_read_ptr - oldbuf);
+
+      fp->_IO_read_base = newbuf;
+      fp->_IO_read_end = fp->_IO_buf_end;
+    }
+  else
+    {
+      fp->_IO_read_base = newbuf + (fp->_IO_read_base - oldbuf);
+      fp->_IO_read_ptr = newbuf + (fp->_IO_read_ptr - oldbuf);
+      fp->_IO_read_end = newbuf + (fp->_IO_read_end - oldbuf);
+      fp->_IO_write_ptr = newbuf + (fp->_IO_write_ptr - oldbuf);
+
+      fp->_IO_write_base = newbuf;
+      fp->_IO_write_end = fp->_IO_buf_end;
+    }
+
+  /* Clear the area between the last write position and th
+     new position.  */
+  assert (offset >= oldend);
+  if (reading)
+    memset (fp->_IO_read_base + oldend, '\0', offset - oldend);
+  else
+    memset (fp->_IO_write_base + oldend, '\0', offset - oldend);
+
+  return 0;
+}
+
+
 _IO_off64_t
 _IO_str_seekoff (fp, offset, dir, mode)
      _IO_FILE *fp;
@@ -251,7 +286,10 @@ _IO_str_seekoff (fp, offset, dir, mode)
            default: /* case _IO_seek_set: */
              break;
            }
-         if (offset < 0 || (_IO_ssize_t) offset > cur_size)
+         if (offset < 0)
+           return EOF;
+         if ((_IO_ssize_t) offset > cur_size
+             && enlarge_userbuf (fp, offset, 1) != 0)
            return EOF;
          fp->_IO_read_ptr = fp->_IO_read_base + offset;
          fp->_IO_read_end = fp->_IO_read_base + cur_size;
@@ -272,7 +310,10 @@ _IO_str_seekoff (fp, offset, dir, mode)
            default: /* case _IO_seek_set: */
              break;
            }
-         if (offset < 0 || (_IO_ssize_t) offset > cur_size)
+         if (offset < 0)
+           return EOF;
+         if ((_IO_ssize_t) offset > cur_size
+             && enlarge_userbuf (fp, offset, 0) != 0)
            return EOF;
          fp->_IO_write_ptr = fp->_IO_write_base + offset;
          new_pos = offset;
index ac7733006dc725e190e638f86846509e73a4b03a..2fdb9f6ed28700f5bbf68d373aaf60e7370a24fb 100644 (file)
@@ -46,6 +46,8 @@ _IO_vasprintf (result_ptr, format, args)
   int ret;
   _IO_size_t needed;
   _IO_size_t allocated;
+  /* No need to clear the memory here (unlike for open_memstream) since
+     we know we will never seek on the stream.  */
   string = (char *) malloc (init_string_size);
   if (string == NULL)
     return -1;
index 1709f2dd337b106598e6a2007e1b0c8c2de94270..85ea64991a8453ce1ee19535ae239a2a0fb6f822 100644 (file)
@@ -83,7 +83,7 @@ open_wmemstream (bufloc, sizeloc)
   new_f->fp._sf._sbf._f._lock = &new_f->lock;
 #endif
 
-  buf = malloc (_IO_BUFSIZ);
+  buf = calloc (1, _IO_BUFSIZ);
   if (buf == NULL)
     return NULL;
 
index 32f7ef3cf7ef1b60aa3dd315847406066d436ea4..8b862fb989304c093de54dd1928d798af16e5160 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 1993,1997-1999,2001-2003,2004 Free Software Foundation, Inc.
+/* Copyright (C) 1993,1997-1999,2001-2004, 2006 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
    This exception applies to code released by its copyright holders
    in files containing the exception.  */
 
+#include <assert.h>
 #include "strfile.h"
 #include "libioP.h"
 #include <string.h>
 #include <wchar.h>
 #include <stdio_ext.h>
 
-#if 0
-/* The following definitions are for exposition only.
-   They map the terminology used in the ANSI/ISO C++ draft standard
-   to the implementation. */
-
-/* allocated:  set  when a dynamic array object has been allocated, and
-   hence should be freed by the destructor for the strstreambuf object. */
-#define ALLOCATED(FP) ((FP)->_f._IO_buf_base && DYNAMIC(FP))
-
-/* constant:  set when the array object has const elements,
-   so the output sequence cannot be written. */
-#define CONSTANT(FP) ((FP)->_f._IO_file_flags & _IO_NO_WRITES)
-
-/* alsize:  the suggested minimum size for a dynamic array object. */
-#define ALSIZE(FP) ??? /* not stored */
-
-/* palloc: points to the function to call to allocate a dynamic array object.*/
-#define PALLOC(FP) \
-  ((FP)->_s._allocate_buffer == default_alloc ? 0 : (FP)->_s._allocate_buffer)
-
-/* pfree: points  to  the  function  to call to free a dynamic array object. */
-#define PFREE(FP) \
-  ((FP)->_s._free_buffer == default_free ? 0 : (FP)->_s._free_buffer)
-
-#endif
-
-#ifdef TODO
-/* An "unbounded buffer" is when a buffer is supplied, but with no
-   specified length.  An example is the buffer argument to sprintf.
-   */
-#endif
-
 void
 _IO_wstr_init_static (fp, ptr, size, pstart)
      _IO_FILE *fp;
@@ -98,7 +67,7 @@ _IO_wstr_init_static (fp, ptr, size, pstart)
       fp->_wide_data->_IO_read_end = end;
     }
   /* A null _allocate_buffer function flags the strfile as being static. */
-  (((_IO_strfile *) fp)->_s._allocate_buffer) =  (_IO_alloc_type)0;
+  (((_IO_strfile *) fp)->_s._allocate_buffer) = (_IO_alloc_type)0;
 }
 
 _IO_wint_t
@@ -116,7 +85,7 @@ _IO_wstr_overflow (fp, c)
       fp->_wide_data->_IO_write_ptr = fp->_wide_data->_IO_read_ptr;
       fp->_wide_data->_IO_read_ptr = fp->_wide_data->_IO_read_end;
     }
-  pos =  fp->_wide_data->_IO_write_ptr - fp->_wide_data->_IO_write_base;
+  pos = fp->_wide_data->_IO_write_ptr - fp->_wide_data->_IO_write_base;
   if (pos >= (_IO_size_t) (_IO_wblen (fp) + flush_only))
     {
       if (fp->_flags & _IO_USER_BUF) /* not allowed to enlarge */
@@ -125,7 +94,10 @@ _IO_wstr_overflow (fp, c)
        {
          wchar_t *new_buf;
          wchar_t *old_buf = fp->_wide_data->_IO_buf_base;
-         _IO_size_t new_size = 2 * _IO_wblen (fp) + 100;
+         size_t old_wblen = _IO_wblen (fp);
+         _IO_size_t new_size = 2 * old_wblen + 100;
+         if (new_size < old_wblen)
+           return EOF;
          new_buf
            = (wchar_t *) (*((_IO_strfile *) fp)->_s._allocate_buffer) (new_size
                                                                        * sizeof (wchar_t));
@@ -136,11 +108,14 @@ _IO_wstr_overflow (fp, c)
            }
          if (old_buf)
            {
-             __wmemcpy (new_buf, old_buf, _IO_wblen (fp));
+             __wmemcpy (new_buf, old_buf, old_wblen);
              (*((_IO_strfile *) fp)->_s._free_buffer) (old_buf);
              /* Make sure _IO_setb won't try to delete _IO_buf_base. */
              fp->_wide_data->_IO_buf_base = NULL;
            }
+
+         wmemset (new_buf + old_wblen, L'\0', new_size - old_wblen);
+
          INTUSE(_IO_wsetb) (fp, new_buf, new_buf + new_size, 1);
          fp->_wide_data->_IO_read_base =
            new_buf + (fp->_wide_data->_IO_read_base - old_buf);
@@ -163,6 +138,7 @@ _IO_wstr_overflow (fp, c)
   return c;
 }
 
+
 _IO_wint_t
 _IO_wstr_underflow (fp)
      _IO_FILE *fp;
@@ -181,17 +157,87 @@ _IO_wstr_underflow (fp)
     return WEOF;
 }
 
-/* The size of the valid part of the buffer.  */
 
+/* The size of the valid part of the buffer.  */
 _IO_ssize_t
 _IO_wstr_count (fp)
      _IO_FILE *fp;
 {
-  return ((fp->_wide_data->_IO_write_ptr > fp->_wide_data->_IO_read_end
-          ? fp->_wide_data->_IO_write_ptr : fp->_wide_data->_IO_read_end)
-         - fp->_wide_data->_IO_read_base);
+  struct _IO_wide_data *wd = fp->_wide_data;
+
+  return ((wd->_IO_write_ptr > wd->_IO_read_end
+          ? wd->_IO_write_ptr : wd->_IO_read_end)
+         - wd->_IO_read_base);
 }
 
+
+static int
+enlarge_userbuf (_IO_FILE *fp, _IO_off64_t offset, int reading)
+{
+  if ((_IO_ssize_t) offset <= _IO_blen (fp))
+    return 0;
+
+  struct _IO_wide_data *wd = fp->_wide_data;
+
+  _IO_ssize_t oldend = wd->_IO_write_end - wd->_IO_write_base;
+
+  /* Try to enlarge the buffer.  */
+  if (fp->_flags & _IO_USER_BUF)
+    /* User-provided buffer.  */
+    return 1;
+
+  _IO_size_t newsize = offset + 100;
+  wchar_t *oldbuf = wd->_IO_buf_base;
+  wchar_t *newbuf
+    = (wchar_t *) (*((_IO_strfile *) fp)->_s._allocate_buffer) (newsize
+                                                               * sizeof (wchar_t));
+  if (newbuf == NULL)
+    return 1;
+
+  if (oldbuf != NULL)
+    {
+      __wmemcpy (newbuf, oldbuf, _IO_wblen (fp));
+      (*((_IO_strfile *) fp)->_s._free_buffer) (oldbuf);
+      /* Make sure _IO_setb won't try to delete
+        _IO_buf_base. */
+      wd->_IO_buf_base = NULL;
+    }
+
+  INTUSE(_IO_wsetb) (fp, newbuf, newbuf + newsize, 1);
+
+  if (reading)
+    {
+      wd->_IO_write_base = newbuf + (wd->_IO_write_base - oldbuf);
+      wd->_IO_write_ptr = newbuf + (wd->_IO_write_ptr - oldbuf);
+      wd->_IO_write_end = newbuf + (wd->_IO_write_end - oldbuf);
+      wd->_IO_read_ptr = newbuf + (wd->_IO_read_ptr - oldbuf);
+
+      wd->_IO_read_base = newbuf;
+      wd->_IO_read_end = wd->_IO_buf_end;
+    }
+  else
+    {
+      wd->_IO_read_base = newbuf + (wd->_IO_read_base - oldbuf);
+      wd->_IO_read_ptr = newbuf + (wd->_IO_read_ptr - oldbuf);
+      wd->_IO_read_end = newbuf + (wd->_IO_read_end - oldbuf);
+      wd->_IO_write_ptr = newbuf + (wd->_IO_write_ptr - oldbuf);
+
+      wd->_IO_write_base = newbuf;
+      wd->_IO_write_end = wd->_IO_buf_end;
+    }
+
+  /* Clear the area between the last write position and th
+     new position.  */
+  assert (offset >= oldend);
+  if (reading)
+    wmemset (wd->_IO_read_base + oldend, L'\0', offset - oldend);
+  else
+    wmemset (wd->_IO_write_base + oldend, L'\0', offset - oldend);
+
+  return 0;
+}
+
+
 _IO_off64_t
 _IO_wstr_seekoff (fp, offset, dir, mode)
      _IO_FILE *fp;
@@ -234,7 +280,10 @@ _IO_wstr_seekoff (fp, offset, dir, mode)
            default: /* case _IO_seek_set: */
              break;
            }
-         if (offset < 0 || (_IO_ssize_t) offset > cur_size)
+         if (offset < 0)
+           return EOF;
+         if ((_IO_ssize_t) offset > cur_size
+             && enlarge_userbuf (fp, offset, 1) != 0)
            return EOF;
          fp->_wide_data->_IO_read_ptr = (fp->_wide_data->_IO_read_base
                                          + offset);
@@ -258,7 +307,10 @@ _IO_wstr_seekoff (fp, offset, dir, mode)
            default: /* case _IO_seek_set: */
              break;
            }
-         if (offset < 0 || (_IO_ssize_t) offset > cur_size)
+         if (offset < 0)
+           return EOF;
+         if ((_IO_ssize_t) offset > cur_size
+             && enlarge_userbuf (fp, offset, 0) != 0)
            return EOF;
          fp->_wide_data->_IO_write_ptr = (fp->_wide_data->_IO_write_base
                                           + offset);
index b0b2e3f805327435e80c31ea300cb7e18a7f5cb2..f38231f984b9e09f06406189c22a02b22c17fd28 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 1995-2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+/* Copyright (C) 1995-2005, 2006 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@gnu.org>, 1995.
 
@@ -992,8 +992,8 @@ ctype_output (struct localedef_t *locale, const struct charmap_t *charmap,
                total += iov[2 + elem + offset].iov_len;
              }
            iov[2 + elem + offset].iov_base = (void *) nulbytes;
-           iov[2 + elem + offset].iov_len = 1 + (4 - ((total + 1) % 4));
-           total += 1 + (4 - ((total + 1) % 4));
+           iov[2 + elem + offset].iov_len = 4 - (total % 4);
+           total += 4 - (total % 4);
 
            idx[elem + 1] = idx[elem] + total;
            break;
@@ -1010,8 +1010,8 @@ ctype_output (struct localedef_t *locale, const struct charmap_t *charmap,
                total += iov[2 + elem + offset].iov_len;
              }
            iov[2 + elem + offset].iov_base = (void *) nulbytes;
-           iov[2 + elem + offset].iov_len = 1 + (4 - ((total + 1) % 4));
-           total += 1 + (4 - ((total + 1) % 4));
+           iov[2 + elem + offset].iov_len = 4 - (total % 4);
+           total += 4 - (total % 4);
 
            idx[elem + 1] = idx[elem] + total;
            break;
@@ -1153,7 +1153,7 @@ ctype_output (struct localedef_t *locale, const struct charmap_t *charmap,
            iov[2 + elem + offset].iov_base =
              ctype->default_missing ?: (uint32_t *) L"";
            iov[2 + elem + offset].iov_len =
-             wcslen (iov[2 + elem + offset].iov_base);
+             wcslen (iov[2 + elem + offset].iov_base) * sizeof (uint32_t);
            idx[elem + 1] = idx[elem] + iov[2 + elem + offset].iov_len;
            break;
 
@@ -3844,9 +3844,14 @@ allocate_arrays (struct locale_ctype_t *ctype, const struct charmap_t *charmap,
     {
       ctype->class_b[nr] = (uint32_t *) xcalloc (256 / 32, sizeof (uint32_t));
 
-      for (idx = 0; idx < 256; ++idx)
-       if (ctype->class256_collection[idx] & _ISbit (nr))
-         ctype->class_b[nr][idx >> 5] |= (uint32_t)1 << (idx & 0x1f);
+      /* We only set CLASS_B for the bits in the ISO C classes, not
+        the user defined classes.  The number should not change but
+        who knows.  */
+#define LAST_ISO_C_BIT 11
+      if (nr <= LAST_ISO_C_BIT)
+       for (idx = 0; idx < 256; ++idx)
+         if (ctype->class256_collection[idx] & _ISbit (nr))
+           ctype->class_b[nr][idx >> 5] |= (uint32_t) 1 << (idx & 0x1f);
     }
 
   for (nr = 0; nr < ctype->nr_charclass; nr++)
index 4f1dcb0ce73e2f42b7c312d19abbf964f7fafcc4..bf5151858a797d977d7d43668b8c6990c4566084 100644 (file)
@@ -542,7 +542,7 @@ time_output (struct localedef_t *locale, const struct charmap_t *charmap,
                              * (2 + _NL_ITEM_INDEX (_NL_NUM_LC_TIME)
                                 + time->num_era - 1
                                 + 2 * 99
-                                + 2 + time->num_era * 10 - 1));
+                                + 2 + time->num_era * 10));
   struct locale_file data;
   uint32_t idx[_NL_ITEM_INDEX (_NL_NUM_LC_TIME)];
   size_t cnt, last_idx, num, n;
@@ -901,6 +901,12 @@ time_output (struct localedef_t *locale, const struct charmap_t *charmap,
   ++cnt;
   ++last_idx;
 
+  /* We must align the following data.  */
+  iov[2 + cnt].iov_base = (void *) "\0\0";
+  iov[2 + cnt].iov_len = -idx[last_idx] & 3;
+  idx[last_idx] += -idx[last_idx] & 3;
+  ++cnt;
+
   iov[2 + cnt].iov_base = (void *) time->wdate_fmt;
   iov[2 + cnt].iov_len = ((wcslen (iov[2 + cnt].iov_base) + 1)
                           * sizeof (uint32_t));
@@ -916,7 +922,7 @@ time_output (struct localedef_t *locale, const struct charmap_t *charmap,
   assert (cnt == (_NL_ITEM_INDEX (_NL_NUM_LC_TIME)
                  + time->num_era - 1
                  + 2 * 99
-                 + 2 + time->num_era * 10 - 1));
+                 + 2 + time->num_era * 10));
   assert (last_idx  == _NL_ITEM_INDEX (_NL_NUM_LC_TIME));
 
   write_locale_data (output_path, LC_TIME, "LC_TIME", 2 + cnt, iov);
index 76129512b6b8cddf82cc3deaae4f4a45e9aa3e54..80adc0406695ee71fd0347e4c9f8bfc524641e74 100644 (file)
@@ -1,3 +1,19 @@
+2006-08-13  Ulrich Drepper  <drepper@redhat.com>
+
+       [BZ #935]
+       * SUPPORTED (SUPPORTED-LOCALES): Add fy_NL.
+       * locales/fy_NL: New file.
+
+2006-08-12  Ulrich Drepper  <drepper@redhat.com>
+
+       [BZ #3034]
+       * locales/pa_IN (day): Fix spelling of Saturday.
+       * locales/or_IN (mon): Fix spelling of May.
+       * locales/ml_IN (day): Fix spelling of Sunday, Monday, Wednesday.
+       (abmon): Fix spelling of March to October.
+       (mon): Fix spelling of March, April, June, August to December.
+       Patches by Mayank Jain <majain@redhat.com>.
+
 2006-06-03  Eddy Petrisor  <eddy.petrisor@gmail.com>
 
        [BZ #2125]
index cd6d91710c1b8831608c2caf6b5e71261b5a3d53..9de5b7ae157d23d856046dd6f430fd7cce2460b9 100644 (file)
@@ -193,6 +193,7 @@ fr_FR@euro/ISO-8859-15 \
 fr_LU.UTF-8/UTF-8 \
 fr_LU/ISO-8859-1 \
 fr_LU@euro/ISO-8859-15 \
+fy_NL/UTF-8 \
 ga_IE.UTF-8/UTF-8 \
 ga_IE/ISO-8859-1 \
 ga_IE@euro/ISO-8859-15 \
diff --git a/localedata/locales/fy_NL b/localedata/locales/fy_NL
new file mode 100644 (file)
index 0000000..d247e50
--- /dev/null
@@ -0,0 +1,139 @@
+comment_char %
+escape_char  /
+%
+% Frisian Language Locale for the Netherlands
+% Language: fy
+% Territory: NL
+% Date: 2006-8-13
+% Users: general
+% Charset: ISO-8859-1
+% Distribution and use is free, also
+% for commercial purposes.
+
+LC_IDENTIFICATION
+title      "Frisian locale for the Netherlands"
+source     "Free Software Foundation, Inc."
+address    "59 Temple Place - Suite 330, Boston, MA 02111-1307, USA"
+contact    ""
+email      "bug-glibc-locales@gnu.org"
+tel        ""
+fax        ""
+language   "Frisian"
+territory  "Netherlands"
+revision   "1.0"
+date       "2006-08-13"
+%
+category  "fy_NL:2000";LC_IDENTIFICATION
+category  "fy_NL:2000";LC_CTYPE
+category  "fy_NL:2000";LC_COLLATE
+category  "fy_NL:2000";LC_TIME
+category  "fy_NL:2000";LC_NUMERIC
+category  "fy_NL:2000";LC_MONETARY
+category  "fy_NL:2000";LC_MEASUREMENT
+category  "fy_NL:2000";LC_MESSAGES
+category  "fy_NL:2000";LC_PAPER
+category  "fy_NL:2000";LC_NAME
+category  "fy_NL:2000";LC_ADDRESS
+category  "fy_NL:2000";LC_TELEPHONE
+END LC_IDENTIFICATION
+
+LC_CTYPE
+copy "nl_NL"
+END LC_CTYPE
+
+LC_COLLATE
+copy "nl_NL"
+END LC_COLLATE
+
+LC_TIME
+abday   "<U0053><U006E>";/
+        "<U004D><U006F>";/
+        "<U0054><U0069>";/
+        "<U0057><U006F>";/
+        "<U0054><U006F>";/
+        "<U0046><U0072>";/
+        "<U0053><U006E>"
+day     "<U0053><U006E><U0065><U0069><U006E>";/
+        "<U004D><U006F><U0061><U006E><U0064><U0065><U0069>";/
+        "<U0054><U0069><U0069><U0073><U0064><U0065><U0069>";/
+        "<U0057><U006F><U0061><U006E><U0073><U0064><U0065><U0069>";/
+        "<U0054><U006F><U006E><U0067><U0065><U0072><U0073><U0064><U0065><U0069>";/
+        "<U0046><U0072><U0065><U0065><U0064>";/
+        "<U0053><U006E><U0065><U006F><U006E>"
+abmon   "<U004A><U0061><U006E>";/
+        "<U0046><U0065><U0062>";/
+        "<U004D><U0061><U0061>";/
+        "<U0041><U0070><U0072>";/
+        "<U004D><U0061><U0061>";/
+        "<U004A><U0075><U006E>";/
+        "<U004A><U0075><U006C>";/
+        "<U0041><U0075><U0067>";/
+        "<U0053><U0065><U0070>";/
+        "<U004F><U006B><U0074>";/
+        "<U004E><U006F><U0076>";/
+        "<U0044><U0065><U0073>"
+mon     "<U004A><U0061><U006E><U0061><U0072><U0069><U0073>";/
+        "<U0046><U0065><U0062><U0072><U0065><U0077><U0061><U0072><U0069><U0073>";/
+        "<U004D><U0061><U0061><U0072><U0074>";/
+        "<U0041><U0070><U0072><U0069><U006C>";/
+        "<U004D><U0061><U0061><U0069><U0065>";/
+        "<U004A><U0075><U006E><U0079>";/
+        "<U004A><U0075><U006C><U0079>";/
+        "<U0041><U0075><U0067><U0075><U0073><U0074><U0075><U0073>";/
+        "<U0053><U0065><U0070><U0074><U0069><U006D><U0062><U0065><U0072>";/
+        "<U004F><U006B><U0074><U006F><U0062><U0065><U0072>";/
+        "<U004E><U006F><U0076><U0069><U006D><U0062><U0065><U0072>";/
+        "<U0044><U0065><U0073><U0069><U006D><U0062><U0065><U0072>"
+d_t_fmt "<U0025><U0061><U0020><U0025><U0064><U0020><U0025><U0062><U0020><U0025><U0059><U0020><U0025><U0054><U0020><U0025><U005A>"
+d_fmt   "<U0025><U0064><U002D><U0025><U006D><U002D><U0025><U0079>"
+t_fmt   "<U0025><U0054>"
+am_pm   "";""
+t_fmt_ampm ""
+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>"
+END LC_TIME
+
+LC_NUMERIC
+copy "nl_NL"
+END LC_NUMERIC
+
+LC_MONETARY
+copy "nl_NL"
+END LC_MONETARY
+
+LC_MEASUREMENT
+copy "nl_NL"
+END LC_MEASUREMENT
+
+LC_MESSAGES
+copy "nl_NL"
+END LC_MESSAGES
+
+LC_PAPER
+copy "nl_NL"
+END LC_PAPER
+
+LC_NAME
+copy "nl_NL"
+END LC_NAME
+
+LC_ADDRESS
+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>/
+<U004E><U0025><U0025><U007A><U0020><U0025><U0054><U0025>/
+<U004E><U0025><U0063><U0025><U004E>"
+country_ab2 "<U004E><U004C>"
+country_ab3 "<U004E><U004C><U0044>"
+country_num 528
+country_car "<U004E><U004C>"
+lang_name "<U0046><U0072><U0069><U0073><U0069><U0061><U006E>"
+lang_ab "<U0066><U0079>"
+lang_term "<U0066><U0072><U0079>"
+lang_lib "<U0066><U0072><U0079>"
+END LC_ADDRESS
+
+LC_TELEPHONE
+copy "nl_NL"
+END LC_TELEPHONE
index 6170d038235df655a79fed29cd0635f8a6a02f0b..03123026d54b89c4ab74e52386b38208980a83ad 100644 (file)
@@ -644,7 +644,7 @@ mon     "<U0B1C><U0B3E><U0B28><U0B41><U0B06><U0B30><U0B40>";/
         "<U0B2B><U0B47><U0B2C><U0B4D><U0B30><U0B41><U0B5F><U0B3E><U0B30><U0B40>";/
         "<U0B2E><U0B3E><U0B30><U0B4D><U0B1A><U0B4D><U0B1A>";/
         "<U0B05><U0B2A><U0B4D><U0B30><U0B47><U0B32>";/
-        "<U0B2E><U0B47>";/
+        "<U0B2E><U0B07>";/
         "<U0B1C><U0B41><U0B28>";/
         "<U0B1C><U0B41><U0B32><U0B3E><U0B07>";/
         "<U0B05><U0B17><U0B37><U0B4D><U0B1F>";/
index d432a169e5785ccdb924421f6483bb1455675287..e38308dfac21c11cd81c053c9d5a3f9dfa5366c1 100644 (file)
@@ -89,7 +89,7 @@ day       "<U0A10><U0A24><U0A35><U0A3E><U0A30><U0020>";/
             "<U0A2C><U0A41><U0A71><U0A27><U0A35><U0A3E><U0A30><U0020>";/
             "<U0A35><U0A40><U0A30><U0A35><U0A3E><U0A30><U0020>";/
             "<U0A36><U0A41><U0A71><U0A15><U0A30><U0A35><U0A3E><U0A30><U0020>";/
-            "<U0A36><U0A28><U0A40><U0A1A><U0A30><U0A35><U0A3E><U0A30><U0020>"
+            "<U0A36><U0A28><U0A3F><U0A71><U0A1A><U0A30><U0A35><U0A3E><U0A30><U0020>"
 
 
 % Abbreviated month names (%b)
index 875dbd59732aeb0c5ea28a61a7c2244ded28b8f4..24ed7f3c46fb152d643f45e3e72cac5bcc2329c8 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 1997, 2002 Free Software Foundation, Inc.
+/* Copyright (C) 1997, 2002, 2006 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Mark Kettenis <kettenis@phys.uva.nl>, 1997.
 
@@ -50,8 +50,7 @@ __utmpname (const char *file)
     {
       if (strcmp (file, default_file_name) == 0)
        {
-         if (__libc_utmp_file_name != default_file_name)
-           free ((char *) __libc_utmp_file_name);
+         free ((char *) __libc_utmp_file_name);
 
          __libc_utmp_file_name = default_file_name;
        }
index a63f62a1cb184827dab8449094fc88e0050e252c..0b0b8ca19fdc014a9fda09fd134920ba54272ea9 100755 (executable)
@@ -558,9 +558,11 @@ sub parse_ulps {
 sub clean_up_number {
   my ($number) = @_;
 
-  # Remove trailing zeros
-  $number =~ s/0+$//;
-  $number =~ s/\.$//;
+  # Remove trailing zeros after the decimal point
+  if ($number =~ /\./) {
+    $number =~ s/0+$//;
+    $number =~ s/\.$//;
+  }
   return $number;
 }
 
index 66a8ccb5016aadae4f632634116d6cdd62a35956..aca435d99590a257f9cc01309afef78a32e7cdd5 100644 (file)
@@ -1,5 +1,5 @@
 /* Error handler for noninteractive utilities
-   Copyright (C) 1990-1998, 2000-2004, 2005 Free Software Foundation, Inc.
+   Copyright (C) 1990-1998, 2000-2005, 2006 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -224,7 +224,10 @@ error_tail (int status, int errnum, const char *message, va_list args)
        {
          /* The string cannot be converted.  */
          if (use_malloc)
-           free (wmessage);
+           {
+             free (wmessage);
+             use_malloc = false;
+           }
          wmessage = (wchar_t *) L"???";
        }
 
@@ -382,14 +385,13 @@ error_at_line (status, errnum, file_name, line_number, message, va_alist)
 #endif
     }
 
-  if (file_name != NULL)
-    {
 #if _LIBC
-      __fxprintf (NULL, "%s:%d: ", file_name, line_number);
+  __fxprintf (NULL, file_name != NULL ? "%s:%d: " : " ",
+             file_name, line_number);
 #else
-      fprintf (stderr, "%s:%d: ", file_name, line_number);
+  fprintf (stderr, file_name != NULL ? "%s:%d: " : " ",
+          file_name, line_number);
 #endif
-    }
 
 #ifdef VA_START
   VA_START (args, message);
index 6450e42574ffd68eaf803cc5f8b2bff7b20f319c..fe6e5c06c32fe3bb4767ff01765659550e77651a 100644 (file)
@@ -1,3 +1,54 @@
+2006-08-14  Jakub Jelinek  <jakub@redhat.com>
+
+       * sysdeps/unix/sysv/linux/bits/posix_opt.h
+       (_POSIX_THREAD_PRIO_PROTECT): Define to 200112L.
+       * descr.h (struct priority_protection_data): New type.
+       (struct pthread): Add tpp field.
+       * pthreadP.h (PTHREAD_MUTEX_PP_NORMAL_NP,
+       PTHREAD_MUTEX_PP_RECURSIVE_NP, PTHREAD_MUTEX_PP_ERRORCHECK_NP,
+       PTHREAD_MUTEX_PP_ADAPTIVE_NP): New enum values.
+       * pthread_mutex_init.c (__pthread_mutex_init): Handle non-robust
+       TPP mutexes.
+       * pthread_mutex_lock.c (__pthread_mutex_lock): Handle TPP mutexes.
+       * pthread_mutex_trylock.c (__pthread_mutex_trylock): Likewise.
+       * pthread_mutex_timedlock.c (pthread_mutex_timedlock): Likewise.
+       * pthread_mutex_unlock.c (__pthread_mutex_unlock_usercnt): Likewise.
+       * tpp.c: New file.
+       * pthread_setschedparam.c (__pthread_setschedparam): Handle priority
+       boosted by TPP.
+       * pthread_setschedprio.c (pthread_setschedprio): Likewise.
+       * pthread_mutexattr_getprioceiling.c
+       (pthread_mutexattr_getprioceiling): If ceiling is 0, ensure it is
+       in the SCHED_FIFO priority range.
+       * pthread_mutexattr_setprioceiling.c
+       (pthread_mutexattr_setprioceiling): Fix prioceiling validation.
+       * pthread_mutex_getprioceiling.c (pthread_mutex_getprioceiling): Fail
+       if mutex is not TPP.  Ceiling is now in __data.__lock.
+       * pthread_mutex_setprioceiling.c: Include stdbool.h.
+       (pthread_mutex_setprioceiling): Fix prioceiling validation.  Ceiling
+       is now in __data.__lock.  Add locking.
+       * pthread_create.c (__free_tcb): Free pd->tpp structure.
+       * Makefile (libpthread-routines): Add tpp.
+       (xtests): Add tst-mutexpp1, tst-mutexpp6 and tst-mutexpp10.
+       * tst-tpp.h: New file.
+       * tst-mutexpp1.c: New file.
+       * tst-mutexpp6.c: New file.
+       * tst-mutexpp10.c: New file.
+       * tst-mutex1.c (TEST_FUNCTION): Don't redefine if already defined.
+       * tst-mutex6.c (TEST_FUNCTION): Likewise.
+
+2006-08-12  Ulrich Drepper  <drepper@redhat.com>
+
+       [BZ #2843]
+       * pthread_join.c (pthread_join): Account for self being canceled
+       when checking for deadlocks.
+       * tst-join5.c: Cleanups.  Allow to be used in tst-join6.
+       (tf1): Don't print anything after pthread_join returns, this would be
+       another cancellation point.
+       (tf2): Likewise.
+       * tst-join6.c: New file.
+       * Makefile (tests): Add tst-join6.
+
 2006-08-03  Ulrich Drepper  <drepper@redhat.com>
 
        [BZ #2892]
index 3a72d3707e26d89b477713b375762eba72138028..c0c09e52fe100247b9e773947ed06467d7e59118 100644 (file)
@@ -224,7 +224,7 @@ tests = tst-typesizes \
        tst-basic1 tst-basic2 tst-basic3 tst-basic4 tst-basic5 tst-basic6 \
        tst-kill1 tst-kill2 tst-kill3 tst-kill4 tst-kill5 tst-kill6 \
        tst-raise1 \
-       tst-join1 tst-join2 tst-join3 tst-join4 tst-join5 \
+       tst-join1 tst-join2 tst-join3 tst-join4 tst-join5 tst-join6 \
        tst-detach1 \
        tst-eintr1 tst-eintr2 tst-eintr3 tst-eintr4 tst-eintr5 \
        tst-tsd1 tst-tsd2 tst-tsd3 tst-tsd4 tst-tsd5 \
index 607aa9fcdbcd2bdf114a150ae69bcb2f9bddbeb6..7acd2f4f22325c419f9f8c5274e9ec9e1c920cd0 100644 (file)
@@ -111,6 +111,14 @@ struct robust_list_head
 };
 
 
+/* Data strcture used to handle thread priority protection.  */
+struct priority_protection_data
+{
+  int priomax;
+  unsigned int priomap[];
+};
+
+
 /* Thread descriptor data structure.  */
 struct pthread
 {
@@ -343,6 +351,9 @@ struct pthread
   /* This is what the user specified and what we will report.  */
   size_t reported_guardsize;
 
+  /* Thread Priority Protection data.  */
+  struct priority_protection_data *tpp;
+
   /* Resolver state.  */
   struct __res_state res;
 
index dc98bb19c0fd7ade380bdcba78f9574f5e18b356..503e99b2b47f8b79a9cb9d7393ad860b4adcede7 100644 (file)
@@ -86,17 +86,31 @@ enum
   = PTHREAD_MUTEX_PRIO_INHERIT_NP | PTHREAD_MUTEX_ROBUST_ERRORCHECK_NP,
   PTHREAD_MUTEX_PI_ROBUST_ADAPTIVE_NP
   = PTHREAD_MUTEX_PRIO_INHERIT_NP | PTHREAD_MUTEX_ROBUST_ADAPTIVE_NP,
-  PTHREAD_MUTEX_PRIO_PROTECT_NP = 64
+  PTHREAD_MUTEX_PRIO_PROTECT_NP = 64,
+  PTHREAD_MUTEX_PP_NORMAL_NP
+  = PTHREAD_MUTEX_PRIO_PROTECT_NP | PTHREAD_MUTEX_NORMAL,
+  PTHREAD_MUTEX_PP_RECURSIVE_NP
+  = PTHREAD_MUTEX_PRIO_PROTECT_NP | PTHREAD_MUTEX_RECURSIVE_NP,
+  PTHREAD_MUTEX_PP_ERRORCHECK_NP
+  = PTHREAD_MUTEX_PRIO_PROTECT_NP | PTHREAD_MUTEX_ERRORCHECK_NP,
+  PTHREAD_MUTEX_PP_ADAPTIVE_NP
+  = PTHREAD_MUTEX_PRIO_PROTECT_NP | PTHREAD_MUTEX_ADAPTIVE_NP
 };
-#define PTHREAD_MUTEX_PRIO_CEILING_SHIFT       16
-#define PTHREAD_MUTEX_PRIO_CEILING_MASK                0x00ff0000
+
+/* Ceiling in __data.__lock.  __data.__lock is signed, so don't
+   use the MSB bit in there, but in the mask also include that bit,
+   so that the compiler can optimize & PTHREAD_MUTEX_PRIO_CEILING_MASK
+   masking if the value is then shifted down by
+   PTHREAD_MUTEX_PRIO_CEILING_SHIFT.  */
+#define PTHREAD_MUTEX_PRIO_CEILING_SHIFT       19
+#define PTHREAD_MUTEX_PRIO_CEILING_MASK                0xfff80000
 
 
 /* Flags in mutex attr.  */
 #define PTHREAD_MUTEXATTR_PROTOCOL_SHIFT       28
 #define PTHREAD_MUTEXATTR_PROTOCOL_MASK                0x30000000
-#define PTHREAD_MUTEXATTR_PRIO_CEILING_SHIFT   16
-#define PTHREAD_MUTEXATTR_PRIO_CEILING_MASK    0x00ff0000
+#define PTHREAD_MUTEXATTR_PRIO_CEILING_SHIFT   12
+#define PTHREAD_MUTEXATTR_PRIO_CEILING_MASK    0x00fff000
 #define PTHREAD_MUTEXATTR_FLAG_ROBUST          0x40000000
 #define PTHREAD_MUTEXATTR_FLAG_PSHARED         0x80000000
 #define PTHREAD_MUTEXATTR_FLAG_BITS \
@@ -151,6 +165,14 @@ extern unsigned int __nptl_nthreads attribute_hidden;
 extern int __set_robust_list_avail attribute_hidden;
 #endif
 
+/* Thread Priority Protection.  */
+extern int __sched_fifo_min_prio attribute_hidden;
+extern int __sched_fifo_max_prio attribute_hidden;
+extern void __init_sched_fifo_prio (void) attribute_hidden;
+extern int __pthread_tpp_change_priority (int prev_prio, int new_prio)
+     attribute_hidden;
+extern int __pthread_current_priority (void) attribute_hidden;
+
 /* The library can run in debugging mode where it performs a lot more
    tests.  */
 extern int __pthread_debug attribute_hidden;
index c1ac199bb9436dcd162d028587188078e939b2ff..315722643b975229b108183c0851b5ac57babd99 100644 (file)
@@ -206,6 +206,15 @@ __free_tcb (struct pthread *pd)
           running thread is gone.  */
        abort ();
 
+      /* Free TPP data.  */
+      if (__builtin_expect (pd->tpp != NULL, 0))
+       {
+         struct priority_protection_data *tpp = pd->tpp;
+
+         pd->tpp = NULL;
+         free (tpp);
+       }
+
       /* Queue the stack memory block for reuse and exit the process.  The
         kernel will signal via writing to the address returned by
         QUEUE-STACK when the stack is available.  */
index 70dc81a023dd049767b316ea53851ddf6b95e405..c88d85b52f57f46117b6cfb37137925088b104d9 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc.
+/* Copyright (C) 2002, 2003, 2005, 2006 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
 
 static void
 cleanup (void *arg)
 {
-  *(void **) arg = NULL;
+  /* If we already changed the waiter ID, reset it.  The call cannot
+     fail for any reason but the thread not having done that yet so
+     there is no reason for a loop.  */
+  atomic_compare_and_exchange_bool_acq ((struct pthread **) arg, NULL,
+                                       THREAD_SELF);
 }
 
 
@@ -36,7 +40,6 @@ pthread_join (threadid, thread_return)
      pthread_t threadid;
      void **thread_return;
 {
-  struct pthread *self;
   struct pthread *pd = (struct pthread *) threadid;
 
   /* Make sure the descriptor is valid.  */
@@ -49,12 +52,23 @@ pthread_join (threadid, thread_return)
     /* We cannot wait for the thread.  */
     return EINVAL;
 
-  self = THREAD_SELF;
-  if (pd == self
-      || (self->joinid == pd
-         && (pd->cancelhandling
-             & (CANCELING_BITMASK | CANCELED_BITMASK | EXITING_BITMASK
-                | TERMINATED_BITMASK)) == 0))
+  struct pthread *self = THREAD_SELF;
+  int result = 0;
+
+  /* During the wait we change to asynchronous cancellation.  If we
+     are canceled the thread we are waiting for must be marked as
+     un-wait-ed for again.  */
+  pthread_cleanup_push (cleanup, &pd->joinid);
+
+  /* Switch to asynchronous cancellation.  */
+  int oldtype = CANCEL_ASYNC ();
+
+  if ((pd == self
+       || (self->joinid == pd
+          && (pd->cancelhandling
+              & (CANCELING_BITMASK | CANCELED_BITMASK | EXITING_BITMASK
+                 | TERMINATED_BITMASK)) == 0))
+      && !CANCEL_ENABLED_AND_CANCELED (self->cancelhandling))
     /* This is a deadlock situation.  The threads are waiting for each
        other to finish.  Note that this is a "may" error.  To be 100%
        sure we catch this error we would have to lock the data
@@ -62,28 +76,17 @@ pthread_join (threadid, thread_return)
        two threads are really caught in this situation they will
        deadlock.  It is the programmer's problem to figure this
        out.  */
-    return EDEADLK;
-
+    result = EDEADLK;
   /* Wait for the thread to finish.  If it is already locked something
      is wrong.  There can only be one waiter.  */
-  if (__builtin_expect (atomic_compare_and_exchange_bool_acq (&pd->joinid,
-                                                             self,
-                                                             NULL), 0))
+  else if (__builtin_expect (atomic_compare_and_exchange_bool_acq (&pd->joinid,
+                                                                  self,
+                                                                  NULL), 0))
     /* There is already somebody waiting for the thread.  */
-    return EINVAL;
-
-
-  /* During the wait we change to asynchronous cancellation.  If we
-     are cancelled the thread we are waiting for must be marked as
-     un-wait-ed for again.  */
-  pthread_cleanup_push (cleanup, &pd->joinid);
-
-  /* Switch to asynchronous cancellation.  */
-  int oldtype = CANCEL_ASYNC ();
-
-
-  /* Wait for the child.  */
-  lll_wait_tid (pd->tid);
+    result = EINVAL;
+  else
+    /* Wait for the child.  */
+    lll_wait_tid (pd->tid);
 
 
   /* Restore cancellation mode.  */
@@ -93,16 +96,19 @@ pthread_join (threadid, thread_return)
   pthread_cleanup_pop (0);
 
 
-  /* We mark the thread as terminated and as joined.  */
-  pd->tid = -1;
+  if (__builtin_expect (result == 0, 1))
+    {
+      /* We mark the thread as terminated and as joined.  */
+      pd->tid = -1;
 
-  /* Store the return value if the caller is interested.  */
-  if (thread_return != NULL)
-    *thread_return = pd->result;
+      /* Store the return value if the caller is interested.  */
+      if (thread_return != NULL)
+       *thread_return = pd->result;
 
 
-  /* Free the TCB.  */
-  __free_tcb (pd);
+      /* Free the TCB.  */
+      __free_tcb (pd);
+    }
 
-  return 0;
+  return result;
 }
index 4d1bc2843113275f4ccb1b16f6001210f65257a5..1ce5eaebefa5e67242a3c1735f01d22e405c85a3 100644 (file)
@@ -18,6 +18,7 @@
    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
    02111-1307 USA.  */
 
+#include <errno.h>
 #include <pthreadP.h>
 
 
@@ -26,7 +27,11 @@ pthread_mutex_getprioceiling (mutex, prioceiling)
      const pthread_mutex_t *mutex;
      int *prioceiling;
 {
-  *prioceiling = (mutex->__data.__kind & PTHREAD_MUTEX_PRIO_CEILING_MASK)
+  if (__builtin_expect ((mutex->__data.__kind
+                        & PTHREAD_MUTEX_PRIO_PROTECT_NP) == 0, 0))
+    return EINVAL;
+
+  *prioceiling = (mutex->__data.__lock & PTHREAD_MUTEX_PRIO_CEILING_MASK)
                 >> PTHREAD_MUTEX_PRIO_CEILING_SHIFT;
 
   return 0;
index 6ceca86052dbd45790439ac357df7506fdf836b7..96f1fb00f8d37975b1c1cfd1dbbeac3c007c6bd0 100644 (file)
@@ -46,7 +46,6 @@ __pthread_mutex_init (mutex, mutexattr)
   imutexattr = (const struct pthread_mutexattr *) mutexattr ?: &default_attr;
 
   /* Sanity checks.  */
-  // XXX For now we don't support priority protected mutexes.
   switch (__builtin_expect (imutexattr->mutexkind
                            & PTHREAD_MUTEXATTR_PROTOCOL_MASK,
                            PTHREAD_PRIO_NONE
@@ -72,7 +71,10 @@ __pthread_mutex_init (mutex, mutexattr)
       break;
 
     default:
-      return ENOTSUP;
+      /* XXX: For now we don't support robust priority protected mutexes.  */
+      if (imutexattr->mutexkind & PTHREAD_MUTEXATTR_FLAG_ROBUST)
+       return ENOTSUP;
+      break;
     }
 
   /* Clear the whole variable.  */
@@ -100,15 +102,18 @@ __pthread_mutex_init (mutex, mutexattr)
 
     case PTHREAD_PRIO_PROTECT << PTHREAD_MUTEXATTR_PROTOCOL_SHIFT:
       mutex->__data.__kind |= PTHREAD_MUTEX_PRIO_PROTECT_NP;
-      if (PTHREAD_MUTEX_PRIO_CEILING_MASK
-         == PTHREAD_MUTEXATTR_PRIO_CEILING_MASK)
-       mutex->__data.__kind |= (imutexattr->mutexkind
-                                & PTHREAD_MUTEXATTR_PRIO_CEILING_MASK);
-      else
-       mutex->__data.__kind |= ((imutexattr->mutexkind
-                                 & PTHREAD_MUTEXATTR_PRIO_CEILING_MASK)
-                                >> PTHREAD_MUTEXATTR_PRIO_CEILING_SHIFT)
-                               << PTHREAD_MUTEX_PRIO_CEILING_SHIFT;
+
+      int ceiling = (imutexattr->mutexkind
+                    & PTHREAD_MUTEXATTR_PRIO_CEILING_MASK)
+                   >> PTHREAD_MUTEXATTR_PRIO_CEILING_SHIFT;
+      if (! ceiling)
+       {
+         if (__sched_fifo_min_prio == -1)
+           __init_sched_fifo_prio ();
+         if (ceiling < __sched_fifo_min_prio)
+           ceiling = __sched_fifo_min_prio;
+       }
+      mutex->__data.__lock = ceiling << PTHREAD_MUTEX_PRIO_CEILING_SHIFT;
       break;
 
     default:
index a19c90769597ac60517a55329cfbf294c96f8279..52cc47f4cc81f1a37a3b56cf3ba8a2a826979e79 100644 (file)
@@ -335,6 +335,90 @@ __pthread_mutex_lock (mutex)
       }
       break;
 
+    case PTHREAD_MUTEX_PP_RECURSIVE_NP:
+    case PTHREAD_MUTEX_PP_ERRORCHECK_NP:
+    case PTHREAD_MUTEX_PP_NORMAL_NP:
+    case PTHREAD_MUTEX_PP_ADAPTIVE_NP:
+      {
+       int kind = mutex->__data.__kind & PTHREAD_MUTEX_KIND_MASK_NP;
+
+       oldval = mutex->__data.__lock;
+
+       /* Check whether we already hold the mutex.  */
+       if (mutex->__data.__owner == id)
+         {
+           if (kind == PTHREAD_MUTEX_ERRORCHECK_NP)
+             return EDEADLK;
+
+           if (kind == PTHREAD_MUTEX_RECURSIVE_NP)
+             {
+               /* Just bump the counter.  */
+               if (__builtin_expect (mutex->__data.__count + 1 == 0, 0))
+                 /* Overflow of the counter.  */
+                 return EAGAIN;
+
+               ++mutex->__data.__count;
+
+               return 0;
+             }
+         }
+
+       int oldprio = -1, ceilval;
+       do
+         {
+           int ceiling = (oldval & PTHREAD_MUTEX_PRIO_CEILING_MASK)
+                         >> PTHREAD_MUTEX_PRIO_CEILING_SHIFT;
+
+           if (__pthread_current_priority () > ceiling)
+             {
+               if (oldprio != -1)
+                 __pthread_tpp_change_priority (oldprio, -1);
+               return EINVAL;
+             }
+
+           retval = __pthread_tpp_change_priority (oldprio, ceiling);
+           if (retval)
+             return retval;
+
+           ceilval = ceiling << PTHREAD_MUTEX_PRIO_CEILING_SHIFT;
+           oldprio = ceiling;
+
+           oldval
+             = atomic_compare_and_exchange_val_acq (&mutex->__data.__lock,
+#ifdef NO_INCR
+                                                    ceilval | 2,
+#else
+                                                    ceilval | 1,
+#endif
+                                                    ceilval);
+
+           if (oldval == ceilval)
+             break;
+
+           do
+             {
+               oldval
+                 = atomic_compare_and_exchange_val_acq (&mutex->__data.__lock,
+                                                        ceilval | 2,
+                                                        ceilval | 1);
+
+               if ((oldval & PTHREAD_MUTEX_PRIO_CEILING_MASK) != ceilval)
+                 break;
+
+               if (oldval != ceilval)
+                 lll_futex_wait (&mutex->__data.__lock, ceilval | 2);
+             }
+           while (atomic_compare_and_exchange_val_acq (&mutex->__data.__lock,
+                                                       ceilval | 2, ceilval)
+                  != ceilval);
+         }
+       while ((oldval & PTHREAD_MUTEX_PRIO_CEILING_MASK) != ceilval);
+
+       assert (mutex->__data.__owner == 0);
+       mutex->__data.__count = 1;
+      }
+      break;
+
     default:
       /* Correct code cannot set any other type.  */
       return EINVAL;
index 3271f8833a4e9a6f2f724d0016f4a7dd2f224638..cd13d1c14cf419a1890316a772cf5cab3cd27825 100644 (file)
@@ -18,6 +18,7 @@
    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
    02111-1307 USA.  */
 
+#include <stdbool.h>
 #include <errno.h>
 #include <pthreadP.h>
 
@@ -33,23 +34,83 @@ pthread_mutex_setprioceiling (mutex, prioceiling, old_ceiling)
   if ((mutex->__data.__kind & PTHREAD_MUTEX_PRIO_PROTECT_NP) == 0)
     return EINVAL;
 
-  if (prioceiling < 0 || __builtin_expect (prioceiling > 255, 0))
+  if (__sched_fifo_min_prio == -1)
+    __init_sched_fifo_prio ();
+
+  if (__builtin_expect (prioceiling < __sched_fifo_min_prio, 0)
+      || __builtin_expect (prioceiling > __sched_fifo_max_prio, 0)
+      || __builtin_expect ((prioceiling
+                           & (PTHREAD_MUTEXATTR_PRIO_CEILING_MASK
+                              >> PTHREAD_MUTEXATTR_PRIO_CEILING_SHIFT))
+                          != prioceiling, 0))
     return EINVAL;
 
-  /* XXX This needs to lock with TID, but shouldn't obey priority protect
-     protocol.  */
-  /* lll_xxx_mutex_lock (mutex->__data.__lock); */
+  /* Check whether we already hold the mutex.  */
+  bool locked = false;
+  if (mutex->__data.__owner == THREAD_GETMEM (THREAD_SELF, tid))
+    {
+      if (mutex->__data.__kind == PTHREAD_MUTEX_PP_ERRORCHECK_NP)
+       return EDEADLK;
+
+      if (mutex->__data.__kind == PTHREAD_MUTEX_PP_RECURSIVE_NP)
+       locked = true;
+    }
+
+  int oldval = mutex->__data.__lock;
+  if (! locked)
+    do
+      {
+       /* Need to lock the mutex, but without obeying the priority
+          protect protocol.  */
+       int ceilval = (oldval & PTHREAD_MUTEX_PRIO_CEILING_MASK);
+
+       oldval = atomic_compare_and_exchange_val_acq (&mutex->__data.__lock,
+                                                     ceilval | 1, ceilval);
+       if (oldval == ceilval)
+         break;
+
+       do
+         {
+           oldval
+             = atomic_compare_and_exchange_val_acq (&mutex->__data.__lock,
+                                                    ceilval | 2,
+                                                    ceilval | 1);
+
+           if ((oldval & PTHREAD_MUTEX_PRIO_CEILING_MASK) != ceilval)
+             break;
+
+           if (oldval != ceilval)
+             lll_futex_wait (&mutex->__data.__lock, ceilval | 2);
+         }
+       while (atomic_compare_and_exchange_val_acq (&mutex->__data.__lock,
+                                                   ceilval | 2, ceilval)
+              != ceilval);
+
+       if ((oldval & PTHREAD_MUTEX_PRIO_CEILING_MASK) != ceilval)
+         continue;
+      }
+    while (0);
+
+  int oldprio = (oldval & PTHREAD_MUTEX_PRIO_CEILING_MASK)
+               >> PTHREAD_MUTEX_PRIO_CEILING_SHIFT;
+  if (locked)
+    {
+      int ret = __pthread_tpp_change_priority (oldprio, prioceiling);
+      if (ret)
+       return ret;
+    }
 
   if (old_ceiling != NULL)
-    *old_ceiling = (mutex->__data.__kind & PTHREAD_MUTEX_PRIO_CEILING_MASK)
-                  >> PTHREAD_MUTEX_PRIO_CEILING_SHIFT;
+    *old_ceiling = oldprio;
 
-  int newkind = (mutex->__data.__kind & ~PTHREAD_MUTEX_PRIO_CEILING_MASK);
-  mutex->__data.__kind = newkind
+  int newlock = 0;
+  if (locked)
+    newlock = (mutex->__data.__lock & ~PTHREAD_MUTEX_PRIO_CEILING_MASK);
+  mutex->__data.__lock = newlock
                         | (prioceiling << PTHREAD_MUTEX_PRIO_CEILING_SHIFT);
+  atomic_full_barrier ();
 
-  /* XXX This needs to unlock the above special kind of lock.  */
-  /* lll_xxx_mutex_unlock (mutex->__data.__lock); */
+  lll_futex_wake (&mutex->__data.__lock, INT_MAX);
 
   return 0;
 }
index dcff4f81a84e436c0f5bf18e074ff837fd8bc3c0..c8e6b8507a30157ec4bc6d8737a7c4e0dd14156b 100644 (file)
@@ -340,6 +340,119 @@ pthread_mutex_timedlock (mutex, abstime)
        }
       break;
 
+    case PTHREAD_MUTEX_PP_RECURSIVE_NP:
+    case PTHREAD_MUTEX_PP_ERRORCHECK_NP:
+    case PTHREAD_MUTEX_PP_NORMAL_NP:
+    case PTHREAD_MUTEX_PP_ADAPTIVE_NP:
+      {
+       int kind = mutex->__data.__kind & PTHREAD_MUTEX_KIND_MASK_NP;
+
+       oldval = mutex->__data.__lock;
+
+       /* Check whether we already hold the mutex.  */
+       if (mutex->__data.__owner == id)
+         {
+           if (kind == PTHREAD_MUTEX_ERRORCHECK_NP)
+             return EDEADLK;
+
+           if (kind == PTHREAD_MUTEX_RECURSIVE_NP)
+             {
+               /* Just bump the counter.  */
+               if (__builtin_expect (mutex->__data.__count + 1 == 0, 0))
+                 /* Overflow of the counter.  */
+                 return EAGAIN;
+
+               ++mutex->__data.__count;
+
+               return 0;
+             }
+         }
+
+       int oldprio = -1, ceilval;
+       do
+         {
+           int ceiling = (oldval & PTHREAD_MUTEX_PRIO_CEILING_MASK)
+                         >> PTHREAD_MUTEX_PRIO_CEILING_SHIFT;
+
+           if (__pthread_current_priority () > ceiling)
+             {
+               result = EINVAL;
+             failpp:
+               if (oldprio != -1)
+                 __pthread_tpp_change_priority (oldprio, -1);
+               return result;
+             }
+
+           result = __pthread_tpp_change_priority (oldprio, ceiling);
+           if (result)
+             return result;
+
+           ceilval = ceiling << PTHREAD_MUTEX_PRIO_CEILING_SHIFT;
+           oldprio = ceiling;
+
+           oldval
+             = atomic_compare_and_exchange_val_acq (&mutex->__data.__lock,
+                                                    ceilval | 1, ceilval);
+
+           if (oldval == ceilval)
+             break;
+
+           do
+             {
+               oldval
+                 = atomic_compare_and_exchange_val_acq (&mutex->__data.__lock,
+                                                        ceilval | 2,
+                                                        ceilval | 1);
+
+               if ((oldval & PTHREAD_MUTEX_PRIO_CEILING_MASK) != ceilval)
+                 break;
+
+               if (oldval != ceilval)
+                 {
+                   /* Reject invalid timeouts.  */
+                   if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000)
+                     {
+                       result = EINVAL;
+                       goto failpp;
+                     }
+
+                   struct timeval tv;
+                   struct timespec rt;
+
+                   /* Get the current time.  */
+                   (void) __gettimeofday (&tv, NULL);
+
+                   /* Compute relative timeout.  */
+                   rt.tv_sec = abstime->tv_sec - tv.tv_sec;
+                   rt.tv_nsec = abstime->tv_nsec - tv.tv_usec * 1000;
+                   if (rt.tv_nsec < 0)
+                     {
+                       rt.tv_nsec += 1000000000;
+                       --rt.tv_sec;
+                     }
+
+                   /* Already timed out?  */
+                   if (rt.tv_sec < 0)
+                     {
+                       result = ETIMEDOUT;
+                       goto failpp;
+                     }
+
+                   lll_futex_timed_wait (&mutex->__data.__lock,
+                                         ceilval | 2, &rt);
+                 }
+             }
+           while (atomic_compare_and_exchange_val_acq (&mutex->__data.__lock,
+                                                       ceilval | 2, ceilval)
+                  != ceilval);
+         }
+       while ((oldval & PTHREAD_MUTEX_PRIO_CEILING_MASK) != ceilval);
+
+       assert (mutex->__data.__owner == 0);
+       mutex->__data.__count = 1;
+      }
+      break;
+
     default:
       /* Correct code cannot set any other type.  */
       return EINVAL;
index f3a18569a14617411dc06c344545477802162cfb..94d519233b5d5d3dce880aebb706f1d0916b3b83 100644 (file)
@@ -297,6 +297,79 @@ __pthread_mutex_trylock (mutex)
        return 0;
       }
 
+    case PTHREAD_MUTEX_PP_RECURSIVE_NP:
+    case PTHREAD_MUTEX_PP_ERRORCHECK_NP:
+    case PTHREAD_MUTEX_PP_NORMAL_NP:
+    case PTHREAD_MUTEX_PP_ADAPTIVE_NP:
+      {
+       int kind = mutex->__data.__kind & PTHREAD_MUTEX_KIND_MASK_NP;
+
+       oldval = mutex->__data.__lock;
+
+       /* Check whether we already hold the mutex.  */
+       if (mutex->__data.__owner == id)
+         {
+           if (kind == PTHREAD_MUTEX_ERRORCHECK_NP)
+             return EDEADLK;
+
+           if (kind == PTHREAD_MUTEX_RECURSIVE_NP)
+             {
+               /* Just bump the counter.  */
+               if (__builtin_expect (mutex->__data.__count + 1 == 0, 0))
+                 /* Overflow of the counter.  */
+                 return EAGAIN;
+
+               ++mutex->__data.__count;
+
+               return 0;
+             }
+         }
+
+       int oldprio = -1, ceilval;
+       do
+         {
+           int ceiling = (oldval & PTHREAD_MUTEX_PRIO_CEILING_MASK)
+                         >> PTHREAD_MUTEX_PRIO_CEILING_SHIFT;
+
+           if (__pthread_current_priority () > ceiling)
+             {
+               if (oldprio != -1)
+                 __pthread_tpp_change_priority (oldprio, -1);
+               return EINVAL;
+             }
+
+           int retval = __pthread_tpp_change_priority (oldprio, ceiling);
+           if (retval)
+             return retval;
+
+           ceilval = ceiling << PTHREAD_MUTEX_PRIO_CEILING_SHIFT;
+           oldprio = ceiling;
+
+           oldval
+             = atomic_compare_and_exchange_val_acq (&mutex->__data.__lock,
+                                                    ceilval | 1, ceilval);
+
+           if (oldval == ceilval)
+             break;
+         }
+       while ((oldval & PTHREAD_MUTEX_PRIO_CEILING_MASK) != ceilval);
+
+       if (oldval != ceilval)
+         {
+           __pthread_tpp_change_priority (oldprio, -1);
+           break;
+         }
+
+       assert (mutex->__data.__owner == 0);
+       /* Record the ownership.  */
+       mutex->__data.__owner = id;
+       ++mutex->__data.__nusers;
+       mutex->__data.__count = 1;
+
+       return 0;
+      }
+      break;
+
     default:
       /* Correct code cannot set any other type.  */
       return EINVAL;
index 2b5064fbacabbcede14d1d9a2a9700ef59152dc3..33919d60af129e74c26e4c58fe3842800658ae69 100644 (file)
@@ -202,6 +202,49 @@ __pthread_mutex_unlock_usercnt (mutex, decr)
       THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL);
       break;
 
+    case PTHREAD_MUTEX_PP_RECURSIVE_NP:
+      /* Recursive mutex.  */
+      if (mutex->__data.__owner != THREAD_GETMEM (THREAD_SELF, tid))
+       return EPERM;
+
+      if (--mutex->__data.__count != 0)
+       /* We still hold the mutex.  */
+       return 0;
+      goto pp;
+
+    case PTHREAD_MUTEX_PP_ERRORCHECK_NP:
+      /* Error checking mutex.  */
+      if (mutex->__data.__owner != THREAD_GETMEM (THREAD_SELF, tid)
+         || (mutex->__data.__lock & ~ PTHREAD_MUTEX_PRIO_CEILING_MASK) == 0)
+       return EPERM;
+      /* FALLTHROUGH */
+
+    case PTHREAD_MUTEX_PP_NORMAL_NP:
+    case PTHREAD_MUTEX_PP_ADAPTIVE_NP:
+      /* Always reset the owner field.  */
+    pp:
+      mutex->__data.__owner = 0;
+
+      if (decr)
+       /* One less user.  */
+       --mutex->__data.__nusers;
+
+      /* Unlock.  */
+      int newval, oldval;
+      do
+       {
+         oldval = mutex->__data.__lock;
+         newval = oldval & PTHREAD_MUTEX_PRIO_CEILING_MASK;
+       }
+      while (atomic_compare_and_exchange_bool_acq (&mutex->__data.__lock,
+                                                  newval, oldval));
+
+      if ((oldval & ~PTHREAD_MUTEX_PRIO_CEILING_MASK) > 1)
+       lll_futex_wake (&mutex->__data.__lock, 1);
+
+      int oldprio = newval >> PTHREAD_MUTEX_PRIO_CEILING_SHIFT;
+      return __pthread_tpp_change_priority (oldprio, -1);
+
     default:
       /* Correct code cannot set any other type.  */
       return EINVAL;
index da1beabf46835c3a5ba5752daee6fc14b5667c54..792e9a43d6342e8498e4a0d14a45aa0959380f0f 100644 (file)
@@ -27,11 +27,22 @@ pthread_mutexattr_getprioceiling (attr, prioceiling)
      int *prioceiling;
 {
   const struct pthread_mutexattr *iattr;
+  int ceiling;
 
   iattr = (const struct pthread_mutexattr *) attr;
 
-  *prioceiling = ((iattr->mutexkind & PTHREAD_MUTEXATTR_PRIO_CEILING_MASK)
-                 >> PTHREAD_MUTEXATTR_PRIO_CEILING_SHIFT);
+  ceiling = ((iattr->mutexkind & PTHREAD_MUTEXATTR_PRIO_CEILING_MASK)
+            >> PTHREAD_MUTEXATTR_PRIO_CEILING_SHIFT);
+
+  if (! ceiling)
+    {
+      if (__sched_fifo_min_prio == -1)
+       __init_sched_fifo_prio ();
+      if (ceiling < __sched_fifo_min_prio)
+       ceiling = __sched_fifo_min_prio;
+    }
+
+  *prioceiling = ceiling;
 
   return 0;
 }
index 6c15b4683300e8e4c4352adff47a7211386cda0b..9b7874f739afc33d3013365ecdeb55c508c50b1d 100644 (file)
@@ -27,7 +27,15 @@ pthread_mutexattr_setprioceiling (attr, prioceiling)
      pthread_mutexattr_t *attr;
      int prioceiling;
 {
-  if (prioceiling < 0 || __builtin_expect (prioceiling > 255, 0))
+  if (__sched_fifo_min_prio == -1)
+    __init_sched_fifo_prio ();
+
+  if (__builtin_expect (prioceiling < __sched_fifo_min_prio, 0)
+      || __builtin_expect (prioceiling > __sched_fifo_max_prio, 0)
+      || __builtin_expect ((prioceiling
+                           & (PTHREAD_MUTEXATTR_PRIO_CEILING_MASK
+                              >> PTHREAD_MUTEXATTR_PRIO_CEILING_SHIFT))
+                          != prioceiling, 0))
     return EINVAL;
 
   struct pthread_mutexattr *iattr = (struct pthread_mutexattr *) attr;
index 5889cc98a9c253e01346316571a6cd0ff118fea5..30ac6b3e8911d8ab7d77513ad5fff11618bd51a4 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+/* Copyright (C) 2002, 2003, 2004, 2006 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
 
@@ -45,6 +45,19 @@ __pthread_setschedparam (threadid, policy, param)
 
   lll_lock (pd->lock);
 
+  struct sched_param p;
+  const struct sched_param *orig_param = param;
+
+  /* If the thread should have higher priority because of some
+     PTHREAD_PRIO_PROTECT mutexes it holds, adjust the priority.  */
+  if (__builtin_expect (pd->tpp != NULL, 0)
+      && pd->tpp->priomax > param->sched_priority)
+    {
+      p = *param;
+      p.sched_priority = pd->tpp->priomax;
+      param = &p;
+    }
+
   /* Try to set the scheduler information.  */
   if (__builtin_expect (__sched_setscheduler (pd->tid, policy,
                                              param) == -1, 0))
@@ -54,7 +67,7 @@ __pthread_setschedparam (threadid, policy, param)
       /* We succeeded changing the kernel information.  Reflect this
         change in the thread descriptor.  */
       pd->schedpolicy = policy;
-      memcpy (&pd->schedparam, param, sizeof (struct sched_param));
+      memcpy (&pd->schedparam, orig_param, sizeof (struct sched_param));
       pd->flags |= ATTR_FLAG_SCHED_SET | ATTR_FLAG_POLICY_SET;
     }
 
index 063f5232f5a58609090d9cda61933db0d1afc02b..4a71f6c7b3973871fddcd3e63d9c738a8878eb27 100644 (file)
@@ -47,6 +47,11 @@ pthread_setschedprio (threadid, prio)
 
   lll_lock (pd->lock);
 
+  /* If the thread should have higher priority because of some
+     PTHREAD_PRIO_PROTECT mutexes it holds, adjust the priority.  */
+  if (__builtin_expect (pd->tpp != NULL, 0) && pd->tpp->priomax > prio)
+    param.sched_priority = pd->tpp->priomax;
+
   /* Try to set the scheduler information.  */
   if (__builtin_expect (sched_setparam (pd->tid, &param) == -1, 0))
     result = errno;
@@ -54,6 +59,7 @@ pthread_setschedprio (threadid, prio)
     {
       /* We succeeded changing the kernel information.  Reflect this
         change in the thread descriptor.  */
+      param.sched_priority = prio;
       memcpy (&pd->schedparam, &param, sizeof (struct sched_param));
       pd->flags |= ATTR_FLAG_SCHED_SET;
     }
index d8eced1f22799c2584f9c52a6f65ac448a95fbf8..40160c54de3fa28d0a9233e8ffea3b62f7e1624a 100644 (file)
 /* We support priority inheritence.  */
 #define _POSIX_THREAD_PRIO_INHERIT     200112L
 
+/* We support priority protection, though only for non-robust
+   mutexes.  */
+#define _POSIX_THREAD_PRIO_PROTECT     200112L
+
 /* We support POSIX.1b semaphores.  */
 #define _POSIX_SEMAPHORES      200112L
 
 /* Typed memory objects are not available.  */
 #define _POSIX_TYPED_MEMORY_OBJECTS    -1
 
-/* No support for priority protection so far.  */
-#define _POSIX_THREAD_PRIO_PROTECT     -1
-
 #endif /* posix_opt.h */
diff --git a/nptl/tpp.c b/nptl/tpp.c
new file mode 100644 (file)
index 0000000..367dd81
--- /dev/null
@@ -0,0 +1,172 @@
+/* Thread Priority Protect helpers.
+   Copyright (C) 2006 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Jakub Jelinek <jakub@redhat.com>, 2006.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <assert.h>
+#include <atomic.h>
+#include <errno.h>
+#include <pthreadP.h>
+#include <sched.h>
+#include <stdlib.h>
+
+
+int __sched_fifo_min_prio = -1;
+int __sched_fifo_max_prio = -1;
+
+void
+__init_sched_fifo_prio (void)
+{
+  __sched_fifo_max_prio = sched_get_priority_max (SCHED_FIFO);
+  atomic_write_barrier ();
+  __sched_fifo_min_prio = sched_get_priority_min (SCHED_FIFO);
+}
+
+int
+__pthread_tpp_change_priority (int previous_prio, int new_prio)
+{
+  struct pthread *self = THREAD_SELF;
+  struct priority_protection_data *tpp = THREAD_GETMEM (self, tpp);
+
+  if (tpp == NULL)
+    {
+      if (__sched_fifo_min_prio == -1)
+       __init_sched_fifo_prio ();
+
+      size_t size = sizeof *tpp;
+      size += (__sched_fifo_max_prio - __sched_fifo_min_prio + 1)
+             * sizeof (tpp->priomap[0]);
+      tpp = calloc (size, 1);
+      if (tpp == NULL)
+       return ENOMEM;
+      tpp->priomax = __sched_fifo_min_prio - 1;
+      THREAD_SETMEM (self, tpp, tpp);
+    }
+
+  assert (new_prio == -1
+         || (new_prio >= __sched_fifo_min_prio
+             && new_prio <= __sched_fifo_max_prio));
+  assert (previous_prio == -1
+         || (previous_prio >= __sched_fifo_min_prio
+             && previous_prio <= __sched_fifo_max_prio));
+
+  int priomax = tpp->priomax;
+  int newpriomax = priomax;
+  if (new_prio != -1)
+    {
+      if (tpp->priomap[new_prio - __sched_fifo_min_prio] + 1 == 0)
+       return EAGAIN;
+      ++tpp->priomap[new_prio - __sched_fifo_min_prio];
+      if (new_prio > priomax)
+       newpriomax = new_prio;
+    }
+
+  if (previous_prio != -1)
+    {
+      if (--tpp->priomap[previous_prio - __sched_fifo_min_prio] == 0
+         && priomax == previous_prio
+         && previous_prio > new_prio)
+       {
+         int i;
+         for (i = previous_prio - 1; i >= __sched_fifo_min_prio; --i)
+           if (tpp->priomap[i - __sched_fifo_min_prio])
+             break;
+         newpriomax = i;
+       }
+    }
+
+  if (priomax == newpriomax)
+    return 0;
+
+  lll_lock (self->lock);
+
+  tpp->priomax = newpriomax;
+
+  int result = 0;
+
+  if ((self->flags & ATTR_FLAG_SCHED_SET) == 0)
+    {
+      if (__sched_getparam (self->tid, &self->schedparam) != 0)
+       result = errno;
+      else
+       self->flags |= ATTR_FLAG_SCHED_SET;
+    }
+
+  if ((self->flags & ATTR_FLAG_POLICY_SET) == 0)
+    {
+      self->schedpolicy = __sched_getscheduler (self->tid);
+      if (self->schedpolicy == -1)
+       result = errno;
+      else
+       self->flags |= ATTR_FLAG_POLICY_SET;
+    }
+
+  if (result == 0)
+    {
+      struct sched_param sp = self->schedparam;
+      if (sp.sched_priority < newpriomax || sp.sched_priority < priomax)
+       {
+         if (sp.sched_priority < newpriomax)
+           sp.sched_priority = newpriomax;
+
+         if (__sched_setscheduler (self->tid, self->schedpolicy, &sp) < 0)
+           result = errno;
+       }
+    }
+
+  lll_unlock (self->lock);
+
+  return result;
+}
+
+int
+__pthread_current_priority (void)
+{
+  struct pthread *self = THREAD_SELF;
+  if ((self->flags & (ATTR_FLAG_POLICY_SET | ATTR_FLAG_SCHED_SET))
+      == (ATTR_FLAG_POLICY_SET | ATTR_FLAG_SCHED_SET))
+    return self->schedparam.sched_priority;
+
+  int result = 0;
+
+  lll_lock (self->lock);
+
+  if ((self->flags & ATTR_FLAG_SCHED_SET) == 0)
+    {
+      if (__sched_getparam (self->tid, &self->schedparam) != 0)
+       result = -1;
+      else
+       self->flags |= ATTR_FLAG_SCHED_SET;
+    }
+
+  if ((self->flags & ATTR_FLAG_POLICY_SET) == 0)
+    {
+      self->schedpolicy = __sched_getscheduler (self->tid);
+      if (self->schedpolicy == -1)
+       result = -1;
+      else
+       self->flags |= ATTR_FLAG_POLICY_SET;
+    }
+
+  if (result != -1)
+    result = self->schedparam.sched_priority;
+
+  lll_unlock (self->lock);
+
+  return result;
+}
index 589fac6b5f66087cbaf75bb43d955fff8811c189..db005f5b71ebbb2c026ddbd644a40a5891ee9b2b 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2003 Free Software Foundation, Inc.
+/* Copyright (C) 2003, 2006 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 2003.
 
 #include <pthread.h>
 #include <stdio.h>
 #include <stdlib.h>
+#include <time.h>
+#include <unistd.h>
+#include <sys/syscall.h>
+
+
+#define wait_code()                                                          \
+  do {                                                                       \
+    struct timespec ts = { .tv_sec = 0, .tv_nsec = 200000000 };                      \
+    while (syscall (__NR_nanosleep, &ts, &ts) < 0)                           \
+      /* nothing */;                                                         \
+  } while (0)
+
+
+#ifdef WAIT_IN_CHILD
+static pthread_barrier_t b;
+#endif
 
 
 static void *
 tf1 (void *arg)
 {
-  pthread_join ((pthread_t) arg, NULL);
+#ifdef WAIT_IN_CHILD
+  int e = pthread_barrier_wait (&b);
+  if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      printf ("%s: barrier_wait failed\n", __func__);
+      exit (1);
+    }
 
-  puts ("1st join returned");
+  wait_code ();
+#endif
 
-  return (void *) 1l;
+  pthread_join ((pthread_t) arg, NULL);
+
+  exit (42);
 }
 
 
 static void *
 tf2 (void *arg)
 {
-  pthread_join ((pthread_t) arg, NULL);
+#ifdef WAIT_IN_CHILD
+  int e = pthread_barrier_wait (&b);
+  if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      printf ("%s: barrier_wait failed\n", __func__);
+      exit (1);
+    }
 
-  puts ("2nd join returned");
+  wait_code ();
+#endif
+  pthread_join ((pthread_t) arg, NULL);
 
-  return (void *) 1l;
+  exit (43);
 }
 
 
 static int
 do_test (void)
 {
+#ifdef WAIT_IN_CHILD
+  if (pthread_barrier_init (&b, NULL, 2) != 0)
+    {
+      puts ("barrier_init failed");
+      return 1;
+    }
+#endif
+
   pthread_t th;
 
   int err = pthread_join (pthread_self (), NULL);
   if (err == 0)
     {
       puts ("1st circular join succeeded");
-      exit (1);
+      return 1;
     }
   if (err != EDEADLK)
     {
       printf ("1st circular join %d, not EDEADLK\n", err);
-      exit (1);
+      return 1;
     }
 
   if (pthread_create (&th, NULL, tf1, (void *) pthread_self ()) != 0)
     {
       puts ("1st create failed");
-      exit (1);
+      return 1;
     }
 
+#ifndef WAIT_IN_CHILD
+  wait_code ();
+#endif
+
   if (pthread_cancel (th) != 0)
     {
       puts ("cannot cancel 1st thread");
-      exit (1);
+      return 1;
+    }
+
+#ifdef WAIT_IN_CHILD
+  int e = pthread_barrier_wait (&b);
+  if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      printf ("%s: barrier_wait failed\n", __func__);
+      return 1;
     }
+#endif
 
   void *r;
   err = pthread_join (th, &r);
   if (err != 0)
     {
       printf ("cannot join 1st thread: %d\n", err);
-      exit (1);
+      return 1;
     }
   if (r != PTHREAD_CANCELED)
     {
       puts ("1st thread not canceled");
-      exit (1);
+      return 1;
     }
 
   err = pthread_join (pthread_self (), NULL);
   if (err == 0)
     {
       puts ("2nd circular join succeeded");
-      exit (1);
+      return 1;
     }
   if (err != EDEADLK)
     {
       printf ("2nd circular join %d, not EDEADLK\n", err);
-      exit (1);
+      return 1;
     }
 
   if (pthread_create (&th, NULL, tf2, (void *) pthread_self ()) != 0)
     {
       puts ("2nd create failed");
-      exit (1);
+      return 1;
     }
 
+#ifndef WAIT_IN_CHILD
+  wait_code ();
+#endif
+
   if (pthread_cancel (th) != 0)
     {
       puts ("cannot cancel 2nd thread");
-      exit (1);
+      return 1;
     }
 
+#ifdef WAIT_IN_CHILD
+  e = pthread_barrier_wait (&b);
+  if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      printf ("%s: barrier_wait failed\n", __func__);
+      return 1;
+    }
+#endif
+
   if (pthread_join (th, &r) != 0)
     {
       puts ("cannot join 2nd thread");
-      exit (1);
+      return 1;
     }
   if (r != PTHREAD_CANCELED)
     {
       puts ("2nd thread not canceled");
-      exit (1);
+      return 1;
     }
 
   err = pthread_join (pthread_self (), NULL);
   if (err == 0)
     {
-      puts ("2nd circular join succeeded");
-      exit (1);
+      puts ("3rd circular join succeeded");
+      return 1;
     }
   if (err != EDEADLK)
     {
-      printf ("2nd circular join %d, not EDEADLK\n", err);
-      exit (1);
+      printf ("3rd circular join %d, not EDEADLK\n", err);
+      return 1;
     }
 
-  exit (0);
+  return 0;
 }
 
 #define TEST_FUNCTION do_test ()
diff --git a/nptl/tst-join6.c b/nptl/tst-join6.c
new file mode 100644 (file)
index 0000000..0c9e7c0
--- /dev/null
@@ -0,0 +1,2 @@
+#define WAIT_IN_CHILD 1
+#include "tst-join5.c"
index c3ef5b2b510367809a97522c254479c142b249bb..9453f04918512b280ce268389715c2cdc7611252 100644 (file)
@@ -71,5 +71,7 @@ do_test (void)
   return 0;
 }
 
-#define TEST_FUNCTION do_test ()
+#ifndef TEST_FUNCTION
+# define TEST_FUNCTION do_test ()
+#endif
 #include "../test-skeleton.c"
index e5698c3eb0d6dc32a10fb3a75e982c0f8bea8149..de64bdb43566819fa46d42d3cc6dc581c928edac 100644 (file)
@@ -69,5 +69,7 @@ do_test (void)
 }
 
 #define EXPECTED_SIGNAL SIGALRM
-#define TEST_FUNCTION do_test ()
+#ifndef TEST_FUNCTION
+# define TEST_FUNCTION do_test ()
+#endif
 #include "../test-skeleton.c"
diff --git a/nptl/tst-mutexpp1.c b/nptl/tst-mutexpp1.c
new file mode 100644 (file)
index 0000000..9b7d7fe
--- /dev/null
@@ -0,0 +1,45 @@
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "tst-tpp.h"
+
+static pthread_mutexattr_t a;
+
+static void
+prepare (void)
+{
+  init_tpp_test ();
+
+  if (pthread_mutexattr_init (&a) != 0)
+    {
+      puts ("mutexattr_init failed");
+      exit (1);
+    }
+
+  if (pthread_mutexattr_setprotocol (&a, PTHREAD_PRIO_PROTECT) != 0)
+    {
+      puts ("mutexattr_setprotocol failed");
+      exit (1);
+    }
+
+  if (pthread_mutexattr_setprioceiling (&a, 6) != 0)
+    {
+      puts ("mutexattr_setprioceiling failed");
+      exit (1);
+    }
+}
+#define PREPARE(argc, argv) prepare ()
+
+static int do_test (void);
+
+static int
+do_test_wrapper (void)
+{
+  init_tpp_test ();
+  return do_test ();
+}
+#define TEST_FUNCTION do_test_wrapper ()
+
+#define ATTR &a
+#include "tst-mutex1.c"
diff --git a/nptl/tst-mutexpp10.c b/nptl/tst-mutexpp10.c
new file mode 100644 (file)
index 0000000..78281a4
--- /dev/null
@@ -0,0 +1,334 @@
+/* Copyright (C) 2006 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Jakub Jelinek <jakub@redhat.com>, 2006.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <errno.h>
+#include <limits.h>
+#include <pthread.h>
+#include <sched.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "tst-tpp.h"
+
+static int
+do_test (void)
+{
+  int ret = 0;
+
+  init_tpp_test ();
+
+  pthread_mutexattr_t ma;
+  if (pthread_mutexattr_init (&ma))
+    {
+      puts ("mutexattr_init failed");
+      return 1;
+    }
+  if (pthread_mutexattr_setprotocol (&ma, PTHREAD_PRIO_PROTECT))
+    {
+      puts ("mutexattr_setprotocol failed");
+      return 1;
+    }
+
+  int prioceiling;
+  if (pthread_mutexattr_getprioceiling (&ma, &prioceiling))
+    {
+      puts ("mutexattr_getprioceiling failed");
+      return 1;
+    }
+
+  if (prioceiling < fifo_min || prioceiling > fifo_max)
+    {
+      printf ("prioceiling %d not in %d..%d range\n",
+             prioceiling, fifo_min, fifo_max);
+      return 1;
+    }
+
+  if (fifo_max < INT_MAX
+      && pthread_mutexattr_setprioceiling (&ma, fifo_max + 1) != EINVAL)
+    {
+      printf ("mutexattr_setprioceiling %d did not fail with EINVAL\n",
+             fifo_max + 1);
+      return 1;
+    }
+  
+  if (fifo_min > 0
+      && pthread_mutexattr_setprioceiling (&ma, fifo_min - 1) != EINVAL)
+    {
+      printf ("mutexattr_setprioceiling %d did not fail with EINVAL\n",
+             fifo_min - 1);
+      return 1;
+    }
+
+  if (pthread_mutexattr_setprioceiling (&ma, fifo_min))
+    {
+      puts ("mutexattr_setprioceiling failed");
+      return 1;
+    }
+
+  if (pthread_mutexattr_setprioceiling (&ma, fifo_max))
+    {
+      puts ("mutexattr_setprioceiling failed");
+      return 1;
+    }
+
+  if (pthread_mutexattr_setprioceiling (&ma, 6))
+    {
+      puts ("mutexattr_setprioceiling failed");
+      return 1;
+    }
+
+  if (pthread_mutexattr_getprioceiling (&ma, &prioceiling))
+    {
+      puts ("mutexattr_getprioceiling failed");
+      return 1;
+    }
+
+  if (prioceiling != 6)
+    {
+      printf ("mutexattr_getprioceiling returned %d != 6\n",
+             prioceiling);
+      return 1;
+    }
+
+  pthread_mutex_t m1, m2, m3;
+  int e = pthread_mutex_init (&m1, &ma);
+  if (e == ENOTSUP)
+    {
+      puts ("cannot support selected type of mutexes");
+      return 0;
+    }
+  else if (e != 0)
+    {
+      puts ("mutex_init failed");
+      return 1;
+    }
+
+  if (pthread_mutexattr_setprioceiling (&ma, 8))
+    {
+      puts ("mutexattr_setprioceiling failed");
+      return 1;
+    }
+
+  if (pthread_mutex_init (&m2, &ma))
+    {
+      puts ("mutex_init failed");
+      return 1;
+    }
+
+  if (pthread_mutexattr_setprioceiling (&ma, 5))
+    {
+      puts ("mutexattr_setprioceiling failed");
+      return 1;
+    }
+
+  if (pthread_mutex_init (&m3, &ma))
+    {
+      puts ("mutex_init failed");
+      return 1;
+    }
+
+  CHECK_TPP_PRIORITY (4, 4);
+
+  if (pthread_mutex_lock (&m1) != 0)
+    {
+      puts ("mutex_lock failed");
+      return 1;
+    }
+
+  CHECK_TPP_PRIORITY (4, 6);
+
+  if (pthread_mutex_trylock (&m2) != 0)
+    {
+      puts ("mutex_lock failed");
+      return 1;
+    }
+
+  CHECK_TPP_PRIORITY (4, 8);
+
+  if (pthread_mutex_lock (&m3) != 0)
+    {
+      puts ("mutex_lock failed");
+      return 1;
+    }
+
+  CHECK_TPP_PRIORITY (4, 8);
+
+  if (pthread_mutex_unlock (&m2) != 0)
+    {
+      puts ("mutex_unlock failed");
+      return 1;
+    }
+
+  CHECK_TPP_PRIORITY (4, 6);
+
+  if (pthread_mutex_unlock (&m1) != 0)
+    {
+      puts ("mutex_unlock failed");
+      return 1;
+    }
+
+  CHECK_TPP_PRIORITY (4, 5);
+
+  if (pthread_mutex_lock (&m2) != 0)
+    {
+      puts ("mutex_lock failed");
+      return 1;
+    }
+
+  CHECK_TPP_PRIORITY (4, 8);
+
+  if (pthread_mutex_unlock (&m2) != 0)
+    {
+      puts ("mutex_unlock failed");
+      return 1;
+    }
+
+  CHECK_TPP_PRIORITY (4, 5);
+
+  if (pthread_mutex_getprioceiling (&m1, &prioceiling))
+    {
+      puts ("mutex_getprioceiling m1 failed");
+      return 1;
+    }
+  else if (prioceiling != 6)
+    {
+      printf ("unexpected m1 prioceiling %d != 6\n", prioceiling);
+      return 1;
+    }
+
+  if (pthread_mutex_getprioceiling (&m2, &prioceiling))
+    {
+      puts ("mutex_getprioceiling m2 failed");
+      return 1;
+    }
+  else if (prioceiling != 8)
+    {
+      printf ("unexpected m2 prioceiling %d != 8\n", prioceiling);
+      return 1;
+    }
+
+  if (pthread_mutex_getprioceiling (&m3, &prioceiling))
+    {
+      puts ("mutex_getprioceiling m3 failed");
+      return 1;
+    }
+  else if (prioceiling != 5)
+    {
+      printf ("unexpected m3 prioceiling %d != 5\n", prioceiling);
+      return 1;
+    }
+
+  if (pthread_mutex_setprioceiling (&m1, 7, &prioceiling))
+    {
+      printf ("mutex_setprioceiling failed");
+      return 1;
+    }
+  else if (prioceiling != 6)
+    {
+      printf ("unexpected m1 old prioceiling %d != 6\n", prioceiling);
+      return 1;
+    }
+    
+  if (pthread_mutex_getprioceiling (&m1, &prioceiling))
+    {
+      puts ("mutex_getprioceiling m1 failed");
+      return 1;
+    }
+  else if (prioceiling != 7)
+    {
+      printf ("unexpected m1 prioceiling %d != 7\n", prioceiling);
+      return 1;
+    }
+
+  CHECK_TPP_PRIORITY (4, 5);
+
+  if (pthread_mutex_unlock (&m3) != 0)
+    {
+      puts ("mutex_unlock failed");
+      return 1;
+    }
+
+  CHECK_TPP_PRIORITY (4, 4);
+
+  if (pthread_mutex_trylock (&m1) != 0)
+    {
+      puts ("mutex_lock failed");
+      return 1;
+    }
+
+  CHECK_TPP_PRIORITY (4, 7);
+
+  struct sched_param sp;
+  memset (&sp, 0, sizeof (sp));
+  sp.sched_priority = 8;
+  if (pthread_setschedparam (pthread_self (), SCHED_FIFO, &sp))
+    {
+      puts ("cannot set scheduling params");
+      return 1;
+    }
+
+  CHECK_TPP_PRIORITY (8, 8);
+
+  if (pthread_mutex_unlock (&m1) != 0)
+    {
+      puts ("mutex_unlock failed");
+      return 1;
+    }
+
+  CHECK_TPP_PRIORITY (8, 8);
+
+  if (pthread_mutex_lock (&m3) != EINVAL)
+    {
+      puts ("pthread_mutex_lock didn't fail with EINVAL");
+      return 1;
+    }
+
+  CHECK_TPP_PRIORITY (8, 8);
+
+  if (pthread_mutex_destroy (&m1) != 0)
+    {
+      puts ("mutex_destroy failed");
+      return 1;
+    }
+
+  if (pthread_mutex_destroy (&m2) != 0)
+    {
+      puts ("mutex_destroy failed");
+      return 1;
+    }
+
+  if (pthread_mutex_destroy (&m3) != 0)
+    {
+      puts ("mutex_destroy failed");
+      return 1;
+    }
+
+  if (pthread_mutexattr_destroy (&ma) != 0)
+    {
+      puts ("mutexattr_destroy failed");
+      return 1;
+    }
+
+  return ret;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/nptl/tst-mutexpp6.c b/nptl/tst-mutexpp6.c
new file mode 100644 (file)
index 0000000..2ddf6b4
--- /dev/null
@@ -0,0 +1,45 @@
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "tst-tpp.h"
+
+static pthread_mutexattr_t a;
+
+static void
+prepare (void)
+{
+  init_tpp_test ();
+
+  if (pthread_mutexattr_init (&a) != 0)
+    {
+      puts ("mutexattr_init failed");
+      exit (1);
+    }
+
+  if (pthread_mutexattr_setprotocol (&a, PTHREAD_PRIO_PROTECT) != 0)
+    {
+      puts ("mutexattr_setprotocol failed");
+      exit (1);
+    }
+
+  if (pthread_mutexattr_setprioceiling (&a, 6) != 0)
+    {
+      puts ("mutexattr_setprioceiling failed");
+      exit (1);
+    }
+}
+#define PREPARE(argc, argv) prepare ()
+
+static int do_test (void);
+
+static int
+do_test_wrapper (void)
+{
+  init_tpp_test ();
+  return do_test ();
+}
+#define TEST_FUNCTION do_test_wrapper ()
+
+#define ATTR &a
+#include "tst-mutex6.c"
diff --git a/nptl/tst-tpp.h b/nptl/tst-tpp.h
new file mode 100644 (file)
index 0000000..c5844b2
--- /dev/null
@@ -0,0 +1,94 @@
+/* Copyright (C) 2006 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Jakub Jelinek <jakub@redhat.com>, 2006.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <errno.h>
+#include <pthread.h>
+#include <sched.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/syscall.h>
+
+/* This test is Linux specific.  */
+#define CHECK_TPP_PRIORITY(normal, boosted) \
+  do                                                           \
+    {                                                          \
+      pid_t tid = syscall (__NR_gettid);                       \
+                                                               \
+      struct sched_param cep_sp;                               \
+      int cep_policy;                                          \
+      if (pthread_getschedparam (pthread_self (), &cep_policy, \
+                                &cep_sp) != 0)                 \
+       {                                                       \
+         puts ("getschedparam failed");                        \
+         ret = 1;                                              \
+       }                                                       \
+      else if (cep_sp.sched_priority != (normal))              \
+       {                                                       \
+         printf ("unexpected priority %d != %d\n",             \
+                 cep_sp.sched_priority, (normal));             \
+       }                                                       \
+      if (syscall (__NR_sched_getparam, tid, &cep_sp) == 0     \
+         && cep_sp.sched_priority != (boosted))                \
+       {                                                       \
+         printf ("unexpected boosted priority %d != %d\n",     \
+                 cep_sp.sched_priority, (boosted));            \
+         ret = 1;                                              \
+       }                                                       \
+    }                                                          \
+  while (0)
+
+int fifo_min, fifo_max;
+
+void
+init_tpp_test (void)
+{
+  fifo_min = sched_get_priority_min (SCHED_FIFO);
+  if (fifo_min < 0)
+    {
+      printf ("couldn't get min priority for SCHED_FIFO: %m\n");
+      exit (1);
+    }
+
+  fifo_max = sched_get_priority_max (SCHED_FIFO);
+  if (fifo_max < 0)
+    {
+      printf ("couldn't get max priority for SCHED_FIFO: %m\n");
+      exit (1);
+    }
+
+  if (fifo_min > 4 || fifo_max < 10)
+    {
+      printf ("%d..%d SCHED_FIFO priority interval not suitable for this test\n",
+             fifo_min, fifo_max);
+      exit (0);
+    }
+
+  struct sched_param sp;
+  memset (&sp, 0, sizeof (sp));
+  sp.sched_priority = 4;
+  int e = pthread_setschedparam (pthread_self (), SCHED_FIFO, &sp);
+  if (e != 0)
+    {
+      errno = e;
+      printf ("cannot set scheduling params: %m\n");
+      exit (0);
+    }
+}
index c86003040973a27c7c6a283620d4e6bf1984caa1..2c729ad2f145079c2714346ff2c9a85b986cb451 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
+/* Copyright (C) 1997,1998,1999,2000,2001,2006 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -297,8 +297,8 @@ typedef unsigned long long int      uintmax_t;
 # endif
 
 /* Unsigned.  */
-# define UINT8_C(c)    c ## U
-# define UINT16_C(c)   c ## U
+# define UINT8_C(c)    c
+# define UINT16_C(c)   c
 # define UINT32_C(c)   c ## U
 # if __WORDSIZE == 64
 #  define UINT64_C(c)  c ## UL
index 392c109d4c7d9fd2213b4027c2b14abe12ddf9b4..6a158c3fffcfaeb3f3092bb36c1a19bf0ca1361e 100644 (file)
@@ -40,8 +40,9 @@ _dl_runtime_resolve:
        mflr r0
  # We also need to save some of the condition register fields
        stw r7,32(r1)
-       stw r0,68(r1)
-       cfi_offset (lr, 4)
+ # Don't clobber the caller's LRSAVE, it is needed by _mcount.
+       stw r0,48(r1)
+       cfi_offset (lr, -16)
        stw r8,36(r1)
        mfcr r0
        stw r9,40(r1)
@@ -51,7 +52,7 @@ _dl_runtime_resolve:
  # 'fixup' returns the address we want to branch to.
        mtctr r3
  # Put the registers back...
-       lwz r0,68(r1)
+       lwz r0,48(r1)
        lwz r10,44(r1)
        lwz r9,40(r1)
        mtlr r0
@@ -128,8 +129,9 @@ _dl_prof_resolve:
        mflr r5
  # We also need to save some of the condition register fields.
        stw r7,32(r1)
-       stw r5,324(r1)
-       cfi_offset (lr, 4)
+ # Don't clobber the caller's LRSAVE, it is needed by _mcount.
+       stw r5,308(r1)
+       cfi_offset (lr, -12)
        stw r8,36(r1)
        mfcr r0
        stw r9,40(r1)
@@ -154,7 +156,7 @@ _dl_prof_resolve:
  # 'fixup' returns the address we want to branch to.
        mtctr r3
  # Put the registers back...
-       lwz r0,324(r1)
+       lwz r0,308(r1)
        lwz r10,44(r1)
        lwz r9,40(r1)
        mtlr r0
index 0194999b36f9e52edc0854feabbffdda5d78834a..a93be6349b6399e107b8263376d252ed55ce28ba 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 1999,2000,2001,2002,2003,2004 Free Software Foundation, Inc.
+/* Copyright (C) 1999-2004, 2006 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -36,6 +36,43 @@ extern void __pthread_clock_settime (clockid_t clock_id, hp_timing_t offset)
 #endif
 
 
+#if HP_TIMING_AVAIL
+static int
+hp_timing_settime (clockid_t clock_id, const struct timespec *tp)
+{
+  hp_timing_t tsc;
+  hp_timing_t usertime;
+
+  /* First thing is to get the current time.  */
+  HP_TIMING_NOW (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;
+    }
+
+  /* Convert the user-provided time into CPU ticks.  */
+  usertime = tp->tv_sec * freq + (tp->tv_nsec * freq) / 1000000000ull;
+
+  /* Determine the offset and use it as the new base value.  */
+  if (clock_id == CLOCK_PROCESS_CPUTIME_ID
+      || __pthread_clock_settime == NULL)
+    GL(dl_cpuclock_offset) = tsc - usertime;
+  else
+    __pthread_clock_settime (clock_id, tsc - usertime);
+
+  return 0;
+}
+#endif
+
+
 /* Set CLOCK to value TP.  */
 int
 clock_settime (clockid_t clock_id, const struct timespec *tp)
@@ -70,55 +107,22 @@ clock_settime (clockid_t clock_id, const struct timespec *tp)
 #endif
 
     default:
-#if HP_TIMING_AVAIL
-      if ((clock_id & ((1 << CLOCK_IDFIELD_SIZE) - 1))
-         != CLOCK_THREAD_CPUTIME_ID)
+#ifdef SYSDEP_SETTIME_CPU
+      SYSDEP_SETTIME_CPU;
 #endif
+#ifndef HANDLED_CPUTIME
+# if HP_TIMING_AVAIL
+      if (CPUCLOCK_WHICH (clock_id) == CLOCK_PROCESS_CPUTIME_ID
+         || CPUCLOCK_WHICH (clock_id) == CLOCK_THREAD_CPUTIME_ID)
+       retval = hp_timing_settime (clock_id, tp);
+      else
+# endif
        {
          __set_errno (EINVAL);
          retval = -1;
-         break;
        }
-
-#if HP_TIMING_AVAIL
-      /* FALLTHROUGH.  */
-    case CLOCK_PROCESS_CPUTIME_ID:
-      {
-       hp_timing_t tsc;
-       hp_timing_t usertime;
-
-       /* First thing is to get the current time.  */
-       HP_TIMING_NOW (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.  */
-               retval = -1;
-               break;
-             }
-         }
-
-       /* Convert the user-provided time into CPU ticks.  */
-       usertime = tp->tv_sec * freq + (tp->tv_nsec * freq) / 1000000000ull;
-
-       /* Determine the offset and use it as the new base value.  */
-       if (clock_id == CLOCK_PROCESS_CPUTIME_ID
-           || __pthread_clock_settime == NULL)
-         GL(dl_cpuclock_offset) = tsc - usertime;
-       else
-         __pthread_clock_settime (clock_id, tsc - usertime);
-
-       retval = 0;
-      }
-      break;
 #endif
+      break;
     }
 
   return retval;
index 1dd57fa5c0e642fc56a41f71764268f5d10faa73..6e75b0327b8a5bcce5a37c19a3b3a94cc79674aa 100644 (file)
@@ -1,4 +1,5 @@
-/* Copyright (C) 1992, 1996, 1997, 2001, 2002 Free Software Foundation, Inc.
+/* Copyright (C) 1992, 1996, 1997, 2001, 2002, 2006
+   Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -47,9 +48,11 @@ nice (int incr)
   else if (prio >= PRIO_MAX)
     prio = PRIO_MAX - 1;
   result = setpriority (PRIO_PROCESS, 0, prio);
-  if (result != -1)
-    return getpriority (PRIO_PROCESS, 0);
-  else
-    return -1;
-
+  if (result == -1)
+    {
+      if (errno == EACCES)
+       errno = EPERM;
+      return -1;
+    }
+  return getpriority (PRIO_PROCESS, 0);
 }
index 31ba0225fbc45b1d8b81d87ca02322bb681173b7..731b7be7b83f08f316afa406a7aa330d8adafe73 100644 (file)
    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
    02111-1307 USA.  */
 
+#include <errno.h>
 #include <sysdep.h>
 
+#include "kernel-posix-cpu-timers.h"
 #include <kernel-features.h>
 
+#ifndef HAVE_CLOCK_GETTIME_VSYSCALL
+# undef INTERNAL_VSYSCALL
+# define INTERNAL_VSYSCALL INTERNAL_SYSCALL
+# undef INLINE_VSYSCALL
+# define INLINE_VSYSCALL INLINE_SYSCALL
+#else
+# include <bits/libc-vdso.h>
+#endif
+
+#if __ASSUME_POSIX_CPU_TIMERS <= 0 && defined __NR_clock_settime
+extern int __libc_missing_posix_timers attribute_hidden;
+extern int __libc_missing_posix_cpu_timers attribute_hidden;
+
+static int
+maybe_syscall_settime_cpu (clockid_t clock_id, const struct timespec *tp)
+{
+  int e = EINVAL;
+
+  if (!__libc_missing_posix_cpu_timers)
+    {
+      INTERNAL_SYSCALL_DECL (err);
+      int r = INTERNAL_VSYSCALL (clock_settime, 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_VSYSCALL (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;
+}
+#endif
+
 
 #ifdef __ASSUME_POSIX_TIMERS
 /* This means the REALTIME clock is definitely supported in the
@@ -73,4 +128,22 @@ extern int __libc_missing_posix_timers attribute_hidden;
 # define HANDLED_REALTIME      1
 #endif
 
+#if __ASSUME_POSIX_CPU_TIMERS > 0
+# define HANDLED_CPUTIME 1
+# define SYSDEP_SETTIME_CPU \
+  retval = INLINE_SYSCALL (clock_settime, 2, clock_id, tp)
+#elif defined __NR_clock_settime
+# define SYSDEP_SETTIME_CPU \
+  retval = maybe_syscall_settime_cpu (clock_id, tp);                         \
+  if (retval == 0)                                                           \
+    break;                                                                   \
+  if (retval != EINVAL || !__libc_missing_posix_cpu_timers)                  \
+    {                                                                        \
+      __set_errno (retval);                                                  \
+      retval = -1;                                                           \
+      break;                                                                 \
+    }                                                                        \
+  do { } while (0)
+#endif
+
 #include <sysdeps/unix/clock_settime.c>
index 40fab28d47f80db51fdbd76300144debc48cebd9..2ec5bd39adf7c63b7aa1a8d87ad95889b40e223e 100644 (file)
@@ -1,47 +1 @@
-/* pause -- suspend the process until a signal arrives.  POSIX.1 version.
-   Copyright (C) 2003 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   The GNU C Library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, write to the Free
-   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
-   02111-1307 USA.  */
-
-#include <errno.h>
-#include <signal.h>
-#include <unistd.h>
-#include <sysdep-cancel.h>
-
-#include <sysdep.h>
-#include <sys/syscall.h>
-#include <bp-checks.h>
-
-/* Suspend the process until a signal arrives.
-   This always returns -1 and sets errno to EINTR.  */
-int
-__libc_pause (void)
-{
-  sigset_t set;
-
-  __sigemptyset (&set);
-  INLINE_SYSCALL (rt_sigprocmask, 4, SIG_BLOCK, CHECK_SIGSET (NULL),
-                 CHECK_SIGSET_NULL_OK (&set), _NSIG / 8);
-
-  /* pause is a cancellation point, but so is sigsuspend.
-     So no need for anything special here.  */
-
-  return __sigsuspend (&set);
-}
-weak_alias (__libc_pause, pause)
-
-LIBC_CANCEL_HANDLED ();                /* sigsuspend handles our cancellation.  */
+#include <sysdeps/posix/pause.c>