blob: 919f5ee7ecde37a46fc6b4a26bda5ad9aa59c82c [file] [log] [blame]
/*
* Copyright (c) 2011 The Native Client Authors. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include <assert.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
void *mapping;
void *thread_func(void *unused_arg) {
fprintf(stderr, "child thread has started.\n");
while (1) {
/*
* This checks whether mmap() with MAP_FIXED is atomic. On
* Windows, mmap() must temporarily unmap and then re-map a page.
* If this is observable by untrusted code, then the memory access
* below can fault if it occurs while the address is temporarily
* unmapped.
* See http://code.google.com/p/nativeclient/issues/detail?id=1848
*
* This is technically a stress test: since this is
* non-deterministic, we are not guaranteed to detect the problem
* if it exists. However, this is such a tight loop that if we
* are running on a multicore system, we are almost certain to
* detect the problem.
*/
(*(volatile int *) mapping)++;
}
return NULL;
}
int main(void) {
mapping = mmap(NULL, 0x10000, PROT_READ | PROT_WRITE,
MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
assert(mapping != MAP_FAILED);
pthread_t tid;
int rc = pthread_create(&tid, NULL, thread_func, NULL);
assert(rc == 0);
/*
* To increase the chance of detecting a problem, spin until we can
* see that our thread has really been scheduled.
*/
fprintf(stderr, "waiting for child thread...\n");
while (*(volatile int *) mapping == 0) {
/* Nothing */
}
for (int index = 0; index < 1000; index++) {
fprintf(stderr, "mmap call #%i\n", index);
void *result = mmap(mapping, 0x10000, PROT_READ | PROT_WRITE,
MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED, -1, 0);
assert(result == mapping);
/*
* Sanity check: Spin until we see that our thread has touched the
* page. This checks that the thread has been correctly
* unsuspended on Windows. On failure, this will hang.
*/
fprintf(stderr, "checking for write to page...\n");
int value = *(volatile int *) mapping;
while (*(volatile int *) mapping == value) {
/* Nothing */
}
}
return 0;
}