summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2006-08-15 05:53:50 +0000
committerJakub Jelinek <jakub@redhat.com>2006-08-15 05:53:50 +0000
commit3a2ba84afba2d9b315c65aa46ba036fd22ef4fb0 (patch)
tree47a553a26365a6738426804af7609434daf047b8
parent256926546643ba909661c83e7a7d24d733b9b390 (diff)
Updated to fedora-glibc-20060815T0533
-rw-r--r--ChangeLog79
-rw-r--r--NEWS4
-rw-r--r--fedora/branch.mk4
-rw-r--r--libio/Makefile3
-rw-r--r--libio/bug-memstream1.c133
-rw-r--r--libio/bug-wmemstream1.c135
-rw-r--r--libio/memstream.c2
-rw-r--r--libio/strops.c125
-rw-r--r--libio/vasprintf.c2
-rw-r--r--libio/wmemstream.c2
-rw-r--r--libio/wstrops.c138
-rw-r--r--locale/programs/ld-ctype.c23
-rw-r--r--locale/programs/ld-time.c10
-rw-r--r--localedata/ChangeLog16
-rw-r--r--localedata/SUPPORTED1
-rw-r--r--localedata/locales/fy_NL139
-rw-r--r--localedata/locales/or_IN2
-rw-r--r--localedata/locales/pa_IN2
-rw-r--r--login/utmpname.c5
-rwxr-xr-xmath/gen-libm-test.pl8
-rw-r--r--misc/error.c16
-rw-r--r--nptl/ChangeLog51
-rw-r--r--nptl/Makefile2
-rw-r--r--nptl/descr.h11
-rw-r--r--nptl/pthreadP.h32
-rw-r--r--nptl/pthread_create.c9
-rw-r--r--nptl/pthread_join.c78
-rw-r--r--nptl/pthread_mutex_getprioceiling.c7
-rw-r--r--nptl/pthread_mutex_init.c27
-rw-r--r--nptl/pthread_mutex_lock.c84
-rw-r--r--nptl/pthread_mutex_setprioceiling.c81
-rw-r--r--nptl/pthread_mutex_timedlock.c113
-rw-r--r--nptl/pthread_mutex_trylock.c73
-rw-r--r--nptl/pthread_mutex_unlock.c43
-rw-r--r--nptl/pthread_mutexattr_getprioceiling.c15
-rw-r--r--nptl/pthread_mutexattr_setprioceiling.c10
-rw-r--r--nptl/pthread_setschedparam.c17
-rw-r--r--nptl/pthread_setschedprio.c6
-rw-r--r--nptl/sysdeps/unix/sysv/linux/bits/posix_opt.h7
-rw-r--r--nptl/tpp.c172
-rw-r--r--nptl/tst-join5.c115
-rw-r--r--nptl/tst-join6.c2
-rw-r--r--nptl/tst-mutex1.c4
-rw-r--r--nptl/tst-mutex6.c4
-rw-r--r--nptl/tst-mutexpp1.c45
-rw-r--r--nptl/tst-mutexpp10.c334
-rw-r--r--nptl/tst-mutexpp6.c45
-rw-r--r--nptl/tst-tpp.h94
-rw-r--r--sysdeps/generic/stdint.h6
-rw-r--r--sysdeps/powerpc/powerpc32/dl-trampoline.S14
-rw-r--r--sysdeps/unix/clock_settime.c92
-rw-r--r--sysdeps/unix/nice.c15
-rw-r--r--sysdeps/unix/sysv/linux/clock_settime.c73
-rw-r--r--sysdeps/unix/sysv/linux/sparc/sparc64/pause.c48
54 files changed, 2257 insertions, 321 deletions
diff --git a/ChangeLog b/ChangeLog
index a356c15e3d..e54bd15b93 100644
--- 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 55855ad81a..14abed4782 100644
--- 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.
+
Version 2.4
diff --git a/fedora/branch.mk b/fedora/branch.mk
index 4a26c92c8e..2416955f13 100644
--- a/fedora/branch.mk
+++ b/fedora/branch.mk
@@ -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
diff --git a/libio/Makefile b/libio/Makefile
index e9c1d522fd..0529744e3d 100644
--- a/libio/Makefile
+++ b/libio/Makefile
@@ -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
index 0000000000..8af36fee2d
--- /dev/null
+++ b/libio/bug-memstream1.c
@@ -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
index 0000000000..2190593c93
--- /dev/null
+++ b/libio/bug-wmemstream1.c
@@ -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"
diff --git a/libio/memstream.c b/libio/memstream.c
index 742da740ef..877383f3a8 100644
--- a/libio/memstream.c
+++ b/libio/memstream.c
@@ -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);
diff --git a/libio/strops.c b/libio/strops.c
index 2de83403a2..05270ce407 100644
--- a/libio/strops.c
+++ b/libio/strops.c
@@ -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
@@ -25,43 +25,12 @@
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;
diff --git a/libio/vasprintf.c b/libio/vasprintf.c
index ac7733006d..2fdb9f6ed2 100644
--- a/libio/vasprintf.c
+++ b/libio/vasprintf.c
@@ -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;
diff --git a/libio/wmemstream.c b/libio/wmemstream.c
index 1709f2dd33..85ea64991a 100644
--- a/libio/wmemstream.c
+++ b/libio/wmemstream.c
@@ -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;
diff --git a/libio/wstrops.c b/libio/wstrops.c
index 32f7ef3cf7..8b862fb989 100644
--- a/libio/wstrops.c
+++ b/libio/wstrops.c
@@ -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
@@ -25,44 +25,13 @@
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);
diff --git a/locale/programs/ld-ctype.c b/locale/programs/ld-ctype.c
index b0b2e3f805..f38231f984 100644
--- a/locale/programs/ld-ctype.c
+++ b/locale/programs/ld-ctype.c
@@ -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++)
diff --git a/locale/programs/ld-time.c b/locale/programs/ld-time.c
index 4f1dcb0ce7..bf5151858a 100644
--- a/locale/programs/ld-time.c
+++ b/locale/programs/ld-time.c
@@ -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);
diff --git a/localedata/ChangeLog b/localedata/ChangeLog
index 76129512b6..80adc04066 100644
--- a/localedata/ChangeLog
+++ b/localedata/ChangeLog
@@ -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]
diff --git a/localedata/SUPPORTED b/localedata/SUPPORTED
index cd6d91710c..9de5b7ae15 100644
--- a/localedata/SUPPORTED
+++ b/localedata/SUPPORTED
@@ -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
index 0000000000..d247e50d0c
--- /dev/null
+++ b/localedata/locales/fy_NL
@@ -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
diff --git a/localedata/locales/or_IN b/localedata/locales/or_IN
index 6170d03823..03123026d5 100644
--- a/localedata/locales/or_IN
+++ b/localedata/locales/or_IN
@@ -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>";/
diff --git a/localedata/locales/pa_IN b/localedata/locales/pa_IN
index d432a169e5..e38308dfac 100644
--- a/localedata/locales/pa_IN
+++ b/localedata/locales/pa_IN
@@ -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)
diff --git a/login/utmpname.c b/login/utmpname.c
index 875dbd5973..24ed7f3c46 100644
--- a/login/utmpname.c
+++ b/login/utmpname.c
@@ -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;
}
diff --git a/math/gen-libm-test.pl b/math/gen-libm-test.pl
index a63f62a1cb..0b0b8ca19f 100755
--- a/math/gen-libm-test.pl
+++ b/math/gen-libm-test.pl
@@ -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;
}
diff --git a/misc/error.c b/misc/error.c
index 66a8ccb501..aca435d995 100644
--- a/misc/error.c
+++ b/misc/error.c
@@ -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);
diff --git a/nptl/ChangeLog b/nptl/ChangeLog
index 6450e42574..fe6e5c06c3 100644
--- a/nptl/ChangeLog
+++ b/nptl/ChangeLog
@@ -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]
diff --git a/nptl/Makefile b/nptl/Makefile
index 3a72d3707e..c0c09e52fe 100644
--- a/nptl/Makefile
+++ b/nptl/Makefile
@@ -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 \
diff --git a/nptl/descr.h b/nptl/descr.h
index 607aa9fcdb..7acd2f4f22 100644
--- a/nptl/descr.h
+++ b/nptl/descr.h
@@ -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;
diff --git a/nptl/pthreadP.h b/nptl/pthreadP.h
index dc98bb19c0..503e99b2b4 100644
--- a/nptl/pthreadP.h
+++ b/nptl/pthreadP.h
@@ -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;
diff --git a/nptl/pthread_create.c b/nptl/pthread_create.c
index c1ac199bb9..315722643b 100644
--- a/nptl/pthread_create.c
+++ b/nptl/pthread_create.c
@@ -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. */
diff --git a/nptl/pthread_join.c b/nptl/pthread_join.c
index 70dc81a023..c88d85b52f 100644
--- a/nptl/pthread_join.c
+++ b/nptl/pthread_join.c
@@ -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.
@@ -27,7 +27,11 @@
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;
}
diff --git a/nptl/pthread_mutex_getprioceiling.c b/nptl/pthread_mutex_getprioceiling.c
index 4d1bc28431..1ce5eaebef 100644
--- a/nptl/pthread_mutex_getprioceiling.c
+++ b/nptl/pthread_mutex_getprioceiling.c
@@ -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;
diff --git a/nptl/pthread_mutex_init.c b/nptl/pthread_mutex_init.c
index 6ceca86052..96f1fb00f8 100644
--- a/nptl/pthread_mutex_init.c
+++ b/nptl/pthread_mutex_init.c
@@ -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:
diff --git a/nptl/pthread_mutex_lock.c b/nptl/pthread_mutex_lock.c
index a19c907695..52cc47f4cc 100644
--- a/nptl/pthread_mutex_lock.c
+++ b/nptl/pthread_mutex_lock.c
@@ -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;
diff --git a/nptl/pthread_mutex_setprioceiling.c b/nptl/pthread_mutex_setprioceiling.c
index 3271f8833a..cd13d1c14c 100644
--- a/nptl/pthread_mutex_setprioceiling.c
+++ b/nptl/pthread_mutex_setprioceiling.c
@@ -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;
}
diff --git a/nptl/pthread_mutex_timedlock.c b/nptl/pthread_mutex_timedlock.c
index dcff4f81a8..c8e6b8507a 100644
--- a/nptl/pthread_mutex_timedlock.c
+++ b/nptl/pthread_mutex_timedlock.c
@@ -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;
diff --git a/nptl/pthread_mutex_trylock.c b/nptl/pthread_mutex_trylock.c
index f3a18569a1..94d519233b 100644
--- a/nptl/pthread_mutex_trylock.c
+++ b/nptl/pthread_mutex_trylock.c
@@ -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;
diff --git a/nptl/pthread_mutex_unlock.c b/nptl/pthread_mutex_unlock.c
index 2b5064fbac..33919d60af 100644
--- a/nptl/pthread_mutex_unlock.c
+++ b/nptl/pthread_mutex_unlock.c
@@ -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;
diff --git a/nptl/pthread_mutexattr_getprioceiling.c b/nptl/pthread_mutexattr_getprioceiling.c
index da1beabf46..792e9a43d6 100644
--- a/nptl/pthread_mutexattr_getprioceiling.c
+++ b/nptl/pthread_mutexattr_getprioceiling.c
@@ -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;
}
diff --git a/nptl/pthread_mutexattr_setprioceiling.c b/nptl/pthread_mutexattr_setprioceiling.c
index 6c15b46833..9b7874f739 100644
--- a/nptl/pthread_mutexattr_setprioceiling.c
+++ b/nptl/pthread_mutexattr_setprioceiling.c
@@ -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;
diff --git a/nptl/pthread_setschedparam.c b/nptl/pthread_setschedparam.c
index 5889cc98a9..30ac6b3e89 100644
--- a/nptl/pthread_setschedparam.c
+++ b/nptl/pthread_setschedparam.c
@@ -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;
}
diff --git a/nptl/pthread_setschedprio.c b/nptl/pthread_setschedprio.c
index 063f5232f5..4a71f6c7b3 100644
--- a/nptl/pthread_setschedprio.c
+++ b/nptl/pthread_setschedprio.c
@@ -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;
}
diff --git a/nptl/sysdeps/unix/sysv/linux/bits/posix_opt.h b/nptl/sysdeps/unix/sysv/linux/bits/posix_opt.h
index d8eced1f22..40160c54de 100644
--- a/nptl/sysdeps/unix/sysv/linux/bits/posix_opt.h
+++ b/nptl/sysdeps/unix/sysv/linux/bits/posix_opt.h
@@ -82,6 +82,10 @@
/* 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
@@ -174,7 +178,4 @@
/* 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
index 0000000000..367dd8162a
--- /dev/null
+++ b/nptl/tpp.c
@@ -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;
+}
diff --git a/nptl/tst-join5.c b/nptl/tst-join5.c
index 589fac6b5f..db005f5b71 100644
--- a/nptl/tst-join5.c
+++ b/nptl/tst-join5.c
@@ -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.
@@ -21,120 +21,187 @@
#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
index 0000000000..0c9e7c056b
--- /dev/null
+++ b/nptl/tst-join6.c
@@ -0,0 +1,2 @@
+#define WAIT_IN_CHILD 1
+#include "tst-join5.c"
diff --git a/nptl/tst-mutex1.c b/nptl/tst-mutex1.c
index c3ef5b2b51..9453f04918 100644
--- a/nptl/tst-mutex1.c
+++ b/nptl/tst-mutex1.c
@@ -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"
diff --git a/nptl/tst-mutex6.c b/nptl/tst-mutex6.c
index e5698c3eb0..de64bdb435 100644
--- a/nptl/tst-mutex6.c
+++ b/nptl/tst-mutex6.c
@@ -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
index 0000000000..9b7d7fe263
--- /dev/null
+++ b/nptl/tst-mutexpp1.c
@@ -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
index 0000000000..78281a4d3b
--- /dev/null
+++ b/nptl/tst-mutexpp10.c
@@ -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
index 0000000000..2ddf6b45c6
--- /dev/null
+++ b/nptl/tst-mutexpp6.c
@@ -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
index 0000000000..c5844b26dd
--- /dev/null
+++ b/nptl/tst-tpp.h
@@ -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);
+ }
+}
diff --git a/sysdeps/generic/stdint.h b/sysdeps/generic/stdint.h
index c860030409..2c729ad2f1 100644
--- a/sysdeps/generic/stdint.h
+++ b/sysdeps/generic/stdint.h
@@ -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
diff --git a/sysdeps/powerpc/powerpc32/dl-trampoline.S b/sysdeps/powerpc/powerpc32/dl-trampoline.S
index 392c109d4c..6a158c3fff 100644
--- a/sysdeps/powerpc/powerpc32/dl-trampoline.S
+++ b/sysdeps/powerpc/powerpc32/dl-trampoline.S
@@ -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
diff --git a/sysdeps/unix/clock_settime.c b/sysdeps/unix/clock_settime.c
index 0194999b36..a93be6349b 100644
--- a/sysdeps/unix/clock_settime.c
+++ b/sysdeps/unix/clock_settime.c
@@ -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;
diff --git a/sysdeps/unix/nice.c b/sysdeps/unix/nice.c
index 1dd57fa5c0..6e75b0327b 100644
--- a/sysdeps/unix/nice.c
+++ b/sysdeps/unix/nice.c
@@ -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);
}
diff --git a/sysdeps/unix/sysv/linux/clock_settime.c b/sysdeps/unix/sysv/linux/clock_settime.c
index 31ba0225fb..731b7be7b8 100644
--- a/sysdeps/unix/sysv/linux/clock_settime.c
+++ b/sysdeps/unix/sysv/linux/clock_settime.c
@@ -16,10 +16,65 @@
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>
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/pause.c b/sysdeps/unix/sysv/linux/sparc/sparc64/pause.c
index 40fab28d47..2ec5bd39ad 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc64/pause.c
+++ b/sysdeps/unix/sysv/linux/sparc/sparc64/pause.c
@@ -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>