Improve threading support further

This commit is contained in:
Justine Tunney 2022-05-17 04:14:28 -07:00
parent 8bfb70ca3f
commit ce71677156
61 changed files with 882 additions and 747 deletions

View file

@ -20,6 +20,8 @@
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/strace.internal.h"
#include "libc/intrin/kprintf.h"
#include "libc/intrin/spinlock.h"
#include "libc/macros.internal.h"
#include "libc/sock/internal.h"
#include "libc/sysv/errfuns.h"
@ -46,6 +48,7 @@
*/
int close(int fd) {
int rc;
_spinlock(&__fds_lock);
if (fd == -1) {
rc = 0;
} else if (fd < 0) {
@ -74,9 +77,10 @@ int close(int fd) {
}
}
if (!__vforked) {
__releasefd(fd);
__releasefd_unlocked(fd);
}
}
_spunlock(&__fds_lock);
STRACE("%s(%d) → %d% m", "close", fd, rc);
return rc;
}

View file

@ -20,6 +20,7 @@
#include "libc/bits/weaken.h"
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/intrin/spinlock.h"
#include "libc/mem/mem.h"
#include "libc/nt/files.h"
#include "libc/nt/runtime.h"
@ -32,25 +33,37 @@
* Implements dup(), dup2(), dup3(), and F_DUPFD for Windows.
*/
textwindows int sys_dup_nt(int oldfd, int newfd, int flags, int start) {
int64_t proc, handle;
int64_t rc, proc, handle;
// validate the api usage
if (oldfd < 0) return einval();
if (flags & ~O_CLOEXEC) return einval();
_spinlock(&__fds_lock);
if (oldfd >= g_fds.n ||
(g_fds.p[oldfd].kind != kFdFile && g_fds.p[oldfd].kind != kFdSocket &&
g_fds.p[oldfd].kind != kFdConsole)) {
_spunlock(&__fds_lock);
return ebadf();
}
// allocate a new file descriptor
if (newfd == -1) {
if ((newfd = __reservefd(start)) == -1) {
if ((newfd = __reservefd_unlocked(start)) == -1) {
_spunlock(&__fds_lock);
return -1;
}
} else {
if (__ensurefds(newfd) == -1) return -1;
if (g_fds.p[newfd].kind) close(newfd);
if (__ensurefds_unlocked(newfd) == -1) {
_spunlock(&__fds_lock);
return -1;
}
if (g_fds.p[newfd].kind) {
_spunlock(&__fds_lock);
close(newfd);
_spinlock(&__fds_lock);
}
g_fds.p[newfd].kind = kFdReserved;
}
@ -80,9 +93,12 @@ textwindows int sys_dup_nt(int oldfd, int newfd, int flags, int start) {
if (g_fds.p[oldfd].worker) {
g_fds.p[newfd].worker = weaken(RefNtStdinWorker)(g_fds.p[oldfd].worker);
}
return newfd;
rc = newfd;
} else {
__releasefd(newfd);
return __winerr();
rc = __winerr();
}
_spunlock(&__fds_lock);
return rc;
}

View file

@ -18,6 +18,6 @@
*/
#include "libc/calls/internal.h"
_Alignas(64) char __sig_lock;
_Alignas(64) int __sig_lock;
unsigned __sighandrvas[NSIG];
unsigned __sighandflags[NSIG];

View file

@ -76,8 +76,8 @@ struct Fds {
extern const struct Fd kEmptyFd;
hidden extern int __vforked;
hidden extern char __fds_lock;
hidden extern char __sig_lock;
hidden extern int __fds_lock;
hidden extern int __sig_lock;
hidden extern bool __time_critical;
hidden extern unsigned __sighandrvas[NSIG];
hidden extern unsigned __sighandflags[NSIG];
@ -85,8 +85,11 @@ hidden extern struct Fds g_fds;
hidden extern const struct NtSecurityAttributes kNtIsInheritable;
int __reservefd(int) hidden;
int __reservefd_unlocked(int) hidden;
void __releasefd(int) hidden;
void __releasefd_unlocked(int) hidden;
int __ensurefds(int) hidden;
int __ensurefds_unlocked(int) hidden;
int64_t __getfdhandleactual(int) hidden;
void __printfds(void) hidden;

View file

@ -23,11 +23,16 @@
#include "libc/calls/strace.internal.h"
#include "libc/calls/struct/sigaction.h"
#include "libc/dce.h"
#include "libc/intrin/spinlock.h"
textwindows bool _check_interrupts(bool restartable, struct Fd *fd) {
bool res;
if (__time_critical) return false;
if (_trylock(&__fds_lock)) return false;
if (weaken(_check_sigalrm)) weaken(_check_sigalrm)();
if (weaken(_check_sigchld)) weaken(_check_sigchld)();
if (fd && weaken(_check_sigwinch)) weaken(_check_sigwinch)(fd);
return weaken(__sig_check) && weaken(__sig_check)(restartable);
res = weaken(__sig_check) && weaken(__sig_check)(restartable);
_spunlock(&__fds_lock);
return res;
}

View file

@ -20,6 +20,7 @@
#include "libc/calls/internal.h"
#include "libc/calls/ntmagicpaths.internal.h"
#include "libc/calls/strace.internal.h"
#include "libc/intrin/spinlock.h"
#include "libc/nt/createfile.h"
#include "libc/nt/enum/accessmask.h"
#include "libc/nt/enum/creationdisposition.h"
@ -87,14 +88,17 @@ textwindows ssize_t sys_open_nt(int dirfd, const char *file, uint32_t flags,
int32_t mode) {
int fd;
ssize_t rc;
if ((fd = __reservefd(-1)) == -1) return -1;
if ((flags & O_ACCMODE) == O_RDWR && !strcmp(file, kNtMagicPaths.devtty)) {
rc = sys_open_nt_console(dirfd, &kNtMagicPaths, flags, mode, fd);
} else {
rc = sys_open_nt_file(dirfd, file, flags, mode, fd);
}
if (rc == -1) {
__releasefd(fd);
_spinlock(&__fds_lock);
if ((rc = fd = __reservefd_unlocked(-1)) != -1) {
if ((flags & O_ACCMODE) == O_RDWR && !strcmp(file, kNtMagicPaths.devtty)) {
rc = sys_open_nt_console(dirfd, &kNtMagicPaths, flags, mode, fd);
} else {
rc = sys_open_nt_file(dirfd, file, flags, mode, fd);
}
if (rc == -1) {
__releasefd_unlocked(fd);
}
_spunlock(&__fds_lock);
}
return rc;
}

View file

@ -17,6 +17,7 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/internal.h"
#include "libc/intrin/spinlock.h"
#include "libc/nt/createfile.h"
#include "libc/nt/enum/accessmask.h"
#include "libc/nt/enum/creationdisposition.h"
@ -33,9 +34,14 @@ textwindows int sys_pipe_nt(int pipefd[2], unsigned flags) {
int reader, writer;
char16_t pipename[64];
CreatePipeName(pipename);
if ((reader = __reservefd(-1)) == -1) return -1;
if ((writer = __reservefd(-1)) == -1) {
__releasefd(reader);
_spinlock(&__fds_lock);
if ((reader = __reservefd_unlocked(-1)) == -1) {
_spunlock(&__fds_lock);
return -1;
}
if ((writer = __reservefd_unlocked(-1)) == -1) {
__releasefd_unlocked(reader);
_spunlock(&__fds_lock);
return -1;
}
if (~flags & O_DIRECT) {
@ -58,12 +64,14 @@ textwindows int sys_pipe_nt(int pipefd[2], unsigned flags) {
g_fds.p[writer].handle = hout;
pipefd[0] = reader;
pipefd[1] = writer;
_spunlock(&__fds_lock);
return 0;
} else {
CloseHandle(hin);
}
}
__releasefd(writer);
__releasefd(reader);
__releasefd_unlocked(writer);
__releasefd_unlocked(reader);
_spunlock(&__fds_lock);
return -1;
}

View file

@ -44,7 +44,7 @@
#include "libc/sysv/consts/sig.h"
#include "libc/sysv/errfuns.h"
_Alignas(64) static char poll_lock;
_Alignas(64) static int poll_lock;
/**
* Polls on the New Technology.

View file

@ -32,10 +32,9 @@
/**
* Grows file descriptor array memory if needed.
*/
int __ensurefds(int fd) {
int __ensurefds_unlocked(int fd) {
size_t n1, n2;
struct Fd *p1, *p2;
_spinlock(&__fds_lock);
n1 = g_fds.n;
if (fd >= n1) {
STRACE("__ensurefds(%d) extending", fd);
@ -48,7 +47,7 @@ int __ensurefds(int fd) {
g_fds.p = p2;
g_fds.n = n2;
if (p1 != g_fds.__init_p) {
weaken(free)(p1);
__cxa_atexit(free, p1, 0);
}
} else {
fd = enomem();
@ -57,32 +56,44 @@ int __ensurefds(int fd) {
fd = emfile();
}
}
return fd;
}
/**
* Grows file descriptor array memory if needed.
*/
int __ensurefds(int fd) {
_spinlock(&__fds_lock);
fd = __ensurefds_unlocked(fd);
_spunlock(&__fds_lock);
return fd;
}
/**
* Finds open file descriptor slot.
*/
int __reservefd_unlocked(int start) {
int fd;
for (fd = g_fds.f; fd < g_fds.n; ++fd) {
if (!g_fds.p[fd].kind) {
break;
}
}
fd = __ensurefds_unlocked(fd);
bzero(g_fds.p + fd, sizeof(*g_fds.p));
g_fds.p[fd].kind = kFdReserved;
return fd;
}
/**
* Finds open file descriptor slot.
*/
int __reservefd(int start) {
int fd;
for (;;) {
_spinlock(&__fds_lock);
fd = start < 0 ? g_fds.f : start;
while (fd < g_fds.n && g_fds.p[fd].kind) ++fd;
if (fd < g_fds.n) {
g_fds.f = fd + 1;
bzero(g_fds.p + fd, sizeof(*g_fds.p));
g_fds.p[fd].kind = kFdReserved;
_spunlock(&__fds_lock);
return fd;
} else {
_spunlock(&__fds_lock);
if (__ensurefds(fd) == -1) {
return -1;
}
}
}
_spinlock(&__fds_lock);
fd = __reservefd_unlocked(start);
_spunlock(&__fds_lock);
return fd;
}
/**
@ -91,9 +102,12 @@ int __reservefd(int start) {
static void FreeFds(void) {
int i;
NTTRACE("FreeFds()");
_spinlock(&__fds_lock);
for (i = 3; i < g_fds.n; ++i) {
if (g_fds.p[i].kind) {
_spunlock(&__fds_lock);
close(i);
_spinlock(&__fds_lock);
}
}
if (g_fds.p != g_fds.__init_p) {
@ -102,6 +116,7 @@ static void FreeFds(void) {
g_fds.p = g_fds.__init_p;
g_fds.n = ARRAYLEN(g_fds.__init_p);
}
_spunlock(&__fds_lock);
}
static textstartup void FreeFdsInit(void) {

View file

@ -223,7 +223,6 @@ static int __sigaction(int sig, const struct sigaction *act,
rc = 0;
}
if (rc != -1 && !__vforked) {
_spinlock(&__sig_lock);
if (oldact) {
oldrva = __sighandrvas[sig];
oldact->sa_sigaction = (sigaction_f)(
@ -233,7 +232,6 @@ static int __sigaction(int sig, const struct sigaction *act,
__sighandrvas[sig] = rva;
__sighandflags[sig] = act->sa_flags;
}
_spunlock(&__sig_lock);
}
return rc;
}
@ -447,7 +445,9 @@ int sigaction(int sig, const struct sigaction *act, struct sigaction *oldact) {
if (sig == SIGKILL || sig == SIGSTOP) {
rc = einval();
} else {
_spinlock(&__sig_lock);
rc = __sigaction(sig, act, oldact);
_spunlock(&__sig_lock);
}
STRACE("sigaction(%G, %s, [%s]) → %d% m", sig,
DescribeSigaction(buf[0], sizeof(buf[0]), 0, act),

View file

@ -53,7 +53,7 @@ void _check_sigchld(void) {
if (__sighandflags[SIGCHLD] & SA_NOCLDWAIT) {
STRACE("SIGCHILD SA_NOCLDWAIT fd=%d handle=%ld", pids[i], handles[i]);
CloseHandle(handles[i]);
__releasefd(pids[i]);
__releasefd_unlocked(pids[i]);
}
g_fds.p[pids[i]].zombie = true;
__sig_add(SIGCHLD, CLD_EXITED);

View file

@ -25,6 +25,7 @@
#include "libc/calls/struct/rusage.h"
#include "libc/fmt/conv.h"
#include "libc/intrin/kprintf.h"
#include "libc/intrin/spinlock.h"
#include "libc/macros.internal.h"
#include "libc/nt/accounting.h"
#include "libc/nt/enum/accessmask.h"
@ -57,6 +58,7 @@ static textwindows int sys_wait4_nt_impl(int pid, int *opt_out_wstatus,
struct NtProcessMemoryCountersEx memcount;
struct NtFileTime createfiletime, exitfiletime, kernelfiletime, userfiletime;
if (_check_interrupts(true, g_fds.p)) return eintr();
_spinlock(&__fds_lock);
if (pid != -1 && pid != 0) {
if (pid < 0) {
/* XXX: this is sloppy */
@ -67,15 +69,17 @@ static textwindows int sys_wait4_nt_impl(int pid, int *opt_out_wstatus,
if (!__isfdopen(pid) &&
(handle = OpenProcess(kNtSynchronize | kNtProcessQueryInformation,
true, pid))) {
if ((pid = __reservefd(-1)) != -1) {
if ((pid = __reservefd_unlocked(-1)) != -1) {
g_fds.p[pid].kind = kFdProcess;
g_fds.p[pid].handle = handle;
g_fds.p[pid].flags = O_CLOEXEC;
} else {
_spunlock(&__fds_lock);
CloseHandle(handle);
return echild();
}
} else {
_spunlock(&__fds_lock);
return echild();
}
}
@ -84,8 +88,12 @@ static textwindows int sys_wait4_nt_impl(int pid, int *opt_out_wstatus,
count = 1;
} else {
count = __sample_pids(pids, handles, false);
if (!count) return echild();
if (!count) {
_spunlock(&__fds_lock);
return echild();
}
}
_spunlock(&__fds_lock);
for (;;) {
if (_check_interrupts(true, 0)) return eintr();
dwExitCode = kNtStillActive;