svn commit: r357809 - head/sys/kern
Mateusz Guzik
mjg at FreeBSD.org
Wed Feb 12 11:17:19 UTC 2020
Author: mjg
Date: Wed Feb 12 11:17:18 2020
New Revision: 357809
URL: https://svnweb.freebsd.org/changeset/base/357809
Log:
rms: use smp_rendezvous_cpus_retry instead of a hand-rolled variant
Modified:
head/sys/kern/kern_rmlock.c
Modified: head/sys/kern/kern_rmlock.c
==============================================================================
--- head/sys/kern/kern_rmlock.c Wed Feb 12 11:16:55 2020 (r357808)
+++ head/sys/kern/kern_rmlock.c Wed Feb 12 11:17:18 2020 (r357809)
@@ -991,17 +991,17 @@ rms_runlock(struct rmslock *rms)
struct rmslock_ipi {
struct rmslock *rms;
- cpuset_t signal;
+ struct smp_rendezvous_cpus_retry_arg srcra;
};
static void
-rms_wlock_IPI(void *arg)
+rms_action_func(void *arg)
{
struct rmslock_ipi *rmsipi;
struct rmslock *rms;
int readers;
- rmsipi = arg;
+ rmsipi = __containerof(arg, struct rmslock_ipi, srcra);
rms = rmsipi->rms;
if (*zpcpu_get(rms->readers_influx))
@@ -1009,65 +1009,40 @@ rms_wlock_IPI(void *arg)
readers = zpcpu_replace(rms->readers_pcpu, 0);
if (readers != 0)
atomic_add_int(&rms->readers, readers);
- CPU_CLR_ATOMIC(curcpu, &rmsipi->signal);
+ smp_rendezvous_cpus_done(arg);
}
static void
+rms_wait_func(void *arg, int cpu)
+{
+ struct rmslock_ipi *rmsipi;
+ struct rmslock *rms;
+ int *in_op;
+
+ rmsipi = __containerof(arg, struct rmslock_ipi, srcra);
+ rms = rmsipi->rms;
+
+ in_op = zpcpu_get_cpu(rms->readers_influx, cpu);
+ while (atomic_load_int(in_op))
+ cpu_spinwait();
+}
+
+static void
rms_wlock_switch(struct rmslock *rms)
{
struct rmslock_ipi rmsipi;
- int *in_op;
- int cpu;
MPASS(rms->readers == 0);
MPASS(rms->writers == 1);
rmsipi.rms = rms;
- /*
- * Publishes rms->writers. rlock and runlock will get this ordered
- * via IPI in the worst case.
- */
- atomic_thread_fence_rel();
-
- /*
- * Collect reader counts from all CPUs using an IPI. The handler can
- * find itself running while the interrupted CPU was doing either
- * rlock or runlock in which case it will fail.
- *
- * Successful attempts clear the cpu id in the bitmap.
- *
- * In case of failure we observe all failing CPUs not executing there to
- * determine when to make the next attempt. Note that threads having
- * the var set have preemption disabled. Setting of readers_influx
- * only uses compiler barriers making these loads unreliable, which is
- * fine -- the IPI handler will always see the correct result.
- *
- * We retry until all counts are collected. Forward progress is
- * guaranteed by that fact that the total number of threads which can
- * be caught like this is finite and they all are going to block on
- * their own.
- */
- CPU_COPY(&all_cpus, &rmsipi.signal);
- for (;;) {
- smp_rendezvous_cpus(
- rmsipi.signal,
- smp_no_rendezvous_barrier,
- rms_wlock_IPI,
- smp_no_rendezvous_barrier,
- &rmsipi);
-
- if (CPU_EMPTY(&rmsipi.signal))
- break;
-
- CPU_FOREACH(cpu) {
- if (!CPU_ISSET(cpu, &rmsipi.signal))
- continue;
- in_op = zpcpu_get_cpu(rms->readers_influx, cpu);
- while (atomic_load_int(in_op))
- cpu_spinwait();
- }
- }
+ smp_rendezvous_cpus_retry(all_cpus,
+ smp_no_rendezvous_barrier,
+ rms_action_func,
+ smp_no_rendezvous_barrier,
+ rms_wait_func,
+ &rmsipi.srcra);
}
void
More information about the svn-src-head
mailing list