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:
Justine Tunney 2022-11-07 02:22:09 -08:00
parent 539bddce8c
commit c995838e5c
No known key found for this signature in database
GPG key ID: BE714B4575D6E328
107 changed files with 1085 additions and 492 deletions

View file

@ -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:

View file

@ -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;

View file

@ -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);

View file

@ -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;