mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-07-14 15:09:09 +00:00
Make improvements
- Clean up sigaction() code - Add a port scanner example - Introduce a ParseCidr() API - Clean up our futex abstraction code - Fix a harmless integer overflow in ParseIp() - Use kernel semaphores on NetBSD to make threads much faster
This commit is contained in:
parent
539bddce8c
commit
c995838e5c
107 changed files with 1085 additions and 492 deletions
|
@ -51,10 +51,10 @@ int _pthread_cancel_sys(void) {
|
|||
return ecanceled();
|
||||
}
|
||||
|
||||
static void OnSigCancel(int sig, siginfo_t *si, void *ctx) {
|
||||
static void OnSigThr(int sig, siginfo_t *si, void *ctx) {
|
||||
ucontext_t *uc = ctx;
|
||||
struct CosmoTib *tib = __get_tls();
|
||||
struct PosixThread *pt = (struct PosixThread *)tib->tib_pthread;
|
||||
struct CosmoTib *t = __get_tls();
|
||||
struct PosixThread *pt = (struct PosixThread *)t->tib_pthread;
|
||||
if (pt && !(pt->flags & PT_NOCANCEL) &&
|
||||
atomic_load_explicit(&pt->cancelled, memory_order_acquire)) {
|
||||
sigaddset(&uc->uc_sigmask, sig);
|
||||
|
@ -64,15 +64,14 @@ static void OnSigCancel(int sig, siginfo_t *si, void *ctx) {
|
|||
} else if (pt->flags & PT_ASYNC) {
|
||||
pthread_exit(PTHREAD_CANCELED);
|
||||
} else {
|
||||
__tkill(atomic_load_explicit(&tib->tib_tid, memory_order_relaxed), sig,
|
||||
tib);
|
||||
__tkill(atomic_load_explicit(&t->tib_tid, memory_order_relaxed), sig, t);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void ListenForSigCancel(void) {
|
||||
static void ListenForSigThr(void) {
|
||||
struct sigaction sa;
|
||||
sa.sa_sigaction = OnSigCancel;
|
||||
sa.sa_sigaction = OnSigThr;
|
||||
sa.sa_flags = SA_SIGINFO | SA_RESTART | SA_ONSTACK;
|
||||
memset(&sa.sa_mask, -1, sizeof(sa.sa_mask));
|
||||
_npassert(!sigaction(SIGTHR, &sa, 0));
|
||||
|
@ -262,7 +261,7 @@ errno_t pthread_cancel(pthread_t thread) {
|
|||
int e, rc, tid;
|
||||
static bool once;
|
||||
struct PosixThread *pt;
|
||||
if (!once) ListenForSigCancel(), once = true;
|
||||
if (!once) ListenForSigThr(), once = true;
|
||||
pt = (struct PosixThread *)thread;
|
||||
switch (atomic_load_explicit(&pt->status, memory_order_acquire)) {
|
||||
case kPosixThreadZombie:
|
||||
|
|
|
@ -35,13 +35,9 @@
|
|||
* @param value is initial count of semaphore
|
||||
* @return 0 on success, or -1 w/ errno
|
||||
* @raise EINVAL if `value` exceeds `SEM_VALUE_MAX`
|
||||
* @raise EPERM on OpenBSD if `pshared` is true
|
||||
*/
|
||||
int sem_init(sem_t *sem, int pshared, unsigned value) {
|
||||
if (value > SEM_VALUE_MAX) return einval();
|
||||
// OpenBSD MAP_ANONYMOUS|MAP_SHARED memory is kind of busted.
|
||||
// The OpenBSD implementation of sem_init() also EPERMs here.
|
||||
if (IsOpenbsd() && pshared) return eperm();
|
||||
sem->sem_magic = SEM_MAGIC_UNNAMED;
|
||||
atomic_store_explicit(&sem->sem_value, value, memory_order_relaxed);
|
||||
sem->sem_pshared = !!pshared;
|
||||
|
|
|
@ -209,7 +209,7 @@ sem_t *sem_open(const char *name, int oflag, ...) {
|
|||
sem = SEM_FAILED;
|
||||
} else if (~oflag & O_EXCL) {
|
||||
sem = s->sem;
|
||||
atomic_fetch_add_explicit(&sem->sem_prefs, 1, memory_order_acquire);
|
||||
atomic_fetch_add_explicit(&sem->sem_prefs, 1, memory_order_acq_rel);
|
||||
++s->refs;
|
||||
} else {
|
||||
eexist();
|
||||
|
@ -218,7 +218,7 @@ sem_t *sem_open(const char *name, int oflag, ...) {
|
|||
} else if ((s = calloc(1, sizeof(struct Semaphore)))) {
|
||||
if ((s->path = strdup(path))) {
|
||||
if ((sem = sem_open_impl(path, oflag, mode, value)) != SEM_FAILED) {
|
||||
atomic_fetch_add_explicit(&sem->sem_prefs, 1, memory_order_relaxed);
|
||||
atomic_fetch_add_explicit(&sem->sem_prefs, 1, memory_order_acq_rel);
|
||||
s->next = g_semaphores.list;
|
||||
s->sem = sem;
|
||||
s->refs = 1;
|
||||
|
@ -260,7 +260,7 @@ int sem_close(sem_t *sem) {
|
|||
sem_open_init();
|
||||
sem_open_lock();
|
||||
_npassert((s = sem_open_get(sem, &p)));
|
||||
prefs = atomic_fetch_add_explicit(&sem->sem_prefs, -1, memory_order_release);
|
||||
prefs = atomic_fetch_add_explicit(&sem->sem_prefs, -1, memory_order_acq_rel);
|
||||
_npassert(s->refs > 0);
|
||||
if ((unmap = !--s->refs)) {
|
||||
_npassert(prefs > 0);
|
||||
|
|
|
@ -33,26 +33,6 @@ static void sem_delay(int n) {
|
|||
for (i = 0; i != 1 << n; i++) donothing;
|
||||
}
|
||||
|
||||
// TODO(jart): This should be abstracted by polyfill.
|
||||
static struct timespec *sem_timeout(struct timespec *memory,
|
||||
const struct timespec *abstime) {
|
||||
struct timespec now;
|
||||
if (!abstime) {
|
||||
return 0;
|
||||
} else if (FUTEX_TIMEOUT_IS_ABSOLUTE) {
|
||||
*memory = *abstime;
|
||||
return memory;
|
||||
} else {
|
||||
now = timespec_real();
|
||||
if (timespec_cmp(now, *abstime) > 0) {
|
||||
*memory = (struct timespec){0};
|
||||
} else {
|
||||
*memory = timespec_sub(*abstime, now);
|
||||
}
|
||||
return memory;
|
||||
}
|
||||
}
|
||||
|
||||
static void sem_timedwait_cleanup(void *arg) {
|
||||
sem_t *sem = arg;
|
||||
_unassert(atomic_fetch_add_explicit(&sem->sem_waiters, -1,
|
||||
|
@ -95,8 +75,7 @@ int sem_timedwait(sem_t *sem, const struct timespec *abstime) {
|
|||
|
||||
do {
|
||||
if (!(v = atomic_load_explicit(&sem->sem_value, memory_order_relaxed))) {
|
||||
rc = nsync_futex_wait_(&sem->sem_value, v, sem->sem_pshared,
|
||||
sem_timeout(&ts, abstime));
|
||||
rc = nsync_futex_wait_(&sem->sem_value, v, sem->sem_pshared, abstime);
|
||||
if (rc == -EINTR || rc == -ECANCELED) {
|
||||
errno = -rc;
|
||||
rc = -1;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue