This is the mail archive of the libc-hacker@sources.redhat.com mailing list for the glibc project.

Note that libc-hacker is a closed list. You may look at the archives of this list, but subscription and posting are not open.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Fix i386 stack alignment in clone and linuxthreads


Hi!

As shown by the testcases below, while NPTL maintains 16 byte stack
alignment on i386 for thread body function, LinuxThreads and, probably
more important (as LT is going to die eventually) clone function don't.
Turns out sysdeps/unix/sysv/linux/i386/clone.S has been adjusted to
what CALL_THREAD_FCT did, i.e. account for an extra pushl in there.
So, in NPTL, start_thread function has misaligned stack (and any function
it calls, with the exception of the thread body).
I think this is wrong, as if you use clone yourself, you should be able
to expect aligned stack.
This patch further adds an i386/tst-stack-align.h, so that the 16 byte
stack alignment is tested not just on -march=pentium4 or -msse2 compiled
glibc, but any glibc.

2004-12-21  Jakub Jelinek  <jakub@redhat.com>

	* sysdeps/unix/sysv/linux/i386/clone.S (__clone): Make sure %esp when
	calling fn is 16 byte aligned.
	* sysdeps/i386/tst-stack-align.h: New file.
nptl/
	* sysdeps/i386/tls.h (CALL_THREAD_FCT): Maintain 16 byte alignment of
	%esp.
	* Makefile (tests): Add tst-align2.
	* tst-align2.c: New test.
	* sysdeps/i386/Makefile (CFLAGS-tst-align{,2}.c): Add
	-mpreferred-stack-boundary=4.
linuxthreads/
	* Makefile (tests): Add tst-align.
	* tst-align.c: New test.
	* sysdeps/i386/Makefile (CFLAGS-tst-align.c): Add
	-mpreferred-stack-boundary=4.

--- libc/sysdeps/unix/sysv/linux/i386/clone.S.jj	2004-12-06 12:40:59.000000000 +0100
+++ libc/sysdeps/unix/sysv/linux/i386/clone.S	2004-12-21 15:05:27.000000000 +0100
@@ -67,7 +67,7 @@ ENTRY (BP_SYM (__clone))
 	/* Insert the argument onto the new stack.  Make sure the new
 	   thread is started with an alignment of (mod 16).  */
 	andl	$0xfffffff0, %ecx
-	subl	$24,%ecx
+	subl	$28,%ecx
 	movl	ARG(%esp),%eax		/* no negative argument counts */
 	movl	%eax,12(%ecx)
 
--- libc/sysdeps/i386/tst-stack-align.h.jj	2004-12-21 14:41:36.000000000 +0100
+++ libc/sysdeps/i386/tst-stack-align.h	2004-12-21 14:56:17.000000000 +0100
@@ -0,0 +1,42 @@
+/* Copyright (C) 2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <stdio.h>
+#include <stdint.h>
+
+typedef struct { int i[4]; } int_al16 __attribute__((aligned (16)));
+
+#define TEST_STACK_ALIGN() \
+  ({									     \
+    int_al16 _m;							     \
+    double _d = 12.0;							     \
+    long double _ld = 15.0;						     \
+    int _ret = 0;							     \
+    printf ("int_al16:  %p %zu\n", &_m, __alignof (int_al16));		     \
+    if ((((uintptr_t) &_m) & (__alignof (int_al16) - 1)) != 0)		     \
+      _ret = 1;								     \
+									     \
+    printf ("double:  %g %p %zu\n", _d, &_d, __alignof (double));	     \
+    if ((((uintptr_t) &_d) & (__alignof (double) - 1)) != 0)		     \
+      _ret = 1;								     \
+									     \
+    printf ("ldouble: %Lg %p %zu\n", _ld, &_ld, __alignof (long double));    \
+    if ((((uintptr_t) &_ld) & (__alignof (long double) - 1)) != 0)	     \
+      _ret = 1;								     \
+    _ret;								     \
+    })
--- libc/nptl/Makefile.jj	2004-12-13 09:36:18.000000000 +0100
+++ libc/nptl/Makefile	2004-12-21 16:19:21.000000000 +0100
@@ -205,7 +205,7 @@ tests = tst-attr1 tst-attr2 tst-attr3 \
 	tst-sem1 tst-sem2 tst-sem3 tst-sem4 tst-sem5 tst-sem6 tst-sem7 \
 	tst-sem8 tst-sem9 \
 	tst-barrier1 tst-barrier2 tst-barrier3 tst-barrier4 \
-	tst-align \
+	tst-align tst-align2 \
 	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 \
--- libc/nptl/tst-align2.c.jj	2004-12-21 14:44:48.000000000 +0100
+++ libc/nptl/tst-align2.c	2004-12-21 14:59:04.000000000 +0100
@@ -0,0 +1,87 @@
+/* Copyright (C) 2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <sched.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include <tst-stack-align.h>
+
+static int
+f (void *arg)
+{
+  bool ok = true;
+
+  if (TEST_STACK_ALIGN ())
+    ok = false;
+
+  return ok ? 0 : 1;
+}
+
+static int
+do_test (void)
+{
+  bool ok = true;
+
+  puts ("in main");
+
+  if (TEST_STACK_ALIGN ())
+    ok = false;
+
+#ifdef __ia64__
+  extern int __clone2 (int (*__fn) (void *__arg), void *__child_stack_base,
+		       size_t __child_stack_size, int __flags,
+		       void *__arg, ...);
+  char st[256 * 1024];
+  pid_t p = __clone2 (f, st, sizeof (st), 0, 0);
+#else
+  char st[128 * 1024];
+  pid_t p = clone (f, st + sizeof (st), 0, 0);
+#endif
+  if (p == -1)
+    {
+      printf("clone failed: %m\n");
+      return 1;
+    }
+
+  int e;
+  if (waitpid (p, &e, __WCLONE) != p)
+    {
+      puts ("waitpid failed");
+      kill (p, SIGKILL);
+      return 1;
+    }
+  if (!WIFEXITED (e))
+    {
+      if (WIFSIGNALED (e))
+	printf ("died from signal %s\n", strsignal (WTERMSIG (e)));
+      else
+	puts ("did not terminate correctly");
+      return 1;
+    }
+  if (WEXITSTATUS (e) != 0)
+    ok = false;
+
+  return ok ? 0 : 1;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
--- libc/nptl/sysdeps/i386/Makefile.jj	2004-05-18 10:55:59.000000000 +0200
+++ libc/nptl/sysdeps/i386/Makefile	2004-12-21 15:00:18.000000000 +0100
@@ -22,4 +22,6 @@ endif
 
 ifeq ($(subdir),nptl)
 CFLAGS-pthread_create.c += -mpreferred-stack-boundary=4
+CFLAGS-tst-align.c += -mpreferred-stack-boundary=4
+CFLAGS-tst-align2.c += -mpreferred-stack-boundary=4
 endif
--- libc/nptl/sysdeps/i386/tls.h.jj	2004-05-18 10:55:59.000000000 +0200
+++ libc/nptl/sysdeps/i386/tls.h	2004-12-21 15:15:47.000000000 +0100
@@ -397,9 +397,12 @@ union user_desc_init
 #define CALL_THREAD_FCT(descr) \
   ({ void *__res;							      \
      int __ignore1, __ignore2;						      \
-     asm volatile ("pushl %%gs:%P4\n\t"					      \
+     asm volatile ("pushl %%eax\n\t"					      \
+		   "pushl %%eax\n\t"					      \
+		   "pushl %%eax\n\t"					      \
+		   "pushl %%gs:%P4\n\t"					      \
 		   "call *%%gs:%P3\n\t"					      \
-		   "addl $4, %%esp"					      \
+		   "addl $16, %%esp"					      \
 		   : "=a" (__res), "=c" (__ignore1), "=d" (__ignore2)	      \
 		   : "i" (offsetof (struct pthread, start_routine)),	      \
 		     "i" (offsetof (struct pthread, arg)));		      \
--- libc/linuxthreads/Makefile.jj	2004-12-06 12:40:53.000000000 +0100
+++ libc/linuxthreads/Makefile	2004-12-21 15:02:37.000000000 +0100
@@ -111,7 +111,7 @@ tests = ex1 ex2 ex3 ex4 ex5 ex6 ex7 ex8 
 	ex17 ex18 tst-cancel tst-context bug-sleep \
 	tst-cancel1 tst-cancel2 tst-cancel3 tst-cancel4 tst-cancel5 \
 	tst-cancel6 tst-cancel7 tst-cancel8 tst-popen tst-popen2 tst-attr1 \
-	tst-stack1
+	tst-stack1 tst-align
 test-srcs = tst-signal
 # These tests are linked with libc before libpthread
 tests-reverse += tst-cancel5
--- libc/linuxthreads/sysdeps/i386/Makefile.jj	2003-09-17 11:13:28.000000000 +0200
+++ libc/linuxthreads/sysdeps/i386/Makefile	2004-12-21 15:03:38.000000000 +0100
@@ -15,6 +15,7 @@ CFLAGS-pthread.c += -fno-omit-frame-poin
 CFLAGS-ptlongjmp.c += -fno-omit-frame-pointer
 CFLAGS-semaphore.c += -fno-omit-frame-pointer
 CFLAGS-sighandler.c += -fno-omit-frame-pointer -mpreferred-stack-boundary=4
+CFLAGS-tst-align.c += -mpreferred-stack-boundary=4
 endif
 
 ifeq ($(subdir),csu)
--- libc/linuxthreads/tst-align.c.jj	2004-12-21 15:01:36.000000000 +0100
+++ libc/linuxthreads/tst-align.c	2003-09-17 10:31:18.000000000 +0200
@@ -0,0 +1,71 @@
+/* Copyright (C) 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@redhat.com>, 2003.
+
+   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 <pthread.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <tst-stack-align.h>
+
+static void *
+tf (void *arg)
+{
+  bool ok = true;
+
+  puts ("in thread");
+
+  if (TEST_STACK_ALIGN ())
+    ok = false;
+
+  return ok ? NULL : (void *) -1l;
+}
+
+static int
+do_test (void)
+{
+  bool ok = true;
+
+  puts ("in main");
+
+  if (TEST_STACK_ALIGN ())
+    ok = false;
+
+  pthread_t th;
+  if (pthread_create (&th, NULL, tf, NULL) != 0)
+    {
+      puts ("create failed");
+      return 1;
+    }
+
+  void *res;
+  if (pthread_join (th, &res) != 0)
+    {
+      puts ("join failed");
+      return 1;
+    }
+
+  if (res != NULL)
+    ok = false;
+
+  return ok ? 0 : 1;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"

	Jakub


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]