mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-06-27 06:48:31 +00:00
Improve threading and i/o routines
- On Windows connect() can now be interrupted by a signal; connect() w/ O_NONBLOCK will now raise EINPROGRESS; and connect() with SO_SNDTIMEO will raise ETIMEDOUT after the interval has elapsed. - We now get the AcceptEx(), ConnectEx(), and TransmitFile() functions from the WIN32 API the officially blessed way, using WSAIoctl(). - Do nothing on Windows when fsync() is called on a directory handle. This was raising EACCES earlier becaues GENERIC_WRITE is required on the handle. It's possible to FlushFileBuffers() a directory handle if it's opened with write access but MSDN doesn't document what it does. If you have any idea, please let us know! - Prefer manual reset event objects for read() and write() on Windows. - Do some code cleanup on our dlmalloc customizations. - Fix errno type error in Windows blocking routines. - Make the futex polyfill simpler and faster.
This commit is contained in:
parent
f7343319cc
commit
49b0eaa69f
43 changed files with 528 additions and 425 deletions
45
third_party/nsync/futex.c
vendored
45
third_party/nsync/futex.c
vendored
|
@ -38,6 +38,7 @@
|
|||
#include "libc/nexgen32e/vendor.internal.h"
|
||||
#include "libc/nt/runtime.h"
|
||||
#include "libc/nt/synchronization.h"
|
||||
#include "libc/runtime/clktck.h"
|
||||
#include "libc/sysv/consts/clock.h"
|
||||
#include "libc/sysv/consts/timer.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
@ -129,46 +130,19 @@ static void nsync_futex_init_ (void) {
|
|||
}
|
||||
|
||||
static int nsync_futex_polyfill_ (atomic_int *w, int expect, struct timespec *abstime) {
|
||||
int rc;
|
||||
int64_t nanos, maxnanos;
|
||||
struct timespec now, wait, remain, deadline;
|
||||
|
||||
if (!abstime) {
|
||||
deadline = timespec_max;
|
||||
} else {
|
||||
deadline = *abstime;
|
||||
}
|
||||
|
||||
nanos = 100;
|
||||
maxnanos = __SIG_LOCK_INTERVAL_MS * 1000L * 1000;
|
||||
for (;;) {
|
||||
if (atomic_load_explicit (w, memory_order_acquire) != expect) {
|
||||
return 0;
|
||||
}
|
||||
now = timespec_real ();
|
||||
if (atomic_load_explicit (w, memory_order_acquire) != expect) {
|
||||
return 0;
|
||||
if (_weaken (pthread_testcancel_np) &&
|
||||
_weaken (pthread_testcancel_np) ()) {
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
if (timespec_cmp (now, deadline) >= 0) {
|
||||
break;
|
||||
}
|
||||
wait = timespec_fromnanos (nanos);
|
||||
remain = timespec_sub (deadline, now);
|
||||
if (timespec_cmp(wait, remain) > 0) {
|
||||
wait = remain;
|
||||
}
|
||||
if ((rc = clock_nanosleep (CLOCK_REALTIME, 0, &wait, 0))) {
|
||||
return -rc;
|
||||
}
|
||||
if (nanos < maxnanos) {
|
||||
nanos <<= 1;
|
||||
if (nanos > maxnanos) {
|
||||
nanos = maxnanos;
|
||||
}
|
||||
if (abstime && timespec_cmp (timespec_real (), *abstime) >= 0) {
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
pthread_yield ();
|
||||
}
|
||||
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
static int nsync_futex_wait_win32_ (atomic_int *w, int expect, char pshare,
|
||||
|
@ -189,7 +163,7 @@ static int nsync_futex_wait_win32_ (atomic_int *w, int expect, char pshare,
|
|||
return etimedout();
|
||||
}
|
||||
remain = timespec_sub (deadline, now);
|
||||
interval = timespec_frommillis (__SIG_LOCK_INTERVAL_MS);
|
||||
interval = timespec_frommillis (5000);
|
||||
wait = timespec_cmp (remain, interval) > 0 ? interval : remain;
|
||||
if (atomic_load_explicit (w, memory_order_acquire) != expect) {
|
||||
return 0;
|
||||
|
@ -274,7 +248,7 @@ int nsync_futex_wait_ (atomic_int *w, int expect, char pshare, const struct time
|
|||
us = -1u;
|
||||
}
|
||||
rc = ulock_wait (op, w, expect, us);
|
||||
if (rc > 0) rc = 0; // TODO(jart): What does it mean?
|
||||
if (rc > 0) rc = 0; // don't care about #waiters
|
||||
} else if (IsFreebsd ()) {
|
||||
rc = sys_umtx_timedwait_uint (w, expect, pshare, timeout);
|
||||
} else {
|
||||
|
@ -356,6 +330,7 @@ int nsync_futex_wake_ (atomic_int *w, int count, char pshare) {
|
|||
op |= ULF_WAKE_ALL;
|
||||
}
|
||||
rc = ulock_wake (op, w, 0);
|
||||
ASSERT (!rc || rc == -ENOENT);
|
||||
if (!rc) {
|
||||
rc = 1;
|
||||
} else if (rc == -ENOENT) {
|
||||
|
|
2
third_party/nsync/mu_semaphore.c
vendored
2
third_party/nsync/mu_semaphore.c
vendored
|
@ -23,7 +23,7 @@
|
|||
/* Apple's ulock (part by Cosmo futexes) is an internal API, but:
|
||||
1. Unlike GCD it's cancellable, i.e. can be EINTR'd by signals
|
||||
2. We currently always use ulock anyway for joining threads */
|
||||
#define PREFER_GCD_OVER_ULOCK 0
|
||||
#define PREFER_GCD_OVER_ULOCK 1
|
||||
|
||||
asm(".ident\t\"\\n\\n\
|
||||
*NSYNC (Apache 2.0)\\n\
|
||||
|
|
4
third_party/nsync/mu_semaphore_gcd.c
vendored
4
third_party/nsync/mu_semaphore_gcd.c
vendored
|
@ -20,6 +20,7 @@
|
|||
#include "libc/errno.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/intrin/weaken.h"
|
||||
#include "libc/runtime/clktck.h"
|
||||
#include "libc/runtime/syslib.internal.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/thread/posixthread.internal.h"
|
||||
|
@ -116,8 +117,7 @@ errno_t nsync_mu_semaphore_p_with_deadline_gcd (nsync_semaphore *s,
|
|||
(pt->pt_flags & PT_NOCANCEL)) {
|
||||
result = nsync_dispatch_semaphore_wait (s, abs_deadline);
|
||||
} else {
|
||||
struct timespec now, until, slice;
|
||||
slice = timespec_frommillis (__SIG_LOCK_INTERVAL_MS);
|
||||
struct timespec now, until, slice = {0, 1000000000 / CLK_TCK};
|
||||
for (;;) {
|
||||
if (_weaken (pthread_testcancel_np) () == ECANCELED) {
|
||||
result = ECANCELED;
|
||||
|
|
11
third_party/nsync/panic.c
vendored
11
third_party/nsync/panic.c
vendored
|
@ -17,12 +17,17 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/intrin/describebacktrace.internal.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "third_party/nsync/common.internal.h"
|
||||
// clang-format off
|
||||
|
||||
/* Aborts after printing the nul-terminated string s[]. */
|
||||
void nsync_panic_ (const char *s) {
|
||||
tinyprint (2, "nsync panic: ", s, NULL);
|
||||
notpossible;
|
||||
tinyprint(2, "error: nsync panic: ", s, "\n",
|
||||
"cosmoaddr2line ", program_invocation_name, " ",
|
||||
DescribeBacktrace (__builtin_frame_address (0)), "\n",
|
||||
NULL);
|
||||
_Exit (44);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue