Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 13 Sep 2012 02:36:58 +0100
From:      Attilio Rao <attilio@freebsd.org>
To:        John Baldwin <jhb@freebsd.org>, mlaier@freebsd.org, Stephan Uphoff <ups@freebsd.org>
Cc:        Konstantin Belousov <kostikbel@gmail.com>, Davide Italiano <davide@freebsd.org>, src-committers@freebsd.org, svn-src-projects@freebsd.org
Subject:   Re: svn commit: r238907 - projects/calloutng/sys/kern
Message-ID:  <CAJ-FndA8Yende_=-hgOMjfUkQVhaSdSjAb0W8xthqN1ThwT=Vg@mail.gmail.com>
In-Reply-To: <201208021707.22356.jhb@freebsd.org>
References:  <201207301350.q6UDobCI099069@svn.freebsd.org> <201207301732.33474.jhb@freebsd.org> <CAJ-FndD5EO12xsWOAe6u0EvX00q33wxO4OivnGjzj0=T2Oe8uA@mail.gmail.com> <201208021707.22356.jhb@freebsd.org>

next in thread | previous in thread | raw e-mail | index | archive | help
On Thu, Aug 2, 2012 at 10:07 PM, John Baldwin <jhb@freebsd.org> wrote:
> On Thursday, August 02, 2012 4:56:03 pm Attilio Rao wrote:
>> On 7/30/12, John Baldwin <jhb@freebsd.org> wrote:
>> > --- //depot/projects/smpng/sys/kern/kern_rmlock.c   2012-03-25
>> > 18:45:29.000000000 0000
>> > +++ //depot/user/jhb/lock/kern/kern_rmlock.c        2012-06-18 21:20:58.000000000
>> > 0000
>> > @@ -70,6 +70,9 @@
>> >  }
>> >
>> >  static void        assert_rm(const struct lock_object *lock, int what);
>> > +#ifdef DDB
>> > +static void        db_show_rm(const struct lock_object *lock);
>> > +#endif
>> >  static void        lock_rm(struct lock_object *lock, int how);
>> >  #ifdef KDTRACE_HOOKS
>> >  static int owner_rm(const struct lock_object *lock, struct thread
>> > **owner);
>>
>> While here, did you consider also:
>> - Abstracting compiler_memory_barrier() into a MI, compiler dependent function?
>> - Fix rm_queue with DCPU possibly
>
> Mostly I just wanted to fill in missing functionality and fixup the
> RM_SLEEPABLE bits a bit.

So what do you think about the following patch? If you agree I will
send to pho@ for testing in a batch with other patches.

Thanks,
Attilio


Subject: [PATCH 7/7] Reimplement pc_rm_queue as a dynamic entry for per-cpu
 members.

Sparse notes:
o rm_tracker_remove() doesn't seem to need the pc argument also
  in the current code
o The stop ptr value changes from &pc->pc_rm_queue to NULL when
  scanning the cpus list

Signed-off-by: Attilio Rao <attilio@pcbsd-2488.(none)>
---
 sys/kern/kern_rmlock.c |   42 ++++++++++++++++++++++--------------------
 sys/kern/subr_pcpu.c   |    2 --
 sys/sys/_rmlock.h      |   10 +++++-----
 sys/sys/pcpu.h         |   18 ------------------
 4 files changed, 27 insertions(+), 45 deletions(-)

diff --git a/sys/kern/kern_rmlock.c b/sys/kern/kern_rmlock.c
index ef1920b..c6ba65a 100644
--- a/sys/kern/kern_rmlock.c
+++ b/sys/kern/kern_rmlock.c
@@ -76,6 +76,8 @@ static int    owner_rm(const struct lock_object
*lock, struct thread **owner);
 #endif
 static int     unlock_rm(struct lock_object *lock);

+static DPCPU_DEFINE(struct rm_queue, rm_queue);
+
 struct lock_class lock_class_rm = {
        .lc_name = "rm",
        .lc_flags = LC_SLEEPLOCK | LC_RECURSABLE,
@@ -133,24 +135,24 @@ MTX_SYSINIT(rm_spinlock, &rm_spinlock,
"rm_spinlock", MTX_SPIN);
  * interrupt on the *local* cpu.
  */
 static void inline
-rm_tracker_add(struct pcpu *pc, struct rm_priotracker *tracker)
+rm_tracker_add(struct rm_queue *pcpu_rm_queue, struct rm_priotracker *tracker)
 {
        struct rm_queue *next;

        /* Initialize all tracker pointers */
-       tracker->rmp_cpuQueue.rmq_prev = &pc->pc_rm_queue;
-       next = pc->pc_rm_queue.rmq_next;
+       tracker->rmp_cpuQueue.rmq_prev = NULL;
+       next = pcpu_rm_queue->rmq_next;
        tracker->rmp_cpuQueue.rmq_next = next;

        /* rmq_prev is not used during froward traversal. */
        next->rmq_prev = &tracker->rmp_cpuQueue;

        /* Update pointer to first element. */
-       pc->pc_rm_queue.rmq_next = &tracker->rmp_cpuQueue;
+       pcpu_rm_queue->rmq_next = &tracker->rmp_cpuQueue;
 }

 static void inline
-rm_tracker_remove(struct pcpu *pc, struct rm_priotracker *tracker)
+rm_tracker_remove(struct rm_priotracker *tracker)
 {
        struct rm_queue *next, *prev;

@@ -167,13 +169,12 @@ rm_tracker_remove(struct pcpu *pc, struct
rm_priotracker *tracker)
 static void
 rm_cleanIPI(void *arg)
 {
-       struct pcpu *pc;
        struct rmlock *rm = arg;
        struct rm_priotracker *tracker;
-       struct rm_queue *queue;
-       pc = pcpu_find(curcpu);
+       struct rm_queue *queue, *pcpu_rm_queue;
+       pcpu_rm_queue = DPCPU_PTR(rm_queue);

-       for (queue = pc->pc_rm_queue.rmq_next; queue != &pc->pc_rm_queue;
+       for (queue = pcpu_rm_queue->rmq_next; queue != NULL;
            queue = queue->rmq_next) {
                tracker = (struct rm_priotracker *)queue;
                if (tracker->rmp_rmlock == rm && tracker->rmp_flags == 0) {
@@ -256,11 +257,12 @@ static int
 _rm_rlock_hard(struct rmlock *rm, struct rm_priotracker *tracker, int trylock)
 {
        struct pcpu *pc;
-       struct rm_queue *queue;
+       struct rm_queue *queue, *pcpu_rm_queue;
        struct rm_priotracker *atracker;

        critical_enter();
        pc = pcpu_find(curcpu);
+       pcpu_rm_queue = DPCPU_PTR(rm_queue);

        /* Check if we just need to do a proper critical_exit. */
        if (!CPU_ISSET(pc->pc_cpuid, &rm->rm_writecpus)) {
@@ -269,12 +271,12 @@ _rm_rlock_hard(struct rmlock *rm, struct
rm_priotracker *tracker, int trylock)
        }

        /* Remove our tracker from the per-cpu list. */
-       rm_tracker_remove(pc, tracker);
+       rm_tracker_remove(tracker);

        /* Check to see if the IPI granted us the lock after all. */
        if (tracker->rmp_flags) {
                /* Just add back tracker - we hold the lock. */
-               rm_tracker_add(pc, tracker);
+               rm_tracker_add(pcpu_rm_queue, tracker);
                critical_exit();
                return (1);
        }
@@ -288,8 +290,8 @@ _rm_rlock_hard(struct rmlock *rm, struct
rm_priotracker *tracker, int trylock)
                 * Just grant the lock if this thread already has a tracker
                 * for this lock on the per-cpu queue.
                 */
-               for (queue = pc->pc_rm_queue.rmq_next;
-                   queue != &pc->pc_rm_queue; queue = queue->rmq_next) {
+               for (queue = pcpu_rm_queue->rmq_next; queue != NULL;
+                   queue = queue->rmq_next) {
                        atracker = (struct rm_priotracker *)queue;
                        if ((atracker->rmp_rmlock == rm) &&
                            (atracker->rmp_thread == tracker->rmp_thread)) {
@@ -298,7 +300,7 @@ _rm_rlock_hard(struct rmlock *rm, struct
rm_priotracker *tracker, int trylock)
                                    tracker, rmp_qentry);
                                tracker->rmp_flags = RMPF_ONQUEUE;
                                mtx_unlock_spin(&rm_spinlock);
-                               rm_tracker_add(pc, tracker);
+                               rm_tracker_add(pcpu_rm_queue, tracker);
                                critical_exit();
                                return (1);
                        }
@@ -326,7 +328,7 @@ _rm_rlock_hard(struct rmlock *rm, struct
rm_priotracker *tracker, int trylock)
        critical_enter();
        pc = pcpu_find(curcpu);
        CPU_CLR(pc->pc_cpuid, &rm->rm_writecpus);
-       rm_tracker_add(pc, tracker);
+       rm_tracker_add(pcpu_rm_queue, tracker);
        sched_pin();
        critical_exit();

@@ -342,6 +344,7 @@ int
 _rm_rlock(struct rmlock *rm, struct rm_priotracker *tracker, int trylock)
 {
        struct thread *td = curthread;
+       struct rm_queue *pcpu_rm_queue;
        struct pcpu *pc;

        if (SCHEDULER_STOPPED())
@@ -356,8 +359,9 @@ _rm_rlock(struct rmlock *rm, struct rm_priotracker
*tracker, int trylock)
        compiler_memory_barrier();

        pc = cpuid_to_pcpu[td->td_oncpu]; /* pcpu_find(td->td_oncpu); */
+       pcpu_rm_queue = DPCPU_ID_PTR(td->td_oncpu, rm_queue);

-       rm_tracker_add(pc, tracker);
+       rm_tracker_add(pcpu_rm_queue, tracker);

        sched_pin();

@@ -413,15 +417,13 @@ _rm_unlock_hard(struct thread *td,struct
rm_priotracker *tracker)
 void
 _rm_runlock(struct rmlock *rm, struct rm_priotracker *tracker)
 {
-       struct pcpu *pc;
        struct thread *td = tracker->rmp_thread;

        if (SCHEDULER_STOPPED())
                return;

        td->td_critnest++;      /* critical_enter(); */
-       pc = cpuid_to_pcpu[td->td_oncpu]; /* pcpu_find(td->td_oncpu); */
-       rm_tracker_remove(pc, tracker);
+       rm_tracker_remove(tracker);
        td->td_critnest--;
        sched_unpin();

diff --git a/sys/kern/subr_pcpu.c b/sys/kern/subr_pcpu.c
index 505a4df..279295e 100644
--- a/sys/kern/subr_pcpu.c
+++ b/sys/kern/subr_pcpu.c
@@ -90,8 +90,6 @@ pcpu_init(struct pcpu *pcpu, int cpuid, size_t size)
        cpuid_to_pcpu[cpuid] = pcpu;
        STAILQ_INSERT_TAIL(&cpuhead, pcpu, pc_allcpu);
        cpu_pcpu_init(pcpu, cpuid, size);
-       pcpu->pc_rm_queue.rmq_next = &pcpu->pc_rm_queue;
-       pcpu->pc_rm_queue.rmq_prev = &pcpu->pc_rm_queue;
 }

 void
diff --git a/sys/sys/_rmlock.h b/sys/sys/_rmlock.h
index 15d6c49..51bb03e 100644
--- a/sys/sys/_rmlock.h
+++ b/sys/sys/_rmlock.h
@@ -32,11 +32,6 @@
 #ifndef _SYS__RMLOCK_H_
 #define        _SYS__RMLOCK_H_

-/*
- * XXXUPS remove as soon as we have per cpu variable
- * linker sets and  can define rm_queue in _rm_lock.h
-*/
-#include <sys/pcpu.h>
 /*
  * Mostly reader/occasional writer lock.
  */
@@ -55,6 +50,11 @@ struct rmlock {
 #define        rm_lock_mtx     _rm_lock._rm_lock_mtx
 #define        rm_lock_sx      _rm_lock._rm_lock_sx

+struct rm_queue {
+       struct rm_queue *volatile rmq_next;
+       struct rm_queue *volatile rmq_prev;
+};
+
 struct rm_priotracker {
        struct rm_queue rmp_cpuQueue; /* Must be first */
        struct rmlock *rmp_rmlock;
diff --git a/sys/sys/pcpu.h b/sys/sys/pcpu.h
index 4a4ec00..78ba04a 100644
--- a/sys/sys/pcpu.h
+++ b/sys/sys/pcpu.h
@@ -137,15 +137,6 @@ extern uintptr_t dpcpu_off[];

 #endif /* _KERNEL */

-/*
- * XXXUPS remove as soon as we have per cpu variable
- * linker sets and can define rm_queue in _rm_lock.h
- */
-struct rm_queue {
-       struct rm_queue* volatile rmq_next;
-       struct rm_queue* volatile rmq_prev;
-};
-
 /*
  * This structure maps out the global data that needs to be kept on a
  * per-cpu basis.  The members are accessed via the PCPU_GET/SET/PTR
@@ -169,15 +160,6 @@ struct pcpu {
        void            *pc_netisr;             /* netisr SWI cookie */
        int             pc_dnweight;            /* vm_page_dontneed() */
        int             pc_domain;              /* Memory domain. */
-
-       /*
-        * Stuff for read mostly lock
-        *
-        * XXXUPS remove as soon as we have per cpu variable
-        * linker sets.
-        */
-       struct rm_queue pc_rm_queue;
-
        uintptr_t       pc_dynamic;             /* Dynamic per-cpu data area */

        /*
-- 
1.7.7.4



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?CAJ-FndA8Yende_=-hgOMjfUkQVhaSdSjAb0W8xthqN1ThwT=Vg>