1 /* 2 * EATTLS.C 3 * 4 * Rapidly switch between threads with different TLS pointers to 5 * test that the operating system properly switches the TLS segment. 6 * 7 * $DragonFly: src/test/stress/eattls.c,v 1.1 2005/05/02 19:33:52 dillon Exp $ 8 */ 9 10 #include <sys/types.h> 11 #include <sys/tls.h> 12 #include <stdio.h> 13 #include <stdlib.h> 14 #include <unistd.h> 15 16 #define BIGSIZE (16 * 1024 * 1024) 17 18 struct test { 19 int random1; 20 int random2; 21 }; 22 23 static int getdata(int offset); 24 25 int 26 main(int ac, char **av) 27 { 28 struct tls_info info; 29 struct test *test; 30 char *buf; 31 int gs; 32 int random1; 33 int random2; 34 35 srandomdev(); 36 random1 = random(); 37 random2 = random(); 38 39 buf = malloc(BIGSIZE); 40 buf += random() % (BIGSIZE - sizeof(struct test)); 41 test = (void *)buf; 42 info.base = buf; 43 info.size = sizeof(struct test); 44 if ((gs = sys_set_tls_area(2, &info, sizeof(info))) < 0) { 45 perror("sys_set_tls_area"); 46 exit(1); 47 } 48 test->random1 = random1; 49 test->random2 = random2; 50 printf("setting %%gs to 0x%02x segment at %p\n", gs, test); 51 __asm __volatile("movl %0,%%eax; movl %%eax,%%gs" : "=m" (gs) : : "ax"); 52 for (;;) { 53 if (getdata(0) != random1 || getdata(4) != random2) 54 printf("data verification failed!\n"); 55 if (random() % 1000 > 500) 56 usleep(random() % 1000); 57 } 58 59 return(0); 60 } 61 62 static int 63 getdata(int offset) 64 { 65 int rv; 66 __asm __volatile("movl %%gs:(%0),%%eax; movl %%eax,%1" : 67 "+r" (offset) : "m" (rv) : "ax"); 68 return (rv); 69 } 70 71