You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
151 lines
2.3 KiB
151 lines
2.3 KiB
#include <common.h>
|
|
|
|
__thread int id;
|
|
|
|
int nthreads;
|
|
int count;
|
|
|
|
void barrier_init()
|
|
{
|
|
count = 0;
|
|
}
|
|
|
|
void barrier()
|
|
{
|
|
// barrier
|
|
for (;;) {
|
|
int oc = count;
|
|
int nc = oc + 1;
|
|
if (__sync_bool_compare_and_swap(&count, oc, nc))
|
|
break;
|
|
}
|
|
|
|
int volatile *p = &count;
|
|
while (*p != nthreads)
|
|
;
|
|
}
|
|
|
|
void *fn(void *a)
|
|
{
|
|
int b = (int)(long)a;
|
|
id = b;
|
|
|
|
// barrier
|
|
barrier();
|
|
|
|
printf("my id is still: %d (%d)\n", id, b);
|
|
if (id != b)
|
|
errx(-1, "TLS fyuked!");
|
|
|
|
return NULL;
|
|
}
|
|
|
|
static long volatile go __attribute__((aligned(4096)));
|
|
static int blah __attribute__((aligned(4096)));
|
|
|
|
void *groupfault(void *a)
|
|
{
|
|
int b = (int)(long)a;
|
|
|
|
while (!go)
|
|
#if defined(__x86_64__)
|
|
asm volatile("pause":::"memory");
|
|
#elif defined(__aarch64__)
|
|
asm volatile("yield":::"memory");
|
|
#endif
|
|
|
|
blah = b;
|
|
|
|
return NULL;
|
|
}
|
|
|
|
static int volatile observe __attribute__((aligned(4096))) = 10;
|
|
|
|
void acquire(void)
|
|
{
|
|
while (__sync_lock_test_and_set(&go, 1) != 0)
|
|
;
|
|
}
|
|
|
|
void release(void)
|
|
{
|
|
go = 0;
|
|
}
|
|
|
|
void *tlbinval(void *a)
|
|
{
|
|
acquire();
|
|
if (observe != 0x31337)
|
|
errx(-1, "didn't get tlb invalidate: %d", observe);
|
|
release();
|
|
return NULL;
|
|
}
|
|
|
|
void joinall(pthread_t t[])
|
|
{
|
|
int i;
|
|
for (i = 0; i < nthreads; i++) {
|
|
void *ret;
|
|
if (pthread_join(t[i], &ret))
|
|
errx(-1, "pthread join");
|
|
if (ret)
|
|
errx(-1, "bad exit");
|
|
}
|
|
}
|
|
|
|
int main(int argc, char **argv)
|
|
{
|
|
if (argc > 1)
|
|
nthreads = atoi(argv[1]);
|
|
if (nthreads <= 0)
|
|
nthreads = 3;
|
|
|
|
barrier_init();
|
|
printf("making %d threads\n", nthreads);
|
|
pthread_t t[nthreads];
|
|
int i;
|
|
for (i = 0; i < nthreads; i++)
|
|
if (pthread_create(&t[i], NULL, fn, (void *)(long)i))
|
|
errx(-1, "pthread create");
|
|
|
|
printf("started\n");
|
|
|
|
joinall(t);
|
|
printf("joined. doing group fault...\n");
|
|
|
|
// test simultaneous faults
|
|
for (i = 0; i < nthreads; i++)
|
|
if (pthread_create(&t[i], NULL, groupfault, (void *)(long)i))
|
|
errx(-1, "pthread create");
|
|
|
|
sleep(1);
|
|
printf("fork\n");
|
|
|
|
// make address space copy-on-write by forking
|
|
pid_t c = fork();
|
|
if (c == -1)
|
|
err(-1, "fork");
|
|
else if (c == 0)
|
|
return 0;
|
|
|
|
go = 1;
|
|
joinall(t);
|
|
go = 0;
|
|
|
|
printf("testing TLB shootdowns...\n");
|
|
// test TLB shootdowns
|
|
acquire();
|
|
for (i = 0; i < nthreads; i++)
|
|
if (pthread_create(&t[i], NULL, tlbinval, NULL))
|
|
errx(-1, "pthread create");
|
|
|
|
observe = 0x31337;
|
|
release();
|
|
|
|
joinall(t);
|
|
|
|
printf("success\n");
|
|
|
|
return 0;
|
|
}
|