[PATCH] nptl: add libpthread __errno_location wrapper

Roman I Khimov khimov at altell.ru
Fri Apr 30 14:18:33 UTC 2010


Trivial test case for x86_64:

==============================================================

static void *process(void * arg)
{
        void *a = &errno;
        printf("thread errno addr: %llx\n", a);
        __asm__("movq    errno at gottpoff(%%rip), %0;\n"
                "add    %%fs:0x0,%0;" : "=r"(a) );
        printf("thread got errno addr: %llx\n", a);
        return NULL;
}

int main() {
        void *a = &errno;
        pthread_t thread;

        printf("errno addr: %llx\n", a);
        __asm__("movq    errno at gottpoff(%%rip), %0;\n"
                "add    %%fs:0x0,%0;" : "=r"(a) );
        printf("got errno addr: %llx\n", a);

        pthread_create(&thread, NULL, process, NULL);
        pthread_join(thread, a);
}
==============================================================

lead to different errno addresses. Direct access through the GOT (as
opposed to __errno_location) is used a lot in arch-speficic NPTL routines, so
errno was broken in many cases, for example, it was easily seen in tst-sem1,
tst-sem3, tst-mqueue2 and other nptl tests.

I've not found any better solution than to introduce local __errno_location
wrapper which seems to work fine (fixed 7 nptl tests).
---
 libpthread/nptl/Makefile.in |    2 +-
 libpthread/nptl/errno.c     |   31 +++++++++++++++++++++++++++++++
 2 files changed, 32 insertions(+), 1 deletions(-)
 create mode 100644 libpthread/nptl/errno.c

diff --git a/libpthread/nptl/Makefile.in b/libpthread/nptl/Makefile.in
index c229673..9b48400 100644
--- a/libpthread/nptl/Makefile.in
+++ b/libpthread/nptl/Makefile.in
@@ -95,7 +95,7 @@ libpthread-routines = init vars events version \
 		      pt-raise pt-system \
 		      flockfile ftrylockfile funlockfile \
 		      sigaction \
-		      herrno res \
+		      herrno errno res \
 		      pthread_kill_other_threads \
 		      pthread_getaffinity pthread_setaffinity \
 		      pthread_attr_getaffinity pthread_attr_setaffinity \
diff --git a/libpthread/nptl/errno.c b/libpthread/nptl/errno.c
new file mode 100644
index 0000000..f66b335
--- /dev/null
+++ b/libpthread/nptl/errno.c
@@ -0,0 +1,31 @@
+/* Copyright (C) 1996,97,98,2002 Free Software Foundation, Inc.
+
+   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 <features.h>
+#include <errno.h>
+#undef errno
+
+#include <tls.h>
+
+extern __thread int errno;
+
+/* When threaded, errno should be a per-thread variable.  */
+int *
+__errno_location (void)
+{
+  return &errno;
+}
-- 
1.5.6.5



More information about the uClibc mailing list