mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-07-30 14:30:27 +00:00
Improve threading support further
This commit is contained in:
parent
8bfb70ca3f
commit
ce71677156
61 changed files with 882 additions and 747 deletions
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue