The new files should have the ISC/OpenBSD license inserted at the top. IMHO, the ticket changes are a separate diff and you will be able to commit that part first.
Also, replacing struct _spinlock with int is also a separate diff. Those changes don't clash with futexes, so less chance of being reverted. Thanks On Fri, Sep 2, 2016 at 8:36 AM, Michal Mazurek <akf...@jasminek.net> wrote: > Here is a working futex implementation for OpenBSD. This diff touches > the kernel and librthread. > > * get rid of tickets from rthreads, they were getting in the way and are > unused anyway > * replace all struct _spinlock with int > * use futexes instead of spinlocks everywhere within librthread > * librthread no longer calls sched_yield(), nor does it spin > > Any comments? > > Index: lib/librthread/Makefile > =================================================================== > RCS file: /cvs/src/lib/librthread/Makefile,v > retrieving revision 1.43 > diff -u -p -r1.43 Makefile > --- lib/librthread/Makefile 1 Jun 2016 04:34:18 -0000 1.43 > +++ lib/librthread/Makefile 2 Sep 2016 13:09:44 -0000 > @@ -18,7 +18,8 @@ CFLAGS+=-DNO_PIC > VERSION_SCRIPT= ${.CURDIR}/Symbols.map > > .PATH: ${.CURDIR}/arch/${MACHINE_CPU} > -SRCS= rthread.c \ > +SRCS= futex.c \ > + rthread.c \ > rthread_attr.c \ > rthread_barrier.c \ > rthread_barrier_attr.c \ > Index: lib/librthread/futex.c > =================================================================== > RCS file: lib/librthread/futex.c > diff -N lib/librthread/futex.c > --- /dev/null 1 Jan 1970 00:00:00 -0000 > +++ lib/librthread/futex.c 2 Sep 2016 13:09:44 -0000 > @@ -0,0 +1,41 @@ > +#include <sys/futex.h> > + > +#include <pthread.h> > +#include "thread_private.h" > +#include "rthread.h" > + > +inline int > +futex_lock(volatile int *val) > +{ > + int c; > + > + if ((c = __sync_val_compare_and_swap(val, 0, 1)) != 0) { > + do { > + if (c == 2 || __sync_val_compare_and_swap(val, 1, > 2) != 0) { > + futex(val, FUTEX_WAIT, 2, NULL, NULL, 0); > + } > + } while ((c = __sync_val_compare_and_swap(val, 0, 2)) != > 0); > + } > + > + return 0; > +} > + > +inline int > +futex_trylock(volatile int *val) > +{ > + if ((__sync_val_compare_and_swap(val, 0, 1)) != 0) > + return 1; > + > + return 0; > +} > + > +inline int > +futex_unlock(volatile int *val) > +{ > + if (__sync_sub_and_fetch(val, 1) != 0) { > + *val = 0; > + futex(val, FUTEX_WAKE, 1, NULL, NULL, 0); > + } > + > + return 0; > +} > Index: lib/librthread/rthread.c > =================================================================== > RCS file: /cvs/src/lib/librthread/rthread.c,v > retrieving revision 1.92 > diff -u -p -r1.92 rthread.c > --- lib/librthread/rthread.c 1 Sep 2016 10:41:02 -0000 1.92 > +++ lib/librthread/rthread.c 2 Sep 2016 13:09:44 -0000 > @@ -63,15 +63,15 @@ REDIRECT_SYSCALL(thrkill); > > static int concurrency_level; /* not used */ > > -struct _spinlock _SPINLOCK_UNLOCKED_ASSIGN = _SPINLOCK_UNLOCKED; > +int _SPINLOCK_UNLOCKED_ASSIGN = _SPINLOCK_UNLOCKED; > > int _threads_ready; > size_t _thread_pagesize; > struct listhead _thread_list = LIST_HEAD_INITIALIZER(_thread_list); > -struct _spinlock _thread_lock = _SPINLOCK_UNLOCKED; > +int _thread_lock = 0; > static struct pthread_queue _thread_gc_list > = TAILQ_HEAD_INITIALIZER(_thread_gc_list); > -static struct _spinlock _thread_gc_lock = _SPINLOCK_UNLOCKED; > +int _thread_gc_lock = 0; > static struct pthread _initial_thread; > > struct pthread_attr _rthread_attr_default = { > @@ -88,23 +88,22 @@ struct pthread_attr _rthread_attr_defaul > /* > * internal support functions > */ > -void > -_spinlock(volatile struct _spinlock *lock) > +inline void > +_spinlock(volatile int *lock) > { > - while (_atomic_lock(&lock->ticket)) > - sched_yield(); > + futex_lock(lock); > } > > -int > -_spinlocktry(volatile struct _spinlock *lock) > +inline int > +_spinlocktry(volatile int *lock) > { > - return 0 == _atomic_lock(&lock->ticket); > + return 0 == futex_trylock(lock); > } > > -void > -_spinunlock(volatile struct _spinlock *lock) > +inline void > +_spinunlock(volatile int *lock) > { > - lock->ticket = _ATOMIC_LOCK_UNLOCKED; > + futex_unlock(lock); > } > > static void > @@ -643,7 +642,7 @@ _thread_dump_info(void) > void > _rthread_dl_lock(int what) > { > - static struct _spinlock lock = _SPINLOCK_UNLOCKED; > + static int lock = _SPINLOCK_UNLOCKED; > static pthread_t owner = NULL; > static struct pthread_queue lockers = > TAILQ_HEAD_INITIALIZER(lockers); > static int count = 0; > @@ -658,8 +657,7 @@ _rthread_dl_lock(int what) > } else if (owner != self) { > TAILQ_INSERT_TAIL(&lockers, self, waiting); > while (owner != self) { > - __thrsleep(self, 0 | _USING_TICKETS, NULL, > - &lock.ticket, NULL); > + __thrsleep(self, 0, NULL, &lock, NULL); > _spinlock(&lock); > } > } > Index: lib/librthread/rthread.h > =================================================================== > RCS file: /cvs/src/lib/librthread/rthread.h,v > retrieving revision 1.58 > diff -u -p -r1.58 rthread.h > --- lib/librthread/rthread.h 7 May 2016 19:05:22 -0000 1.58 > +++ lib/librthread/rthread.h 2 Sep 2016 13:09:44 -0000 > @@ -37,18 +37,8 @@ > #define RTHREAD_STACK_SIZE_DEF (256 * 1024) > #endif > > -#define _USING_TICKETS 0 > -/* > - * tickets don't work yet? (or seem much slower, with lots of system time) > - * until then, keep the struct around to avoid excessive changes going > - * back and forth. > - */ > -struct _spinlock { > - _atomic_lock_t ticket; > -}; > - > -#define _SPINLOCK_UNLOCKED { _ATOMIC_LOCK_UNLOCKED } > -extern struct _spinlock _SPINLOCK_UNLOCKED_ASSIGN; > +#define _SPINLOCK_UNLOCKED _ATOMIC_LOCK_UNLOCKED > +extern int _SPINLOCK_UNLOCKED_ASSIGN; > > struct stack { > SLIST_ENTRY(stack) link; /* link for free default stacks */ > @@ -60,7 +50,7 @@ struct stack { > }; > > struct __sem { > - struct _spinlock lock; > + int lock; > volatile int waitcount; > volatile int value; > int shared; > @@ -69,7 +59,7 @@ struct __sem { > TAILQ_HEAD(pthread_queue, pthread); > > struct pthread_mutex { > - struct _spinlock lock; > + int lock; > struct pthread_queue lockers; > int type; > pthread_t owner; > @@ -84,7 +74,7 @@ struct pthread_mutex_attr { > }; > > struct pthread_cond { > - struct _spinlock lock; > + int lock; > struct pthread_queue waiters; > struct pthread_mutex *mutex; > clockid_t clock; > @@ -95,7 +85,7 @@ struct pthread_cond_attr { > }; > > struct pthread_rwlock { > - struct _spinlock lock; > + int lock; > pthread_t owner; > struct pthread_queue writers; > int readers; > @@ -150,7 +140,7 @@ struct pthread_barrierattr { > }; > > struct pthread_spinlock { > - struct _spinlock lock; > + int lock; > pthread_t owner; > }; > > @@ -158,7 +148,7 @@ struct tib; > struct pthread { > struct __sem donesem; > unsigned int flags; > - struct _spinlock flags_lock; > + int flags_lock; > struct tib *tib; > void *retval; > void *(*fn)(void *); > @@ -192,9 +182,9 @@ struct pthread { > (((size) + (_thread_pagesize - 1)) & ~(_thread_pagesize - 1)) > > __BEGIN_HIDDEN_DECLS > -void _spinlock(volatile struct _spinlock *); > -int _spinlocktry(volatile struct _spinlock *); > -void _spinunlock(volatile struct _spinlock *); > +void _spinlock(volatile int *); > +int _spinlocktry(volatile int *); > +void _spinunlock(volatile int *); > int _sem_wait(sem_t, int, const struct timespec *, int *); > int _sem_post(sem_t); > > @@ -213,7 +203,7 @@ void _thread_malloc_reinit(void); > extern int _threads_ready; > extern size_t _thread_pagesize; > extern LIST_HEAD(listhead, pthread) _thread_list; > -extern struct _spinlock _thread_lock; > +extern int _thread_lock; > extern struct pthread_attr _rthread_attr_default; > __END_HIDDEN_DECLS > > @@ -226,3 +216,8 @@ int __thrsleep(const volatile void *, cl > volatile void *, const int *); > int __thrwakeup(const volatile void *, int n); > int __thrsigdivert(sigset_t, siginfo_t *, const struct timespec *); > + > +/* futex.c */ > +int futex_lock(volatile int *); > +int futex_trylock(volatile int *); > +int futex_unlock(volatile int *); > Index: lib/librthread/rthread_file.c > =================================================================== > RCS file: /cvs/src/lib/librthread/rthread_file.c,v > retrieving revision 1.8 > diff -u -p -r1.8 rthread_file.c > --- lib/librthread/rthread_file.c 7 May 2016 19:05:22 -0000 1.8 > +++ lib/librthread/rthread_file.c 2 Sep 2016 13:09:44 -0000 > @@ -87,7 +87,7 @@ static struct static_file_lock { > } flh[NUM_HEADS]; > > /* Lock for accesses to the hash table: */ > -static struct _spinlock hash_lock = _SPINLOCK_UNLOCKED; > +static int hash_lock = _SPINLOCK_UNLOCKED; > > /* > * Find a lock structure for a FILE, return NULL if the file is > @@ -205,8 +205,7 @@ _thread_flockfile(FILE * fp) > */ > TAILQ_INSERT_TAIL(&p->lockers,self,waiting); > while (p->owner != self) { > - __thrsleep(self, 0 | _USING_TICKETS, NULL, > - &hash_lock.ticket, NULL); > + __thrsleep(self, 0, NULL, &hash_lock, NULL); > _spinlock(&hash_lock); > } > } > Index: lib/librthread/rthread_libc.c > =================================================================== > RCS file: /cvs/src/lib/librthread/rthread_libc.c,v > retrieving revision 1.16 > diff -u -p -r1.16 rthread_libc.c > --- lib/librthread/rthread_libc.c 1 Sep 2016 10:56:46 -0000 > 1.16 > +++ lib/librthread/rthread_libc.c 2 Sep 2016 13:09:44 -0000 > @@ -201,7 +201,7 @@ _thread_malloc_reinit(void) > /* > * atexit lock > */ > -static struct _spinlock atexit_lock = _SPINLOCK_UNLOCKED; > +int atexit_lock = 0; > > void > _thread_atexit_lock(void) > @@ -218,7 +218,7 @@ _thread_atexit_unlock(void) > /* > * atfork lock > */ > -static struct _spinlock atfork_lock = _SPINLOCK_UNLOCKED; > +int atfork_lock = 0; > > void > _thread_atfork_lock(void) > @@ -235,7 +235,7 @@ _thread_atfork_unlock(void) > /* > * arc4random lock > */ > -static struct _spinlock arc4_lock = _SPINLOCK_UNLOCKED; > +int arc4_lock = 0; > > void > _thread_arc4_lock(void) > Index: lib/librthread/rthread_rwlock.c > =================================================================== > RCS file: /cvs/src/lib/librthread/rthread_rwlock.c,v > retrieving revision 1.6 > diff -u -p -r1.6 rthread_rwlock.c > --- lib/librthread/rthread_rwlock.c 2 Apr 2016 19:56:53 -0000 > 1.6 > +++ lib/librthread/rthread_rwlock.c 2 Sep 2016 13:09:45 -0000 > @@ -31,7 +31,7 @@ > #include "rthread.h" > > > -static struct _spinlock rwlock_init_lock = _SPINLOCK_UNLOCKED; > +int rwlock_init_lock = 0; > > int > pthread_rwlock_init(pthread_rwlock_t *lockp, > @@ -117,8 +117,8 @@ _rthread_rwlock_rdlock(pthread_rwlock_t > error = EDEADLK; > else { > do { > - if (__thrsleep(lock, CLOCK_REALTIME | > _USING_TICKETS, > - abstime, &lock->lock.ticket, NULL) == > EWOULDBLOCK) > + if (__thrsleep(lock, CLOCK_REALTIME, > + abstime, &lock->lock, NULL) == EWOULDBLOCK) > return (ETIMEDOUT); > _spinlock(&lock->lock); > } while (lock->owner != NULL || > !TAILQ_EMPTY(&lock->writers)); > @@ -180,9 +180,8 @@ _rthread_rwlock_wrlock(pthread_rwlock_t > /* gotta block */ > TAILQ_INSERT_TAIL(&lock->writers, thread, waiting); > do { > - do_wait = __thrsleep(thread, CLOCK_REALTIME | > - _USING_TICKETS, abstime, > - &lock->lock.ticket, NULL) != EWOULDBLOCK; > + do_wait = __thrsleep(thread, CLOCK_REALTIME, > abstime, > + &lock->lock, NULL) != EWOULDBLOCK; > _spinlock(&lock->lock); > } while (lock->owner != thread && do_wait); > > Index: lib/librthread/rthread_sem.c > =================================================================== > RCS file: /cvs/src/lib/librthread/rthread_sem.c,v > retrieving revision 1.23 > diff -u -p -r1.23 rthread_sem.c > --- lib/librthread/rthread_sem.c 7 May 2016 19:05:22 -0000 > 1.23 > +++ lib/librthread/rthread_sem.c 2 Sep 2016 13:09:45 -0000 > @@ -71,9 +71,8 @@ _sem_wait(sem_t sem, int tryonly, const > } else { > sem->waitcount++; > do { > - r = __thrsleep(ident, CLOCK_REALTIME | > - _USING_TICKETS, abstime, &sem->lock.ticket, > - delayed_cancel); > + r = __thrsleep(ident, CLOCK_REALTIME, abstime, > + &sem->lock, delayed_cancel); > _spinlock(&sem->lock); > /* ignore interruptions other than cancelation */ > if (r == EINTR && (delayed_cancel == NULL || > Index: lib/librthread/rthread_stack.c > =================================================================== > RCS file: /cvs/src/lib/librthread/rthread_stack.c,v > retrieving revision 1.15 > diff -u -p -r1.15 rthread_stack.c > --- lib/librthread/rthread_stack.c 1 Sep 2016 10:56:46 -0000 > 1.15 > +++ lib/librthread/rthread_stack.c 2 Sep 2016 13:09:45 -0000 > @@ -18,7 +18,7 @@ > * attributes for possible reuse. > */ > static SLIST_HEAD(, stack) def_stacks = SLIST_HEAD_INITIALIZER(head); > -static struct _spinlock def_stacks_lock = _SPINLOCK_UNLOCKED; > +int def_stacks_lock = 0; > > struct stack * > _rthread_alloc_stack(pthread_t thread) > Index: lib/librthread/rthread_sync.c > =================================================================== > RCS file: /cvs/src/lib/librthread/rthread_sync.c,v > retrieving revision 1.42 > diff -u -p -r1.42 rthread_sync.c > --- lib/librthread/rthread_sync.c 7 May 2016 19:05:22 -0000 > 1.42 > +++ lib/librthread/rthread_sync.c 2 Sep 2016 13:09:45 -0000 > @@ -32,7 +32,7 @@ > #include "rthread.h" > #include "cancel.h" /* in libc/include */ > > -static struct _spinlock static_init_lock = _SPINLOCK_UNLOCKED; > +int static_init_lock = 0; > > /* > * mutexen > @@ -130,9 +130,8 @@ _rthread_mutex_lock(pthread_mutex_t *mut > abort(); > > /* self-deadlock, possibly until timeout */ > - while (__thrsleep(self, CLOCK_REALTIME | > - _USING_TICKETS, abstime, > - &mutex->lock.ticket, NULL) != EWOULDBLOCK) > + while (__thrsleep(self, CLOCK_REALTIME, abstime, > + &mutex->lock, NULL) != EWOULDBLOCK) > _spinlock(&mutex->lock); > return (ETIMEDOUT); > } > @@ -148,8 +147,8 @@ _rthread_mutex_lock(pthread_mutex_t *mut > /* add to the wait queue and block until at the head */ > TAILQ_INSERT_TAIL(&mutex->lockers, self, waiting); > while (mutex->owner != self) { > - ret = __thrsleep(self, CLOCK_REALTIME | > _USING_TICKETS, > - abstime, &mutex->lock.ticket, NULL); > + ret = __thrsleep(self, CLOCK_REALTIME, abstime, > + &mutex->lock, NULL); > _spinlock(&mutex->lock); > assert(mutex->owner != NULL); > if (ret == EWOULDBLOCK) { > @@ -360,8 +359,8 @@ pthread_cond_timedwait(pthread_cond_t *c > > /* wait until we're the owner of the mutex again */ > while (mutex->owner != self) { > - error = __thrsleep(self, cond->clock | _USING_TICKETS, > abstime, > - &mutex->lock.ticket, &self->delayed_cancel); > + error = __thrsleep(self, cond->clock, abstime, > + &mutex->lock, &self->delayed_cancel); > > /* > * If abstime == NULL, then we're definitely waiting > @@ -510,8 +509,8 @@ pthread_cond_wait(pthread_cond_t *condp, > > /* wait until we're the owner of the mutex again */ > while (mutex->owner != self) { > - error = __thrsleep(self, 0 | _USING_TICKETS, NULL, > - &mutex->lock.ticket, &self->delayed_cancel); > + error = __thrsleep(self, 0, NULL, &mutex->lock, > + &self->delayed_cancel); > > /* > * If we took a normal signal (not from > Index: lib/librthread/rthread_tls.c > =================================================================== > RCS file: /cvs/src/lib/librthread/rthread_tls.c,v > retrieving revision 1.17 > diff -u -p -r1.17 rthread_tls.c > --- lib/librthread/rthread_tls.c 2 Apr 2016 19:56:53 -0000 > 1.17 > +++ lib/librthread/rthread_tls.c 2 Sep 2016 13:09:45 -0000 > @@ -27,7 +27,7 @@ > #include "rthread.h" > > static struct rthread_key rkeys[PTHREAD_KEYS_MAX]; > -static struct _spinlock rkeyslock = _SPINLOCK_UNLOCKED; > +int rkeyslock = 0; > > int > pthread_key_create(pthread_key_t *key, void (*destructor)(void*)) > Index: sys/conf/files > =================================================================== > RCS file: /cvs/src/sys/conf/files,v > retrieving revision 1.625 > diff -u -p -r1.625 files > --- sys/conf/files 1 Sep 2016 10:06:33 -0000 1.625 > +++ sys/conf/files 2 Sep 2016 13:09:47 -0000 > @@ -660,6 +660,7 @@ file kern/kern_event.c > file kern/kern_exec.c > file kern/kern_exit.c > file kern/kern_fork.c > +file kern/kern_futex.c > file kern/kern_kthread.c > file kern/kern_ktrace.c ktrace > file kern/kern_lock.c > Index: sys/kern/init_sysent.c > =================================================================== > RCS file: /cvs/src/sys/kern/init_sysent.c,v > retrieving revision 1.184 > diff -u -p -r1.184 init_sysent.c > --- sys/kern/init_sysent.c 27 Jun 2016 16:52:01 -0000 1.184 > +++ sys/kern/init_sysent.c 2 Sep 2016 13:09:48 -0000 > @@ -751,5 +751,7 @@ struct sysent sysent[] = { > sys___set_tcb }, /* 329 = __set_tcb */ > { 0, 0, SY_NOLOCK | 0, > sys___get_tcb }, /* 330 = __get_tcb */ > + { 6, s(struct sys_futex_args), 0, > + sys_futex }, /* 331 = futex */ > }; > > Index: sys/kern/kern_futex.c > =================================================================== > RCS file: sys/kern/kern_futex.c > diff -N sys/kern/kern_futex.c > --- /dev/null 1 Jan 1970 00:00:00 -0000 > +++ sys/kern/kern_futex.c 2 Sep 2016 13:09:49 -0000 > @@ -0,0 +1,143 @@ > +/* $OpenBSD$ */ > + > +#include <sys/param.h> > +#include <sys/systm.h> > + > +#include <sys/signal.h> > +#include <sys/mount.h> > +#include <sys/socket.h> > +#include <sys/syscallargs.h> > +#include <sys/proc.h> > +#include <sys/futex.h> > +#include <sys/param.h> > +#include <sys/ktrace.h> > +#include <sys/kernel.h> > + > +int > +futex_wait(struct proc *p, struct sys_futex_args *v) > +{ > + struct sys_futex_args /* { > + syscallarg(void *) uaddr; > + syscallarg(int) futex_op; > + syscallarg(int) val; > + syscallarg(const struct timespec *) tp; > + syscallarg(int *) uaddr2; > + syscallarg(int) val3; > + } */ *uap = v; > + void *uaddr = SCARG(uap, uaddr); > + int val = SCARG(uap, val); > + int futex_op = SCARG(uap, futex_op); > + uint64_t to_ticks = 0; > + int uval; > + int error; > + int abort; > + > + if ((error = copyin(uaddr, &uval, sizeof uval))) > + return error; > + if (val != uval) > + return EWOULDBLOCK; > + if (SCARG(uap, tp) != NULL) { > + struct timespec now; > + struct timespec tsp; > + int clock_id; > + > + if ((error = copyin(SCARG(uap, tp), &tsp, sizeof(tsp)))) > + return error; > + > + clock_id = futex_op & FUTEX_CLOCK_REALTIME ? > + CLOCK_REALTIME : CLOCK_MONOTONIC; > + > + clock_id = CLOCK_MONOTONIC; > + > + if ((error = clock_gettime(p, clock_id, &now))) > + return error; > + > +#ifdef KTRACE > + if (KTRPOINT(p, KTR_STRUCT)) > + ktrabstimespec(p, &tsp); > +#endif > + > + if (timespeccmp(&tsp, &now, <)) > + return EWOULDBLOCK; > + > + timespecsub(&tsp, &now, &tsp); > + to_ticks = (uint64_t)hz * tsp.tv_sec + > + (tsp.tv_nsec + tick * 1000 - 1) / (tick * 1000) + 1; > + if (to_ticks > INT_MAX) > + to_ticks = INT_MAX; > + } > + > + /* XXX emulate 'abort' from thrsleep */ > + if (SCARG(uap, uaddr2) != NULL) { > + if ((error = copyin(SCARG(uap, uaddr2), &abort, > + sizeof(abort))) != 0) > + return error; > + if (abort) > + return EINTR; > + } > + > + p->p_futslpid = (long)uaddr; > + error = tsleep(&p->p_futslpid, PUSER | PCATCH, "futex", > (int)to_ticks); > + > + if (error == ERESTART) > + error = EINTR; > + > + return error; > +} > + > +int > +futex_wake(struct proc *p, struct sys_futex_args *v) > +{ > + struct sys_futex_args /* { > + syscallarg(void *) uaddr; > + syscallarg(int) futex_op; > + syscallarg(int) val; > + syscallarg(const struct timespec *) tp; > + syscallarg(int *) uaddr2; > + syscallarg(int) val3; > + } */ *uap = v; > + void *uaddr = SCARG(uap, uaddr); > + int n = SCARG(uap, val); > + int found = 0; > + struct proc *q; > + > + TAILQ_FOREACH(q, &p->p_p->ps_threads, p_thr_link) { > + if (q->p_futslpid == (long)uaddr) { > + wakeup_one(&q->p_futslpid); > + q->p_futslpid = 0; > + if (++found == n) > + break; > + } > + } > + > + return found ? 0 : ESRCH; > +} > + > +int > +sys_futex(struct proc *p, void *v, register_t *retval) > +{ > + struct sys_futex_args /* { > + syscallarg(void *) uaddr; > + syscallarg(int) futex_op; > + syscallarg(int) val; > + syscallarg(const struct timespec *) tp; > + syscallarg(int *) uaddr2; > + syscallarg(int) val3; > + } */ *uap = v; > + int op = SCARG(uap, futex_op); > + > + *retval = 0; > + > + switch (op) { > + case FUTEX_WAIT: > + *retval = futex_wait(p, uap); > + break; > + case FUTEX_WAKE: > + *retval = futex_wake(p, uap); > + break; > + default: > + *retval = EINVAL; > + break; > + } > + return 0; > +} > Index: sys/kern/kern_pledge.c > =================================================================== > RCS file: /cvs/src/sys/kern/kern_pledge.c,v > retrieving revision 1.181 > diff -u -p -r1.181 kern_pledge.c > --- sys/kern/kern_pledge.c 31 Aug 2016 07:22:43 -0000 1.181 > +++ sys/kern/kern_pledge.c 2 Sep 2016 13:09:50 -0000 > @@ -260,6 +260,7 @@ const uint64_t pledge_syscalls[SYS_MAXSY > [SYS___tfork] = PLEDGE_STDIO, > [SYS_sched_yield] = PLEDGE_STDIO, > [SYS___thrsleep] = PLEDGE_STDIO, > + [SYS_futex] = PLEDGE_ALWAYS, > [SYS___thrwakeup] = PLEDGE_STDIO, > [SYS___threxit] = PLEDGE_STDIO, > [SYS___thrsigdivert] = PLEDGE_STDIO, > Index: sys/kern/kern_synch.c > =================================================================== > RCS file: /cvs/src/sys/kern/kern_synch.c,v > retrieving revision 1.133 > diff -u -p -r1.133 kern_synch.c > --- sys/kern/kern_synch.c 6 Jul 2016 15:53:01 -0000 1.133 > +++ sys/kern/kern_synch.c 2 Sep 2016 13:09:51 -0000 > @@ -59,7 +59,7 @@ > #endif > > int thrsleep(struct proc *, struct sys___thrsleep_args *); > -int thrsleep_unlock(void *, int); > +int thrsleep_unlock(struct proc *, void *, int); > > /* > * We're only looking at 7 bits of the address; everything is > @@ -454,25 +454,27 @@ sys_sched_yield(struct proc *p, void *v, > } > > int > -thrsleep_unlock(void *lock, int lockflags) > +thrsleep_unlock(struct proc *p, void *lock, int lockflags) > { > static _atomic_lock_t unlocked = _ATOMIC_LOCK_UNLOCKED; > _atomic_lock_t *atomiclock = lock; > - uint32_t *ticket = lock; > - uint32_t ticketvalue; > int error; > > if (!lock) > return (0); > > - if (lockflags) { > - if ((error = copyin(ticket, &ticketvalue, > sizeof(ticketvalue)))) > - return (error); > - ticketvalue++; > - error = copyout(&ticketvalue, ticket, sizeof(ticketvalue)); > - } else { > - error = copyout(&unlocked, atomiclock, sizeof(unlocked)); > + error = copyout(&unlocked, atomiclock, sizeof(unlocked)); > + > + struct proc *q; > + > + TAILQ_FOREACH(q, &p->p_p->ps_threads, p_thr_link) { > + if (q->p_futslpid == (long)lock) { > + wakeup_one(&q->p_futslpid); > + q->p_futslpid = 0; > + break; > + } > } > + > return (error); > } > > @@ -510,7 +512,7 @@ thrsleep(struct proc *p, struct sys___th > > if (timespeccmp(tsp, &now, <)) { > /* already passed: still do the unlock */ > - if ((error = thrsleep_unlock(lock, lockflags))) > + if ((error = thrsleep_unlock(p, lock, lockflags))) > return (error); > return (EWOULDBLOCK); > } > @@ -524,7 +526,7 @@ thrsleep(struct proc *p, struct sys___th > > p->p_thrslpid = ident; > > - if ((error = thrsleep_unlock(lock, lockflags))) { > + if ((error = thrsleep_unlock(p, lock, lockflags))) { > goto out; > } > > Index: sys/kern/syscalls.c > =================================================================== > RCS file: /cvs/src/sys/kern/syscalls.c,v > retrieving revision 1.183 > diff -u -p -r1.183 syscalls.c > --- sys/kern/syscalls.c 27 Jun 2016 16:52:01 -0000 1.183 > +++ sys/kern/syscalls.c 2 Sep 2016 13:09:54 -0000 > @@ -393,4 +393,5 @@ char *syscallnames[] = { > "#328 (obsolete __tfork51)", /* 328 = obsolete > __tfork51 */ > "__set_tcb", /* 329 = __set_tcb */ > "__get_tcb", /* 330 = __get_tcb */ > + "futex", /* 331 = futex */ > }; > Index: sys/kern/syscalls.master > =================================================================== > RCS file: /cvs/src/sys/kern/syscalls.master,v > retrieving revision 1.173 > diff -u -p -r1.173 syscalls.master > --- sys/kern/syscalls.master 27 Jun 2016 16:50:07 -0000 1.173 > +++ sys/kern/syscalls.master 2 Sep 2016 13:09:54 -0000 > @@ -563,3 +563,6 @@ > 328 OBSOL __tfork51 > 329 STD NOLOCK { void sys___set_tcb(void *tcb); } > 330 STD NOLOCK { void *sys___get_tcb(void); } > +331 STD { void sys_futex(void *uaddr, int futex_op, int > val, \ > + const struct timespec *tp, int *uaddr2, \ > + int val3); } > Index: sys/sys/futex.h > =================================================================== > RCS file: sys/sys/futex.h > diff -N sys/sys/futex.h > --- /dev/null 1 Jan 1970 00:00:00 -0000 > +++ sys/sys/futex.h 2 Sep 2016 13:09:59 -0000 > @@ -0,0 +1,17 @@ > +/* $OpenBSD$ */ > + > +#ifndef _SYS_FUTEX_H_ > +#define _SYS_FUTEX_H_ > + > +#include <sys/types.h> > + > +#define FUTEX_WAIT 0 > +#define FUTEX_WAKE 1 > + > +#define FUTEX_CLOCK_REALTIME 256 > + > +__BEGIN_DECLS > +int futex(volatile void *, int, int, const struct timespec *, int *, > int); > +__END_DECLS > + > +#endif /* !_SYS_FUTEX_H_ */ > Index: sys/sys/proc.h > =================================================================== > RCS file: /cvs/src/sys/sys/proc.h,v > retrieving revision 1.224 > diff -u -p -r1.224 proc.h > --- sys/sys/proc.h 27 Jun 2016 19:55:02 -0000 1.224 > +++ sys/sys/proc.h 2 Sep 2016 13:10:00 -0000 > @@ -297,6 +297,7 @@ struct proc { > int p_dupfd; /* Sideways return value from > filedescopen. XXX */ > > long p_thrslpid; /* for thrsleep syscall */ > + long p_futslpid; /* for futex syscall */ > > /* scheduling */ > u_int p_estcpu; /* Time averaged value of p_cpticks. */ > Index: sys/sys/syscall.h > =================================================================== > RCS file: /cvs/src/sys/sys/syscall.h,v > retrieving revision 1.182 > diff -u -p -r1.182 syscall.h > --- sys/sys/syscall.h 27 Jun 2016 16:52:01 -0000 1.182 > +++ sys/sys/syscall.h 2 Sep 2016 13:10:01 -0000 > @@ -1,4 +1,4 @@ > -/* $OpenBSD: syscall.h,v 1.182 2016/06/27 16:52:01 jsing Exp $ */ > +/* $OpenBSD$ */ > > /* > * System call numbers. > @@ -702,4 +702,7 @@ > /* syscall: "__get_tcb" ret: "void *" args: */ > #define SYS___get_tcb 330 > > -#define SYS_MAXSYSCALL 331 > +/* syscall: "futex" ret: "void" args: "void *" "int" "int" "const struct > timespec *" "int *" "int" */ > +#define SYS_futex 331 > + > +#define SYS_MAXSYSCALL 332 > Index: sys/sys/syscallargs.h > =================================================================== > RCS file: /cvs/src/sys/sys/syscallargs.h,v > retrieving revision 1.185 > diff -u -p -r1.185 syscallargs.h > --- sys/sys/syscallargs.h 27 Jun 2016 16:52:01 -0000 1.185 > +++ sys/sys/syscallargs.h 2 Sep 2016 13:10:02 -0000 > @@ -1,4 +1,4 @@ > -/* $OpenBSD: syscallargs.h,v 1.185 2016/06/27 16:52:01 jsing Exp $ */ > +/* $OpenBSD$ */ > > /* > * System call argument lists. > @@ -1098,6 +1098,15 @@ struct sys___set_tcb_args { > syscallarg(void *) tcb; > }; > > +struct sys_futex_args { > + syscallarg(void *) uaddr; > + syscallarg(int) futex_op; > + syscallarg(int) val; > + syscallarg(const struct timespec *) tp; > + syscallarg(int *) uaddr2; > + syscallarg(int) val3; > +}; > + > /* > * System call prototypes. > */ > @@ -1347,3 +1356,4 @@ int sys_symlinkat(struct proc *, void *, > int sys_unlinkat(struct proc *, void *, register_t *); > int sys___set_tcb(struct proc *, void *, register_t *); > int sys___get_tcb(struct proc *, void *, register_t *); > +int sys_futex(struct proc *, void *, register_t *); > > -- > Michal Mazurek > >