Workaround MAP_GROWSDOWN unavailability on WSL

This commit is contained in:
Justine Tunney 2022-11-02 01:38:06 -07:00
parent bd6069deb5
commit fc96af058b
No known key found for this signature in database
GPG key ID: BE714B4575D6E328
4 changed files with 62 additions and 47 deletions

Binary file not shown.

View file

@ -380,16 +380,20 @@ static noasan inline void *Mmap(void *addr, size_t size, int prot, int flags,
// with 4kb guards like a sane multithreaded production system. // with 4kb guards like a sane multithreaded production system.
// however this 1mb behavior oddly enough is smart enough to not // however this 1mb behavior oddly enough is smart enough to not
// apply if the mapping is a manually-created guard page. // apply if the mapping is a manually-created guard page.
int e = errno;
if ((dm = sys_mmap(p + size - PAGESIZE, PAGESIZE, prot, if ((dm = sys_mmap(p + size - PAGESIZE, PAGESIZE, prot,
f | MAP_GROWSDOWN_linux, fd, off)) f | MAP_GROWSDOWN_linux, fd, off))
.addr == MAP_FAILED) { .addr != MAP_FAILED) {
return MAP_FAILED;
}
_npassert(sys_mmap(p, PAGESIZE, PROT_NONE, _npassert(sys_mmap(p, PAGESIZE, PROT_NONE,
MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0) MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0)
.addr == p); .addr == p);
dm.addr = p; dm.addr = p;
return FinishMemory(p, size, prot, flags, fd, off, f, x, n, dm); return FinishMemory(p, size, prot, flags, fd, off, f, x, n, dm);
} else if (errno == ENOTSUP) {
// WSL doesn't support MAP_GROWSDOWN
needguard = true;
errno = e;
}
} else { } else {
if (IsFreebsd()) { if (IsFreebsd()) {
f |= MAP_STACK_freebsd; f |= MAP_STACK_freebsd;

View file

@ -77,7 +77,7 @@ syscon errno EPROTOTYPE 91 41 41 41 41 10041 # protocol wrong typ
syscon errno ENOPROTOOPT 92 42 42 42 42 10042 # protocol not available; bsd consensus; WSAENOPROTOOPT; raised by getsockopt(2), accept(2), ip(7) syscon errno ENOPROTOOPT 92 42 42 42 42 10042 # protocol not available; bsd consensus; WSAENOPROTOOPT; raised by getsockopt(2), accept(2), ip(7)
syscon errno EPROTONOSUPPORT 93 43 43 43 43 10043 # protocol not supported; bsd consensus; WSAEPROTONOSUPPORT; raised by socket(2), socketpair(2), unix(7) syscon errno EPROTONOSUPPORT 93 43 43 43 43 10043 # protocol not supported; bsd consensus; WSAEPROTONOSUPPORT; raised by socket(2), socketpair(2), unix(7)
syscon errno ESOCKTNOSUPPORT 94 44 44 44 44 10044 # socket type not supported; bsd consensus; WSAESOCKTNOSUPPORT; raised by unix(7), ip(7) syscon errno ESOCKTNOSUPPORT 94 44 44 44 44 10044 # socket type not supported; bsd consensus; WSAESOCKTNOSUPPORT; raised by unix(7), ip(7)
syscon errno ENOTSUP 95 45 45 91 86 10045 # operation not supported; raised by chmod(2), clock_getres(2), clock_nanosleep(2), getxattr(2), listxattr(2), removexattr(2), setxattr(2), timer_create(2) syscon errno ENOTSUP 95 45 45 91 86 10045 # operation not supported; raised by chmod(2), clock_getres(2), clock_nanosleep(2), getxattr(2), listxattr(2), removexattr(2), setxattr(2), timer_create(2), mmap(2)
syscon errno EOPNOTSUPP 95 102 45 45 45 10045 # socket operation not supported; raised by accept(2), fallocate(2), fanotify_mark(2), ioctl_ficlonerange(2), ioctl_fideduperange(2), ioctl_getfsmap(2), keyctl(2), listen(2), mmap(2), open_by_handle_at(2), pciconfig_read(2), perf_event_open(2), prctl(2), readv(2), s390_guarded_storage(2), s390_runtime_instr(2), s390_sthyi(2), send(2), socketpair(2), unix(7), ip(7) syscon errno EOPNOTSUPP 95 102 45 45 45 10045 # socket operation not supported; raised by accept(2), fallocate(2), fanotify_mark(2), ioctl_ficlonerange(2), ioctl_fideduperange(2), ioctl_getfsmap(2), keyctl(2), listen(2), mmap(2), open_by_handle_at(2), pciconfig_read(2), perf_event_open(2), prctl(2), readv(2), s390_guarded_storage(2), s390_runtime_instr(2), s390_sthyi(2), send(2), socketpair(2), unix(7), ip(7)
syscon errno EPFNOSUPPORT 96 46 46 46 46 10046 # protocol family not supported; bsd consensus; WSAEPFNOSUPPORT syscon errno EPFNOSUPPORT 96 46 46 46 46 10046 # protocol family not supported; bsd consensus; WSAEPFNOSUPPORT
syscon errno EAFNOSUPPORT 97 47 47 47 47 10047 # address family not supported; bsd consensus; WSAEAFNOSUPPORT; raised by connect(2), socket(2), socketpair(2), tcp(7) syscon errno EAFNOSUPPORT 97 47 47 47 47 10047 # address family not supported; bsd consensus; WSAEAFNOSUPPORT; raised by connect(2), socket(2), socketpair(2), tcp(7)

View file

@ -76,6 +76,10 @@
#define kIncludePrefix "include \"" #define kIncludePrefix "include \""
#define THREADS 1 // _getcpucount()
#define LOCK (void) // if (__threaded) pthread_spin_lock
#define UNLOCK (void) // pthread_spin_unlock
const char kSourceExts[][5] = {".s", ".S", ".c", ".cc", ".cpp"}; const char kSourceExts[][5] = {".s", ".S", ".c", ".cc", ".cpp"};
const char *const kIgnorePrefixes[] = { const char *const kIgnorePrefixes[] = {
@ -118,20 +122,19 @@ struct Edges {
}; };
char *out; char *out;
int threads;
char **bouts; char **bouts;
pthread_t *th;
unsigned counter; unsigned counter;
struct spawn *th;
struct GetArgs ga; struct GetArgs ga;
struct Edges edges; struct Edges edges;
struct Sauce *sauces; struct Sauce *sauces;
struct Strings strings; struct Strings strings;
struct Sources sources; struct Sources sources;
const char *buildroot; const char *buildroot;
pthread_mutex_t galock; pthread_spinlock_t galock;
pthread_mutex_t readlock; pthread_spinlock_t readlock;
pthread_mutex_t writelock; pthread_spinlock_t writelock;
pthread_mutex_t reportlock; pthread_spinlock_t reportlock;
unsigned Hash(const void *s, size_t l) { unsigned Hash(const void *s, size_t l) {
return max(1, crc32c(0, s, l)); return max(1, crc32c(0, s, l));
@ -243,7 +246,7 @@ wontreturn void OnMissingFile(const char *list, const char *src) {
exit(1); exit(1);
} }
int LoadRelationshipsWorker(void *arg, int tid) { void *LoadRelationshipsWorker(void *arg) {
int fd; int fd;
ssize_t rc; ssize_t rc;
bool skipme; bool skipme;
@ -255,18 +258,18 @@ int LoadRelationshipsWorker(void *arg, int tid) {
const char *p, *pe, *src, *path, *pathend; const char *p, *pe, *src, *path, *pathend;
inclen = strlen(kIncludePrefix); inclen = strlen(kIncludePrefix);
for (;;) { for (;;) {
pthread_mutex_lock(&galock); LOCK(&galock);
if ((src = getargs_next(&ga))) strcpy(srcbuf, src); if ((src = getargs_next(&ga))) strcpy(srcbuf, src);
pthread_mutex_unlock(&galock); UNLOCK(&galock);
if (!src) break; if (!src) break;
src = srcbuf; src = srcbuf;
if (ShouldSkipSource(src)) continue; if (ShouldSkipSource(src)) continue;
n = strlen(src); n = strlen(src);
pthread_mutex_lock(&readlock); LOCK(&readlock);
srcid = GetSourceId(src, n); srcid = GetSourceId(src, n);
pthread_mutex_unlock(&readlock); UNLOCK(&readlock);
if ((fd = open(src, O_RDONLY)) == -1) { if ((fd = open(src, O_RDONLY)) == -1) {
pthread_mutex_lock(&reportlock); LOCK(&reportlock);
OnMissingFile(ga.path, src); OnMissingFile(ga.path, src);
} }
CHECK_NE(-1, fstat(fd, &st)); CHECK_NE(-1, fstat(fd, &st));
@ -279,14 +282,14 @@ int LoadRelationshipsWorker(void *arg, int tid) {
if (pathend && // if (pathend && //
(p[-1] == '#' || p[-1] == '.') && // (p[-1] == '#' || p[-1] == '.') && //
(p - buf == 1 || p[-2] == '\n')) { // (p - buf == 1 || p[-2] == '\n')) { //
pthread_mutex_lock(&readlock); LOCK(&readlock);
dependency = GetSourceId(path, pathend - path); dependency = GetSourceId(path, pathend - path);
pthread_mutex_unlock(&readlock); UNLOCK(&readlock);
edge.from = srcid; edge.from = srcid;
edge.to = dependency; edge.to = dependency;
pthread_mutex_lock(&writelock); LOCK(&writelock);
append(&edges, &edge); append(&edges, &edge);
pthread_mutex_unlock(&writelock); UNLOCK(&writelock);
p = pathend; p = pathend;
} }
} }
@ -300,15 +303,20 @@ int LoadRelationshipsWorker(void *arg, int tid) {
void LoadRelationships(int argc, char *argv[]) { void LoadRelationships(int argc, char *argv[]) {
int i; int i;
getargs_init(&ga, argv + optind); getargs_init(&ga, argv + optind);
for (i = 0; i < threads; ++i) { if (THREADS == 1) {
if (_spawn(LoadRelationshipsWorker, (void *)(intptr_t)i, th + i) == -1) { LoadRelationshipsWorker((void *)(intptr_t)0);
pthread_mutex_lock(&reportlock); } else {
for (i = 0; i < THREADS; ++i) {
if (pthread_create(th + i, 0, LoadRelationshipsWorker,
(void *)(intptr_t)i)) {
LOCK(&reportlock);
kprintf("error: _spawn(%d) failed %m\n", i); kprintf("error: _spawn(%d) failed %m\n", i);
exit(1); exit(1);
} }
} }
for (i = 0; i < threads; ++i) { for (i = 0; i < THREADS; ++i) {
_join(th + i); pthread_join(th[i], 0);
}
} }
getargs_destroy(&ga); getargs_destroy(&ga);
} }
@ -375,7 +383,7 @@ void Dive(char **bout, uint32_t *visited, unsigned id) {
} }
} }
int Diver(void *arg, int tid) { void *Diver(void *arg) {
char *bout = 0; char *bout = 0;
const char *path; const char *path;
uint32_t *visited; uint32_t *visited;
@ -385,7 +393,7 @@ int Diver(void *arg, int tid) {
visilen = (sources.i + sizeof(*visited) * CHAR_BIT - 1) / visilen = (sources.i + sizeof(*visited) * CHAR_BIT - 1) /
(sizeof(*visited) * CHAR_BIT); (sizeof(*visited) * CHAR_BIT);
visited = malloc(visilen * sizeof(*visited)); visited = malloc(visilen * sizeof(*visited));
for (i = x; i < sources.i; i += threads) { for (i = x; i < sources.i; i += THREADS) {
path = strings.p + sauces[i].name; path = strings.p + sauces[i].name;
if (!IsObjectSource(path)) continue; if (!IsObjectSource(path)) continue;
appendw(&bout, '\n'); appendw(&bout, '\n');
@ -408,15 +416,19 @@ int Diver(void *arg, int tid) {
void Explore(void) { void Explore(void) {
int i; int i;
for (i = 0; i < threads; ++i) { if (THREADS == 1) {
if (_spawn(Diver, (void *)(intptr_t)i, th + i) == -1) { Diver((void *)(intptr_t)0);
pthread_mutex_lock(&reportlock); } else {
for (i = 0; i < THREADS; ++i) {
if (pthread_create(th + i, 0, Diver, (void *)(intptr_t)i)) {
LOCK(&reportlock);
kprintf("error: _spawn(%d) failed %m\n", i); kprintf("error: _spawn(%d) failed %m\n", i);
exit(1); exit(1);
} }
} }
for (i = 0; i < threads; ++i) { for (i = 0; i < THREADS; ++i) {
_join(th + i); pthread_join(th[i], 0);
}
} }
} }
@ -425,19 +437,18 @@ int main(int argc, char *argv[]) {
ShowCrashReports(); ShowCrashReports();
if (argc == 2 && !strcmp(argv[1], "-n")) exit(0); if (argc == 2 && !strcmp(argv[1], "-n")) exit(0);
GetOpts(argc, argv); GetOpts(argc, argv);
threads = 1; // _getcpucount(); th = calloc(THREADS, sizeof(*th));
th = calloc(threads, sizeof(*th)); bouts = calloc(THREADS, sizeof(*bouts));
bouts = calloc(threads, sizeof(*bouts));
LoadRelationships(argc, argv); LoadRelationships(argc, argv);
Crunch(); Crunch();
Explore(); Explore();
CHECK_NE(-1, (fd = open(out, O_WRONLY | O_CREAT | O_TRUNC, 0644)), CHECK_NE(-1, (fd = open(out, O_WRONLY | O_CREAT | O_TRUNC, 0644)),
"open(%#s)", out); "open(%#s)", out);
for (i = 0; i < threads; ++i) { for (i = 0; i < THREADS; ++i) {
CHECK_NE(-1, xwrite(fd, bouts[i], appendz(bouts[i]).i)); CHECK_NE(-1, xwrite(fd, bouts[i], appendz(bouts[i]).i));
} }
CHECK_NE(-1, close(fd)); CHECK_NE(-1, close(fd));
for (i = 0; i < threads; ++i) { for (i = 0; i < THREADS; ++i) {
free(bouts[i]); free(bouts[i]);
} }
free(strings.p); free(strings.p);