Make some more fixes

This change deletes mkfifo() so that GNU Make on Windows will work in
parallel mode using its pipe-based implementation. There's an example
called greenbean2 now, which shows how to build a scalable web server
for Windows with 10k+ threads. The accuracy of clock_nanosleep is now
significantly improved on Linux.
This commit is contained in:
Justine Tunney 2023-10-09 11:56:21 -07:00
parent 820c3599ed
commit 3b4dbc9fdd
No known key found for this signature in database
GPG key ID: BE714B4575D6E328
22 changed files with 870 additions and 330 deletions

View file

@ -4,7 +4,7 @@
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
#define nsync_atomic_uint32_ atomic_uint_fast32_t
#define nsync_atomic_uint32_ atomic_uint
#define NSYNC_ATOMIC_UINT32_INIT_ 0
#define NSYNC_ATOMIC_UINT32_LOAD_(p) (*(p))

View file

@ -37,6 +37,8 @@ void nsync_mu_semaphore_init (nsync_semaphore *s) {
return nsync_mu_semaphore_init_gcd (s);
} else if (IsNetbsd ()) {
return nsync_mu_semaphore_init_sem (s);
} else if (IsWindows ()) {
return nsync_mu_semaphore_init_win32 (s);
} else {
return nsync_mu_semaphore_init_futex (s);
}
@ -48,6 +50,8 @@ void nsync_mu_semaphore_destroy (nsync_semaphore *s) {
return nsync_mu_semaphore_destroy_gcd (s);
} else if (IsNetbsd ()) {
return nsync_mu_semaphore_destroy_sem (s);
} else if (IsWindows ()) {
return nsync_mu_semaphore_destroy_win32 (s);
}
}
@ -62,6 +66,8 @@ errno_t nsync_mu_semaphore_p (nsync_semaphore *s) {
err = nsync_mu_semaphore_p_gcd (s);
} else if (IsNetbsd ()) {
err = nsync_mu_semaphore_p_sem (s);
} else if (IsWindows ()) {
err = nsync_mu_semaphore_p_win32 (s);
} else {
err = nsync_mu_semaphore_p_futex (s);
}
@ -80,6 +86,8 @@ errno_t nsync_mu_semaphore_p_with_deadline (nsync_semaphore *s, nsync_time abs_d
err = nsync_mu_semaphore_p_with_deadline_gcd (s, abs_deadline);
} else if (IsNetbsd ()) {
err = nsync_mu_semaphore_p_with_deadline_sem (s, abs_deadline);
} else if (IsWindows ()) {
err = nsync_mu_semaphore_p_with_deadline_win32 (s, abs_deadline);
} else {
err = nsync_mu_semaphore_p_with_deadline_futex (s, abs_deadline);
}
@ -93,6 +101,8 @@ void nsync_mu_semaphore_v (nsync_semaphore *s) {
return nsync_mu_semaphore_v_gcd (s);
} else if (IsNetbsd ()) {
return nsync_mu_semaphore_v_sem (s);
} else if (IsWindows ()) {
return nsync_mu_semaphore_v_win32 (s);
} else {
return nsync_mu_semaphore_v_futex (s);
}

View file

@ -22,6 +22,12 @@ errno_t nsync_mu_semaphore_p_gcd(nsync_semaphore *);
errno_t nsync_mu_semaphore_p_with_deadline_gcd(nsync_semaphore *, nsync_time);
void nsync_mu_semaphore_v_gcd(nsync_semaphore *);
void nsync_mu_semaphore_init_win32(nsync_semaphore *);
void nsync_mu_semaphore_destroy_win32(nsync_semaphore *);
errno_t nsync_mu_semaphore_p_win32(nsync_semaphore *);
errno_t nsync_mu_semaphore_p_with_deadline_win32(nsync_semaphore *, nsync_time);
void nsync_mu_semaphore_v_win32(nsync_semaphore *);
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_THIRD_PARTY_NSYNC_MU_SEMAPHORE_INTERNAL_H_ */

140
third_party/nsync/mu_semaphore_win32.c vendored Normal file
View file

@ -0,0 +1,140 @@
/*-*- mode:c;indent-tabs-mode:t;c-basic-offset:8;tab-width:8;coding:utf-8 -*-│
vi: set et ft=c ts=8 tw=8 fenc=utf-8 :vi
Copyright 2016 Google Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0 │
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#include "libc/calls/internal.h"
#include "libc/calls/state.internal.h"
#include "libc/errno.h"
#include "libc/nt/enum/wait.h"
#include "libc/nt/runtime.h"
#include "libc/nt/synchronization.h"
#include "libc/runtime/runtime.h"
#include "libc/thread/posixthread.internal.h"
#include "third_party/nsync/mu_semaphore.h"
#include "third_party/nsync/mu_semaphore.internal.h"
#include "third_party/nsync/time.h"
#ifdef __x86_64__
asm(".ident\t\"\\n\\n\
*NSYNC (Apache 2.0)\\n\
Copyright 2016 Google, Inc.\\n\
https://github.com/google/nsync\"");
// clang-format off
/* Initialize *s; the initial value is 0. */
textwindows void nsync_mu_semaphore_init_win32 (nsync_semaphore *s) {
int64_t *h = (int64_t *) s;
*h = CreateSemaphore (&kNtIsInheritable, 0, 1, NULL);
if (!*h) notpossible;
}
/* Releases system resources associated with *s. */
textwindows void nsync_mu_semaphore_destroy_win32 (nsync_semaphore *s) {
int64_t *h = (int64_t *) s;
CloseHandle (*h);
}
/* Wait until the count of *s exceeds 0, and decrement it. */
textwindows errno_t nsync_mu_semaphore_p_win32 (nsync_semaphore *s) {
errno_t err = 0;
int64_t *h = (int64_t *) s;
struct PosixThread *pt = _pthread_self ();
if (pt) {
pt->pt_semaphore = *h;
pt->pt_flags &= ~PT_RESTARTABLE;
atomic_store_explicit (&pt->pt_blocker, PT_BLOCKER_SEM, memory_order_release);
}
if (_check_cancel() != -1) {
WaitForSingleObject (*h, -1u);
if (_check_cancel()) {
err = ECANCELED;
}
} else {
err = ECANCELED;
}
if (pt) {
atomic_store_explicit (&pt->pt_blocker, PT_BLOCKER_CPU, memory_order_release);
pt->pt_semaphore = 0;
}
return err;
}
/* Wait until one of:
the count of *s is non-zero, in which case decrement *s and return 0;
or abs_deadline expires, in which case return ETIMEDOUT. */
textwindows int nsync_mu_semaphore_p_with_deadline_win32 (nsync_semaphore *s, nsync_time abs_deadline) {
int result;
int64_t *h = (int64_t *) s;
struct PosixThread *pt = _pthread_self ();
if (nsync_time_cmp (abs_deadline, nsync_time_no_deadline) == 0) {
if (!nsync_mu_semaphore_p_win32 (s)) {
return 0;
} else {
return ECANCELED;
}
} else {
nsync_time now;
now = nsync_time_now ();
do {
if (nsync_time_cmp (abs_deadline, now) <= 0) {
result = WaitForSingleObject (*h, 0);
} else {
errno_t err = 0;
nsync_time delay;
delay = nsync_time_sub (abs_deadline, now);
if (pt) {
pt->pt_semaphore = *h;
pt->pt_flags &= ~PT_RESTARTABLE;
atomic_store_explicit (&pt->pt_blocker, PT_BLOCKER_SEM, memory_order_release);
}
if (_check_cancel() != -1) {
if (NSYNC_TIME_SEC (delay) > 1000*1000) {
result = WaitForSingleObject (*h, 1000*1000);
} else {
result = WaitForSingleObject (*h,
(unsigned) (NSYNC_TIME_SEC (delay) * 1000 +
(NSYNC_TIME_NSEC (delay) + 999999) / (1000 * 1000)));
}
if (_check_cancel()) {
err = ECANCELED;
}
} else {
err = ECANCELED;
}
if (pt) {
atomic_store_explicit (&pt->pt_blocker, PT_BLOCKER_CPU, memory_order_release);
pt->pt_semaphore = 0;
}
if (err) {
return err;
}
}
if (result == kNtWaitTimeout) {
now = nsync_time_now ();
}
} while (result == kNtWaitTimeout && /* Windows generates early wakeups. */
nsync_time_cmp (abs_deadline, now) > 0);
}
return (result == kNtWaitTimeout ? ETIMEDOUT : 0);
}
/* Ensure that the count of *s is at least 1. */
textwindows void nsync_mu_semaphore_v_win32 (nsync_semaphore *s) {
int64_t *h = (int64_t *) s;
ReleaseSemaphore(*h, 1, NULL);
}
#endif /* __x86_64__ */