Improve synchronization

- Fix bugs in kDos2Errno definition
- malloc() should now be thread safe
- Fix bug in rollup.com header generator
- Fix open(O_APPEND) on the New Technology
- Fix select() on the New Technology and test it
- Work towards refactoring i/o for thread safety
- Socket reads and writes on NT now poll for signals
- Work towards i/o completion ports on the New Technology
- Make read() and write() intermittently check for signals
- Blinkenlights keyboard i/o so much better on NT w/ poll()
- You can now poll() files and sockets at the same time on NT
- Fix bug in appendr() that manifests with dlmalloc footers off
This commit is contained in:
Justine Tunney 2022-04-14 23:39:48 -07:00
parent 233144b19d
commit 933411ba99
266 changed files with 8761 additions and 4344 deletions

View file

@ -700,14 +700,12 @@ static void LoadSyms(void) {
static int DrainInput(int fd) {
char buf[32];
struct pollfd fds[1];
if (!IsWindows()) {
for (;;) {
fds[0].fd = fd;
fds[0].events = POLLIN;
if (poll(fds, ARRAYLEN(fds), 0) == -1) return -1;
if (!(fds[0].revents & POLLIN)) break;
if (read(fd, buf, sizeof(buf)) == -1) return -1;
}
for (;;) {
fds[0].fd = fd;
fds[0].events = POLLIN;
if (poll(fds, ARRAYLEN(fds), 0) == -1) return -1;
if (!(fds[0].revents & POLLIN)) break;
if (read(fd, buf, sizeof(buf)) == -1) return -1;
}
return 0;
}
@ -1928,25 +1926,21 @@ static int OnPtyFdPoll(struct pollfd *fds, size_t nfds, int ms) {
ReactiveDraw();
once = true;
}
if (!IsWindows()) {
p2.fd = fds[i].fd;
p2.events = fds[i].events;
switch (poll(&p2, 1, ms)) {
case -1:
re = POLLERR;
++t;
break;
case 0:
break;
case 1:
re = p2.revents;
++t;
break;
default:
unreachable;
}
} else {
re = POLLIN | POLLOUT; /* xxx */
p2.fd = fds[i].fd;
p2.events = fds[i].events;
switch (poll(&p2, 1, ms)) {
case -1:
re = POLLERR;
++t;
break;
case 0:
break;
case 1:
re = p2.revents;
++t;
break;
default:
unreachable;
}
}
}
@ -2608,11 +2602,7 @@ static bool HasPendingKeyboard(void) {
}
static void Sleep(int ms) {
if (IsWindows()) {
usleep(ms * 1000L);
} else {
poll((struct pollfd[]){{ttyin, POLLIN}}, 1, ms);
}
poll((struct pollfd[]){{ttyin, POLLIN}}, 1, ms);
}
static void OnMouseWheelUp(struct Panel *p, int y, int x) {

View file

@ -40,5 +40,5 @@ int main() {
SetVideoMode(7);
SetEs(0xb0000 >> 4);
MdaTest((void *)0);
for (;;) asm("pause");
for (;;) __builtin_ia32_pause();
}

View file

@ -21,6 +21,7 @@
#include "libc/bits/safemacros.internal.h"
#include "libc/mem/mem.h"
#include "libc/nexgen32e/crc32.h"
#include "libc/runtime/runtime.h"
#include "libc/str/str.h"
#include "libc/x/x.h"
#include "tool/build/lib/interner.h"
@ -92,10 +93,12 @@ size_t interncount(const struct Interner *t) {
* @note use consistent size w/ non-string items
*/
size_t internobj(struct Interner *t, const void *data, size_t size) {
char *p2;
size_t n2;
char *item;
unsigned hash;
size_t i, step;
struct InternerObject *it;
size_t i, off, step, need, bytes;
step = 0;
item = data;
it = (struct InternerObject *)t;
@ -117,9 +120,25 @@ size_t internobj(struct Interner *t, const void *data, size_t size) {
step++;
} while (it->p[i].hash);
}
off = it->pool.i;
if (__builtin_add_overflow(off, size, &need)) abort();
if (__builtin_add_overflow(need, 1, &need)) abort();
if (need > it->pool.n) {
if (__builtin_add_overflow(it->pool.n, 1, &n2)) abort();
do {
if (__builtin_add_overflow(n2, n2 >> 1, &n2)) abort();
} while (need > n2);
if (__builtin_mul_overflow(n2, sizeof(*it->pool.p), &bytes)) abort();
if (!(p2 = realloc(it->pool.p, bytes))) abort();
it->pool.p = p2;
it->pool.n = n2;
}
memcpy(it->pool.p + off, data, size);
it->pool.p[off + size] = 0;
it->p[i].hash = hash;
return (it->p[i].index =
CONCAT(&it->pool.p, &it->pool.i, &it->pool.n, item, size));
it->p[i].index = off;
it->pool.i += size;
return off;
}
/**

View file

@ -69,11 +69,7 @@ static int OpSerialIn(struct Machine *m, int r) {
return 0x01;
}
case UART_LSR:
if (IsWindows()) {
p = POLLIN | POLLOUT; /* XXX */
} else {
if ((p = OpE9Poll(m)) == -1) return -1;
}
if ((p = OpE9Poll(m)) == -1) return -1;
s = UART_TTYIDL;
if (p & POLLIN) s |= UART_TTYDA;
if (p & POLLOUT) s |= UART_TTYTXR;

View file

@ -37,13 +37,9 @@ void OpPause(struct Machine *m, uint32_t rde) {
interactive = isatty(0);
once = true;
}
if (!IsWindows() && interactive) {
pf.fd = 0;
pf.events = POLLIN;
poll(&pf, 1, 20); /* make spin loops less brutal */
} else {
sched_yield();
}
pf.fd = 0;
pf.events = POLLIN;
poll(&pf, 1, 20); /* make spin loops less brutal */
}
void OpRdtsc(struct Machine *m, uint32_t rde) {

View file

@ -37,7 +37,7 @@
#include "libc/sysv/consts/sa.h"
#include "libc/sysv/consts/sig.h"
#include "libc/x/x.h"
#include "third_party/dlmalloc/dlmalloc.internal.h"
#include "third_party/dlmalloc/dlmalloc.h"
#include "third_party/getopt/getopt.h"
/**

View file

@ -20,62 +20,45 @@
#include "libc/alg/arraylist2.internal.h"
#include "libc/calls/calls.h"
#include "libc/calls/struct/stat.h"
#include "libc/errno.h"
#include "libc/fmt/itoa.h"
#include "libc/intrin/kprintf.h"
#include "libc/log/check.h"
#include "libc/log/log.h"
#include "libc/mem/mem.h"
#include "libc/runtime/runtime.h"
#include "libc/stdio/append.internal.h"
#include "libc/stdio/stdio.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/map.h"
#include "libc/sysv/consts/o.h"
#include "libc/sysv/consts/prot.h"
#include "tool/build/lib/getargs.h"
#include "tool/build/lib/interner.h"
#define LOOKINGAT(p, pe, s) LookingAt(p, pe, s, strlen(s))
#define APPENDSTR(s) AppendData(s, strlen(s))
struct Output {
size_t i, n;
const char *p;
};
struct Visited {
size_t i, n;
const char **p;
};
static struct stat st;
static struct Output output;
static struct Visited visited;
char *output;
struct Interner *visited;
static void Visit(const char *);
void Visit(const char *);
static bool HasVisited(const char *path) {
int i;
for (i = 0; i < visited.i; ++i) {
if (strcmp(path, visited.p[i]) == 0) {
return true;
}
}
return false;
size_t GetFdSize(int fd) {
struct stat st;
CHECK_NE(-1, fstat(fd, &st));
return st.st_size;
}
static void AppendData(const char *s, size_t n) {
CONCAT(&output.p, &output.i, &output.n, s, n);
}
static void AppendInt(long x) {
char ibuf[21];
AppendData(ibuf, int64toarray_radix10(x, ibuf));
}
static bool LookingAt(const char *p, const char *pe, const char *s, size_t n) {
bool LookingAt(const char *p, const char *pe, const char *s, size_t n) {
return pe - p >= n && memcmp(p, s, n) == 0;
}
static void Process(const char *p, const char *pe, const char *path,
bool isheader) {
void Process(const char *p, const char *pe, const char *path, bool isheader) {
int level;
bool noformat;
const char *p2, *dq, *name;
@ -101,16 +84,18 @@ static void Process(const char *p, const char *pe, const char *path,
continue;
}
}
AppendData(p, p2 - p);
appendd(&output, p, p2 - p);
}
if (noformat) {
APPENDSTR("/* clang-format on */\n");
appends(&output, "/* clang-format on */\n");
}
kprintf("finished%n");
}
static void Visit(const char *path) {
void Visit(const char *path) {
int fd;
char *map;
size_t size;
bool isheader;
if (!endswith(path, ".h") && !endswith(path, ".inc")) return;
if (endswith(path, ".internal.h")) return;
@ -118,43 +103,62 @@ static void Visit(const char *path) {
if (endswith(path, ".internal.inc")) return;
if (endswith(path, "/internal.inc")) return;
isheader = endswith(path, ".h");
if (isheader && HasVisited(path)) return;
APPENDSTR("\n\f\n/*!BEGIN ");
APPENDSTR(path);
APPENDSTR(" */\n\n");
APPEND(&visited.p, &visited.i, &visited.n, &path);
if (isheader && isinterned(visited, path)) return;
appends(&output, "\n\f\n/*!BEGIN ");
appends(&output, path);
appends(&output, " */\n\n");
intern(visited, path);
if ((fd = open(path, O_RDONLY)) == -1) {
fprintf(stderr, "error: %s: failed to open\n", path);
exit(1);
}
CHECK_NE(-1, fstat(fd, &st));
if (st.st_size) {
if ((size = GetFdSize(fd))) {
kprintf("size 1 = %'zu%n", size);
CHECK_NE(MAP_FAILED,
(map = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0)));
Process(map, map + st.st_size, path, isheader);
LOGIFNEG1(munmap(map, st.st_size));
(map = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0)));
Process(map, map + size, path, isheader);
kprintf("size = %'zu%n", size);
CHECK_EQ(0, munmap(map, size), "p=%p z=%'zu path=%s", map, size, path);
}
LOGIFNEG1(close(fd));
CHECK_EQ(0, close(fd));
}
ssize_t WriteAll(int fd, const char *p, size_t n) {
ssize_t rc;
size_t i, got;
for (i = 0; i < n;) {
rc = write(fd, p + i, n - i);
if (rc != -1) {
got = rc;
i += got;
} else if (errno != EINTR) {
return -1;
}
}
return i;
}
int main(int argc, char *argv[]) {
const char *src;
struct GetArgs ga;
APPENDSTR("#ifndef COSMOPOLITAN_H_\n");
APPENDSTR("#define COSMOPOLITAN_H_\n");
/* APPENDSTR("#define IMAGE_BASE_VIRTUAL "); */
/* AppendInt(IMAGE_BASE_VIRTUAL); */
/* APPENDSTR("\n"); */
/* APPENDSTR("#define IMAGE_BASE_PHYSICAL "); */
/* AppendInt(IMAGE_BASE_PHYSICAL); */
/* APPENDSTR("\n"); */
ShowCrashReports();
visited = newinterner();
appends(&output, "#ifndef COSMOPOLITAN_H_\n");
appends(&output, "#define COSMOPOLITAN_H_\n");
/* appends(&output, "#define IMAGE_BASE_VIRTUAL "); */
/* appendf(&output, "%p", IMAGE_BASE_VIRTUAL); */
/* appends(&output, "\n"); */
/* appends(&output, "#define IMAGE_BASE_PHYSICAL "); */
/* appendf(&output, "%p", IMAGE_BASE_PHYSICAL); */
/* appends(&output, "\n"); */
getargs_init(&ga, argv + 1);
while ((src = getargs_next(&ga))) {
Visit(src);
}
getargs_destroy(&ga);
APPENDSTR("\n");
APPENDSTR("#endif /* COSMOPOLITAN_H_ */\n");
CHECK_EQ(output.i, write(1, output.p, output.i));
appends(&output, "\n");
appends(&output, "#endif /* COSMOPOLITAN_H_ */\n");
CHECK_NE(-1, WriteAll(1, output, appendz(output).i));
freeinterner(visited);
return 0;
}

View file

@ -92,6 +92,8 @@
#define kLogFile "o/runitd.log"
#define kLogMaxBytes (2 * 1000 * 1000)
bool use_ftrace;
bool use_strace;
char *g_exepath;
volatile bool g_interrupted;
struct sockaddr_in g_servaddr;
@ -136,9 +138,15 @@ void GetOpts(int argc, char *argv[]) {
g_servaddr.sin_family = AF_INET;
g_servaddr.sin_port = htons(RUNITD_PORT);
g_servaddr.sin_addr.s_addr = INADDR_ANY;
while ((opt = getopt(argc, argv, "hvsdrl:p:t:w:")) != -1) {
while ((opt = getopt(argc, argv, "fqhvsdrl:p:t:w:")) != -1) {
switch (opt) {
case 'f':
use_ftrace = true;
break;
case 's':
use_strace = true;
break;
case 'q':
--__log_level;
break;
case 'v':
@ -340,7 +348,12 @@ void HandleClient(void) {
dup2(pipefds[1], 2);
if (pipefds[0] > 2) close(pipefds[1]);
if (g_devnullfd > 2) close(g_devnullfd);
execv(g_exepath, (char *const[]){g_exepath, NULL});
int i = 0;
char *args[4] = {0};
args[i++] = g_exepath;
if (use_strace) args[i++] = "--strace";
if (use_ftrace) args[i++] = "--ftrace";
execv(g_exepath, args);
_exit(127);
}
LOGIFNEG1(close(pipefds[1]));

View file

@ -269,7 +269,13 @@
"__builtin_bcmp"
"__builtin_bzero"
"__builtin_memset"
"__builtin_strlen"))
"__builtin_strlen"
"__ATOMIC_RELAXED"
"__ATOMIC_CONSUME"
"__ATOMIC_ACQUIRE"
"__ATOMIC_RELEASE"
"__ATOMIC_ACQ_REL"
"__ATOMIC_SEQ_CST"))
(gcc-builtin-functions-atomic
'("__atomic_load_n"

View file

@ -902,6 +902,47 @@ static int LuaUnixRecvfrom(lua_State *L) {
return 4;
}
// unix.recv(fd[, bufsiz[, flags]]) → data, errno
static int LuaUnixRecv(lua_State *L) {
char *buf;
size_t got;
ssize_t rc;
int fd, flags, bufsiz, olderr;
olderr = errno;
fd = luaL_checkinteger(L, 1);
bufsiz = luaL_optinteger(L, 2, 1500);
flags = luaL_optinteger(L, 3, 0);
bufsiz = MIN(bufsiz, 0x7ffff000);
buf = xmalloc(bufsiz);
rc = recv(fd, buf, bufsiz, flags);
if (rc != -1) {
got = rc;
lua_pushlstring(L, buf, got);
lua_pushnil(L);
} else {
lua_pushnil(L);
lua_pushinteger(L, errno);
errno = olderr;
}
free(buf);
return 4;
}
// unix.send(fd, data[, flags]) → sent, errno
static int LuaUnixSend(lua_State *L) {
char *data;
ssize_t rc;
size_t sent, size;
int fd, flags, bufsiz, olderr;
olderr = errno;
fd = luaL_checkinteger(L, 1);
data = luaL_checklstring(L, 2, &size);
size = MIN(size, 0x7ffff000);
flags = luaL_optinteger(L, 5, 0);
rc = send(fd, data, size, flags);
return ReturnRc(L, rc, olderr);
}
// unix.sendto(fd, data, ip, port[, flags]) → sent, errno
// flags MSG_OOB, MSG_DONTROUTE, MSG_NOSIGNAL, etc.
static int LuaUnixSendto(lua_State *L) {
@ -1401,7 +1442,9 @@ static const luaL_Reg kLuaUnix[] = {
{"listen", LuaUnixListen}, // begin listening for clients
{"accept", LuaUnixAccept}, // create client fd for client
{"connect", LuaUnixConnect}, // connect to remote address
{"recv", LuaUnixRecv}, // receive tcp from some address
{"recvfrom", LuaUnixRecvfrom}, // receive udp from some address
{"send", LuaUnixSend}, // send tcp to some address
{"sendto", LuaUnixSendto}, // send udp to some address
{"shutdown", LuaUnixShutdown}, // make socket half empty or full
{"getpeername", LuaUnixGetpeername}, // get address of remote end

View file

@ -24,6 +24,7 @@
#include "libc/calls/calls.h"
#include "libc/calls/math.h"
#include "libc/calls/sigbits.h"
#include "libc/calls/strace.internal.h"
#include "libc/calls/struct/dirent.h"
#include "libc/calls/struct/flock.h"
#include "libc/calls/struct/rusage.h"
@ -1187,11 +1188,7 @@ static void KillGroupImpl(int sig) {
}
static void KillGroup(void) {
if (IsWindows()) {
KillGroupImpl(SIGINT);
} else {
KillGroupImpl(SIGTERM);
}
KillGroupImpl(SIGTERM);
}
static void WaitAll(void) {

View file

@ -20,6 +20,7 @@
#include "libc/calls/calls.h"
#include "libc/dns/dns.h"
#include "libc/errno.h"
#include "libc/fmt/conv.h"
#include "libc/log/check.h"
#include "libc/log/log.h"
#include "libc/macros.internal.h"
@ -53,6 +54,8 @@
#include "third_party/mbedtls/error.h"
#include "third_party/mbedtls/ssl.h"
#define OPTS "BIqksvzX:H:C:m:"
#define Micros(t) ((int64_t)((t)*1e6))
#define HasHeader(H) (!!msg.headers[H].a)
#define HeaderData(H) (inbuf.p + msg.headers[H].a)
@ -79,16 +82,17 @@ bool authmode = MBEDTLS_SSL_VERIFY_NONE;
char *host;
char *port;
char *flags;
bool usessl;
uint32_t ip;
struct Url url;
struct addrinfo *addr;
struct Buffer inbuf;
long fetch_count;
long error_count;
long failure_count;
long response_count;
long message_count;
long connect_count;
double *latencies;
size_t latencies_n;
size_t latencies_c;
@ -96,6 +100,8 @@ long double start_run;
long double end_run;
long double start_fetch;
long double end_fetch;
long connectionstobemade = 100;
long messagesperconnection = 100;
mbedtls_x509_crt *cachain;
mbedtls_ssl_config conf;
@ -146,7 +152,18 @@ static int TlsRecv(void *c, unsigned char *p, size_t n, uint32_t o) {
}
static wontreturn void PrintUsage(FILE *f, int rc) {
fprintf(f, "usage: %s [-ksvV] URL\n", program_invocation_name);
fprintf(f, "usage: %s [-%s] URL\n", OPTS, program_invocation_name);
fprintf(f, "wb - cosmopolitan http/https benchmark tool\n");
fprintf(f, " -C INT connections to be made\n");
fprintf(f, " -m INT messages per connection\n");
fprintf(f, " -B use suite b ciphersuites\n");
fprintf(f, " -v increase verbosity\n");
fprintf(f, " -H K:V append http header\n");
fprintf(f, " -X NAME specify http method\n");
fprintf(f, " -k verify ssl certs\n");
fprintf(f, " -I same as -X HEAD\n");
fprintf(f, " -z same as -H Accept-Encoding:gzip\n");
fprintf(f, " -h show this help\n");
exit(rc);
}
@ -157,11 +174,14 @@ int fetch(void) {
const char *body;
int t, ret, sock;
struct TlsBio *bio;
long messagesremaining;
struct HttpMessage msg;
struct HttpUnchunker u;
size_t urlarglen, requestlen;
size_t g, i, n, hdrsize, paylen;
messagesremaining = messagesperconnection;
/*
* Setup crypto.
*/
@ -294,13 +314,12 @@ SendAnother:
Finished:
status = msg.status;
DestroyHttpMessage(&msg);
if (!isdone && status == 200) {
if (!isdone && status == 200 && --messagesremaining > 0) {
long double now = nowl();
end_fetch = now;
++response_count;
++message_count;
latencies = realloc(latencies, ++latencies_n * sizeof(*latencies));
latencies[latencies_n - 1] = end_fetch - start_fetch;
++fetch_count;
start_fetch = now;
goto SendAnother;
}
@ -321,29 +340,45 @@ int main(int argc, char *argv[]) {
*/
int opt;
__log_level = kLogWarn;
while ((opt = getopt(argc, argv, "BqksvIX:H:")) != -1) {
while ((opt = getopt(argc, argv, OPTS)) != -1) {
switch (opt) {
case 's':
case 'q':
break;
case 'B':
suiteb = true;
appendf(&flags, " -B");
break;
case 'v':
++__log_level;
break;
case 'I':
method = kHttpHead;
appendf(&flags, " -I");
break;
case 'H':
headers.p = realloc(headers.p, ++headers.n * sizeof(*headers.p));
headers.p[headers.n - 1] = optarg;
appendf(&flags, " -H '%s'", optarg);
break;
case 'z':
headers.p = realloc(headers.p, ++headers.n * sizeof(*headers.p));
headers.p[headers.n - 1] = "Accept-Encoding: gzip";
appendf(&flags, " -z");
break;
case 'X':
CHECK((method = GetHttpMethod(optarg, strlen(optarg))));
appendf(&flags, " -X %s", optarg);
break;
case 'k':
authmode = MBEDTLS_SSL_VERIFY_REQUIRED;
appendf(&flags, " -k");
break;
case 'm':
messagesperconnection = strtol(optarg, 0, 0);
break;
case 'C':
connectionstobemade = strtol(optarg, 0, 0);
break;
case 'h':
PrintUsage(stdout, EXIT_SUCCESS);
@ -352,10 +387,15 @@ int main(int argc, char *argv[]) {
}
}
appendf(&flags, " -m %ld", messagesperconnection);
appendf(&flags, " -C %ld", connectionstobemade);
if (optind == argc) PrintUsage(stdout, EXIT_SUCCESS);
urlarg = argv[optind];
cachain = GetSslRoots();
long connectsremaining = connectionstobemade;
/*
* Parse URL.
*/
@ -434,13 +474,13 @@ int main(int argc, char *argv[]) {
latencies_c = 1024;
latencies = malloc(latencies_c * sizeof(*latencies));
start_run = nowl();
while (!isdone) {
++fetch_count;
while (!isdone && --connectsremaining >= 0) {
start_fetch = nowl();
status = fetch();
end_fetch = nowl();
if (status == 200) {
++response_count;
++connect_count;
++message_count;
latencies = realloc(latencies, ++latencies_n * sizeof(*latencies));
latencies[latencies_n - 1] = end_fetch - start_fetch;
} else if (status == 900) {
@ -452,17 +492,17 @@ int main(int argc, char *argv[]) {
end_run = nowl();
double latencies_sum = fsum(latencies, latencies_n);
double avg_latency = latencies_sum / response_count;
double avg_latency = latencies_sum / message_count;
printf("\n");
printf("run time: %,ldµs\n", Micros(end_run - start_run));
printf("per second: %,ld\n",
(int64_t)(response_count / (end_run - start_run)));
printf("avg latency: %,ldµs\n", Micros(avg_latency));
printf("response count: %,ld\n", response_count);
printf("fetch count: %,ld\n", fetch_count - failure_count);
printf("error count: %,ld (non-200 responses)\n", error_count);
printf("failure count: %,ld (transport error)\n", failure_count);
printf("wb%s\n", flags);
printf("msgs / second: %,ld qps\n",
(int64_t)(message_count / (end_run - start_run)));
printf("run time: %,ldµs\n", Micros(end_run - start_run));
printf("latency / msgs: %,ldµs\n", Micros(avg_latency));
printf("message count: %,ld\n", message_count);
printf("connect count: %,ld\n", connect_count);
printf("error count: %,ld (non-200 responses)\n", error_count);
printf("failure count: %,ld (transport error)\n", failure_count);
return 0;
}

View file

@ -20,6 +20,7 @@
#include "libc/calls/calls.h"
#include "libc/calls/strace.internal.h"
#include "libc/calls/struct/sigaction.h"
#include "libc/errno.h"
#include "libc/intrin/kprintf.h"
#include "libc/log/countbranch.h"
#include "libc/log/countexpr.h"
@ -29,6 +30,7 @@
#include "libc/runtime/runtime.h"
#include "libc/runtime/stack.h"
#include "libc/runtime/symbols.internal.h"
#include "libc/stdio/stdio.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/map.h"
#include "libc/sysv/consts/o.h"
@ -936,9 +938,12 @@ int Plinko(int argc, char *argv[]) {
if (arch_prctl(ARCH_SET_FS, 0x200000000000) == -1 ||
arch_prctl(ARCH_SET_GS, (intptr_t)DispatchPlan) == -1) {
kprintf("error: %m%nyour operating system doesn't allow you change both "
"the %%fs and %%gs registers in your processor which is a shame "
"since they're crucial for performance and thread-local storage%n");
fputs("error: ", stderr);
fputs(strerror(errno), stderr);
fputs("\nyour operating system doesn't allow you change both "
"the %fs and %gs registers\nin your processor. that's a shame, "
"since they're crucial for performance.\n",
stderr);
exit(1);
}
@ -960,13 +965,16 @@ int Plinko(int argc, char *argv[]) {
(BANE & (BANE | MASK(BANE))) * sizeof(g_mem[0]),
PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED, -1,
0) == MAP_FAILED) {
kprintf("error: %m%nyour operating system doesn't allow you to allocate "
"outrageous amounts of overcommit memory, which is a shame, since "
"the pml4t feature in your processor was intended to give you that "
"power since it's crucial for sparse data applications and lisp. "
"for instance, the way racket works around this problem is by "
"triggering thousands of segmentation faults as part of normal "
"operation%n");
fputs("error: ", stderr);
fputs(strerror(errno), stderr);
fputs("\nyour operating system doesn't allow you to allocate\n"
"outrageous amounts of overcommit memory, which is a shame, since\n"
"the pml4t feature in your processor was intended to give you that\n"
"power since it's crucial for sparse data applications and lisp.\n"
"for instance, the way racket works around this problem is by\n"
"triggering thousands of segmentation faults as part of normal\n"
"operation\n",
stderr);
exit(1);
}

42
tool/viz/fixconsole.c Normal file
View file

@ -0,0 +1,42 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2022 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/dce.h"
#include "libc/intrin/kprintf.h"
#include "libc/nt/console.h"
#include "libc/nt/enum/consolemodeflags.h"
#include "libc/nt/runtime.h"
#include "libc/runtime/runtime.h"
int main(int argc, char *argv[]) {
if (!IsWindows()) {
kprintf("%s is intended for windows%n", argv[0]);
return 1;
}
SetConsoleMode(GetStdHandle(kNtStdInputHandle),
kNtEnableProcessedInput | kNtEnableLineInput |
kNtEnableEchoInput | kNtEnableMouseInput |
kNtEnableInsertMode | kNtEnableQuickEditMode |
kNtEnableExtendedFlags | kNtEnableAutoPosition);
SetConsoleMode(GetStdHandle(kNtStdOutputHandle),
kNtEnableProcessedOutput | kNtEnableWrapAtEolOutput);
SetConsoleMode(GetStdHandle(kNtStdErrorHandle),
kNtEnableProcessedOutput | kNtEnableWrapAtEolOutput |
kNtEnableVirtualTerminalProcessing);
_Exit(0);
}

36
tool/viz/printdos2errno.c Normal file
View file

@ -0,0 +1,36 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2022 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/fmt/fmt.h"
#include "libc/intrin/dos2errno.internal.h"
#include "libc/intrin/kprintf.h"
// note: these are supplementary errno magnum mappings
// don't include the ones in libc/sysv/consts.sh
int main(int argc, char *argv[]) {
int i;
for (i = 0; kDos2Errno[i].doscode; ++i) {
kprintf("dos error %10hu maps to rva %10d errno %10d which is %s%n",
kDos2Errno[i].doscode, kDos2Errno[i].systemv,
*(const int *)((intptr_t)kDos2Errno + kDos2Errno[i].systemv),
strerror_short(
*(const int *)((intptr_t)kDos2Errno + kDos2Errno[i].systemv)));
}
return 0;
}