aboutsummaryrefslogtreecommitdiff
path: root/elf/tst-tls1.c
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>2002-02-10 09:15:59 +0000
committerUlrich Drepper <drepper@redhat.com>2002-02-10 09:15:59 +0000
commit27cd32989b69864f513681caa0b52e154008a0e1 (patch)
treeac9e308ea6a2dff8ec1c5004aca2a4c15d44d132 /elf/tst-tls1.c
parent32083fb8881ee3d8459a795d98b2779928b78929 (diff)
downloadglibc-27cd32989b69864f513681caa0b52e154008a0e1.zip
glibc-27cd32989b69864f513681caa0b52e154008a0e1.tar.gz
glibc-27cd32989b69864f513681caa0b52e154008a0e1.tar.bz2
Update.
* elf/tst-tls1.c (main): Add complete set of tests. Split architecture specific definitions from the actual test code.
Diffstat (limited to 'elf/tst-tls1.c')
-rw-r--r--elf/tst-tls1.c158
1 files changed, 107 insertions, 51 deletions
diff --git a/elf/tst-tls1.c b/elf/tst-tls1.c
index 4d09138..fc426b0 100644
--- a/elf/tst-tls1.c
+++ b/elf/tst-tls1.c
@@ -6,14 +6,8 @@
/* XXX Until gcc gets told how to define and use thread-local
variables we will have to resort to use asms. */
-//asm (".tls_common foo,4,4");
-asm (".section \".tdata\", \"awT\", @progbits\n\t"
- ".align 4\n\t"
- ".globl foo\n"
- "foo:\t.long 0\n\t"
- ".globl bar\n"
- "bar:\t.long 0\n\t"
- ".previous");
+asm (".tls_common foo,4,4");
+asm (".tls_common bar,4,4");
int
@@ -21,59 +15,121 @@ main (void)
{
#ifdef USE_TLS
int result = 0;
- int a, b;
+ int *ap, *bp;
/* XXX Each architecture must have its own asm for now. */
# ifdef __i386__
- /* Set the variable using the local exec model. */
- puts ("set bar to 1 (LE)");
- asm ("movl %gs:0,%eax\n\t"
- "subl $bar@tpoff,%eax\n\t"
- "movl $1,(%eax)");
+# define TLS_LE(x) \
+ ({ int *__l; \
+ asm ("movl %%gs:0,%0\n\t" \
+ "subl $" #x "@tpoff,%0" \
+ : "=r" (__l)); \
+ __l; })
-#if 0
- // XXX Doesn't work yet; no runtime relocations.
- fputs ("get sum of foo and bar (IE)", stdout);
- asm ("call 1f\n\t"
- ".subsection 1\n"
- "1:\tmovl (%%esp), %%ebx\n\t"
- "ret\n\t"
- ".previous\n\t"
- "addl $_GLOBAL_OFFSET_TABLE_, %%ebx\n\t"
- "movl %%gs:0,%%eax\n\t"
- "movl %%eax,%%edx\n\t"
- "addl foo@gottpoff(%%ebx),%%eax\n\t"
- "addl bar@gottpoff(%%ebx),%%eax\n\t"
- "movl (%%eax), %0\n\t"
- "addl (%%edx), %0"
- : "=a" (a), "=&b" (b));
- printf (" = %d\n", a);
- result |= a != 1;
-#endif
+#define TLS_IE(x) \
+ ({ int *__l, __b; \
+ asm ("call 1f\n\t" \
+ ".subsection 1\n" \
+ "1:\tmovl (%%esp), %%ebx\n\t" \
+ "ret\n\t" \
+ ".previous\n\t" \
+ "addl $_GLOBAL_OFFSET_TABLE_, %%ebx\n\t" \
+ "movl %%gs:0,%0\n\t" \
+ "subl " #x "@gottpoff(%%ebx),%0" \
+ : "=r" (__l), "=&b" (__b)); \
+ __l; })
- fputs ("get sum of foo and bar (GD)", stdout);
- asm ("call 1f\n\t"
- ".subsection 1\n"
- "1:\tmovl (%%esp), %%ebx\n\t"
- "ret\n\t"
- ".previous\n\t"
- "addl $_GLOBAL_OFFSET_TABLE_, %%ebx\n\t"
- "leal foo@tlsgd(%%ebx),%%eax\n\t"
- "call ___tls_get_addr@plt\n\t"
- "nop\n\t"
- "movl (%%eax), %%edx\n\t"
- "leal bar@tlsgd(%%ebx),%%eax\n\t"
- "call ___tls_get_addr@plt\n\t"
- "nop\n\t"
- "addl (%%eax), %%edx\n\t"
- : "=&a" (a), "=d" (b));
- printf (" = %d\n", b);
- result |= b != 1;
+#define TLS_LD(x) \
+ ({ int *__l, __b; \
+ asm ("call 1f\n\t" \
+ ".subsection 1\n" \
+ "1:\tmovl (%%esp), %%ebx\n\t" \
+ "ret\n\t" \
+ ".previous\n\t" \
+ "addl $_GLOBAL_OFFSET_TABLE_, %%ebx\n\t" \
+ "leal " #x "@tlsldm(%%ebx),%%eax\n\t" \
+ "call ___tls_get_addr@plt\n\t" \
+ "leal " #x "@dtpoff(%%eax), %%eax" \
+ : "=a" (__l), "=&b" (__b)); \
+ __l; })
+
+#define TLS_GD(x) \
+ ({ int *__l, __b; \
+ asm ("call 1f\n\t" \
+ ".subsection 1\n" \
+ "1:\tmovl (%%esp), %%ebx\n\t" \
+ "ret\n\t" \
+ ".previous\n\t" \
+ "addl $_GLOBAL_OFFSET_TABLE_, %%ebx\n\t" \
+ "leal " #x "@tlsgd(%%ebx),%%eax\n\t" \
+ "call ___tls_get_addr@plt\n\t" \
+ "nop" \
+ : "=a" (__l), "=&b" (__b)); \
+ __l; })
# else
# error "No support for this architecture so far."
# endif
+ /* Set the variable using the local exec model. */
+ puts ("set bar to 1 (LE)");
+ ap = TLS_LE (bar);
+ *ap = 1;
+
+
+ /* Get variables using initial exec model. */
+ fputs ("get sum of foo and bar (IE)", stdout);
+ ap = TLS_IE (foo);
+ bp = TLS_IE (bar);
+ printf (" = %d\n", *ap + *bp);
+ result |= *ap + *bp != 1;
+ if (*ap != 0)
+ {
+ printf ("foo = %d\n", *ap);
+ result = 1;
+ }
+ if (*bp != 1)
+ {
+ printf ("bar = %d\n", *bp);
+ result = 1;
+ }
+
+
+ /* Get variables using local dynamic model. */
+ fputs ("get sum of foo and bar (LD)", stdout);
+ ap = TLS_LD (foo);
+ bp = TLS_LD (bar);
+ printf (" = %d\n", *ap + *bp);
+ result |= *ap + *bp != 1;
+ if (*ap != 0)
+ {
+ printf ("foo = %d\n", *ap);
+ result = 1;
+ }
+ if (*bp != 1)
+ {
+ printf ("bar = %d\n", *bp);
+ result = 1;
+ }
+
+
+ /* Get variables using generic dynamic model. */
+ fputs ("get sum of foo and bar (GD)", stdout);
+ ap = TLS_GD (foo);
+ bp = TLS_GD (bar);
+ printf (" = %d\n", *ap + *bp);
+ result |= *ap + *bp != 1;
+ if (*ap != 0)
+ {
+ printf ("foo = %d\n", *ap);
+ result = 1;
+ }
+ if (*bp != 1)
+ {
+ printf ("bar = %d\n", *bp);
+ result = 1;
+ }
+
return result;
#else
return 0;