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

@ -16,52 +16,47 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/assert.h"
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/struct/sigset.internal.h"
#include "libc/errno.h"
#include "libc/intrin/atomic.h"
#include "libc/nt/enum/wait.h"
#include "libc/nt/runtime.h"
#include "libc/nt/synchronization.h"
#include "libc/sysv/errfuns.h"
#include "libc/thread/posixthread.internal.h"
#include "libc/thread/thread.h"
#include "libc/thread/tls.h"
#ifdef __x86_64__
// each thread has its own pt_futex which is used by both posix signals
// and posix thread cancelation to "park" blocking operations that dont
// need win32 overlapped i/o. the delay is advisory and may be -1 which
// means wait forever. these functions don't guarantee to wait the full
// duration. other threads wanting to deliver a signal, can wake parked
// futexes without releasing them, just to stir up activity. if a futex
// is both woken and released then the cancelation point shall generate
// an eintr. we also abstract checking for signals & thread cancelation
static textwindows int _park_wait(uint32_t msdelay, bool restartable,
struct PosixThread *pt) {
int got, expect = 0;
if (_check_cancel() == -1) return -1;
if (_check_signal(restartable) == -1) return -1;
WaitOnAddress(&pt->pt_futex, &expect, sizeof(expect), msdelay);
got = atomic_load_explicit(&pt->pt_futex, memory_order_acquire);
return got != expect ? eintr() : 0;
}
static textwindows int _park_thread(uint32_t msdelay, sigset_t waitmask,
bool restartable) {
int rc;
int64_t sem;
sigset_t om;
uint32_t wi;
struct PosixThread *pt;
pt = _pthread_self();
pt->pt_flags &= ~PT_RESTARTABLE;
if (restartable) pt->pt_flags |= PT_RESTARTABLE;
atomic_store_explicit(&pt->pt_futex, 0, memory_order_release);
atomic_store_explicit(&pt->pt_blocker, &pt->pt_futex, memory_order_release);
pt->pt_semaphore = sem = CreateSemaphore(0, 0, 1, 0);
pthread_cleanup_push((void *)CloseHandle, (void *)sem);
atomic_store_explicit(&pt->pt_blocker, PT_BLOCKER_SEM, memory_order_release);
om = __sig_beginwait(waitmask);
rc = _park_wait(msdelay, restartable, pt);
if (rc == -1 && errno == EINTR) _check_cancel();
if ((rc = _check_cancel()) != -1 && (rc = _check_signal(restartable)) != -1) {
unassert((wi = WaitForSingleObject(sem, msdelay)) != -1u);
if (wi != kNtWaitTimeout) {
rc = eintr();
_check_cancel();
}
}
__sig_finishwait(om);
atomic_store_explicit(&pt->pt_blocker, PT_BLOCKER_CPU, memory_order_release);
pt->pt_flags &= ~PT_RESTARTABLE;
pthread_cleanup_pop(true);
pt->pt_semaphore = 0;
return rc;
}