#include <sys/cdefs.h>
__RCSID("$NetBSD: pthread_lock.c,v 1.36 2022/04/10 10:38:33 riastradh Exp $");
#include "../../common/lib/libc/atomic/atomic_op_namespace.h"
#include <sys/types.h>
#include <sys/ras.h>
#include <machine/lock.h>
#include <errno.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include "pthread.h"
#include "pthread_int.h"
#define PTHREAD__NSPINS 64
RAS_DECL(pthread__lock);
static void pthread__spinlock_slow(pthread_spin_t *);
#ifdef PTHREAD__ASM_RASOPS
void pthread__ras_simple_lock_init(__cpu_simple_lock_t *);
int pthread__ras_simple_lock_try(__cpu_simple_lock_t *);
void pthread__ras_simple_unlock(__cpu_simple_lock_t *);
#else
static void
pthread__ras_simple_lock_init(__cpu_simple_lock_t *alp)
{
__cpu_simple_lock_clear(alp);
}
static int
pthread__ras_simple_lock_try(__cpu_simple_lock_t *alp)
{
int locked;
RAS_START(pthread__lock);
locked = __SIMPLELOCK_LOCKED_P(alp);
__cpu_simple_lock_set(alp);
RAS_END(pthread__lock);
return !locked;
}
static void
pthread__ras_simple_unlock(__cpu_simple_lock_t *alp)
{
__cpu_simple_lock_clear(alp);
}
#endif
static const struct pthread_lock_ops pthread__lock_ops_ras = {
pthread__ras_simple_lock_init,
pthread__ras_simple_lock_try,
pthread__ras_simple_unlock,
pthread__spinlock_slow,
};
static void
pthread__atomic_simple_lock_init(__cpu_simple_lock_t *alp)
{
__cpu_simple_lock_init(alp);
}
static int
pthread__atomic_simple_lock_try(__cpu_simple_lock_t *alp)
{
return (__cpu_simple_lock_try(alp));
}
static void
pthread__atomic_simple_unlock(__cpu_simple_lock_t *alp)
{
__cpu_simple_unlock(alp);
}
static const struct pthread_lock_ops pthread__lock_ops_atomic = {
pthread__atomic_simple_lock_init,
pthread__atomic_simple_lock_try,
pthread__atomic_simple_unlock,
pthread__spinlock_slow,
};
const struct pthread_lock_ops *pthread__lock_ops = &pthread__lock_ops_ras;
static void
pthread__spinlock_slow(pthread_spin_t *lock)
{
pthread_t self;
int count;
self = pthread__self();
do {
count = pthread__nspins;
while (__SIMPLELOCK_LOCKED_P(lock) && --count > 0)
pthread__smt_pause();
if (count > 0) {
if ((*self->pt_lockops.plo_try)(lock))
break;
continue;
}
sched_yield();
} while ( 1);
}
void
pthread__lockprim_init(void)
{
char *p;
if ((p = pthread__getenv("PTHREAD_NSPINS")) != NULL)
pthread__nspins = atoi(p);
else if (pthread__concurrency != 1)
pthread__nspins = PTHREAD__NSPINS;
else
pthread__nspins = 1;
if (pthread__concurrency != 1) {
pthread__lock_ops = &pthread__lock_ops_atomic;
return;
}
if (rasctl(RAS_ADDR(pthread__lock), RAS_SIZE(pthread__lock),
RAS_INSTALL) != 0) {
pthread__lock_ops = &pthread__lock_ops_atomic;
return;
}
}
void
pthread_lockinit(pthread_spin_t *lock)
{
pthread__simple_lock_init(lock);
}