Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/arch/sparc/sparc Use a double linked list with a static ...



details:   https://anonhg.NetBSD.org/src/rev/5e56c6dffd00
branches:  trunk
changeset: 791879:5e56c6dffd00
user:      jdc <jdc%NetBSD.org@localhost>
date:      Sun Dec 08 10:12:39 2013 +0000

description:
Use a double linked list with a static head to track MMU entries.
Code from martin@.
Tested on SUN4 (4/330), SUN4C (SS2), and SUN4M (Krups, 4/630).

diffstat:

 sys/arch/sparc/sparc/pmap.c |  166 +++++++++++++++++++++++++------------------
 1 files changed, 98 insertions(+), 68 deletions(-)

diffs (truncated from 383 to 300 lines):

diff -r f67ce663f4b1 -r 5e56c6dffd00 sys/arch/sparc/sparc/pmap.c
--- a/sys/arch/sparc/sparc/pmap.c       Sun Dec 08 09:32:51 2013 +0000
+++ b/sys/arch/sparc/sparc/pmap.c       Sun Dec 08 10:12:39 2013 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: pmap.c,v 1.353 2013/11/25 02:59:14 christos Exp $ */
+/*     $NetBSD: pmap.c,v 1.354 2013/12/08 10:12:39 jdc Exp $ */
 
 /*
  * Copyright (c) 1996
@@ -56,7 +56,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.353 2013/11/25 02:59:14 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.354 2013/12/08 10:12:39 jdc Exp $");
 
 #include "opt_ddb.h"
 #include "opt_kgdb.h"
@@ -279,12 +279,12 @@
  * by flushing (and invalidating) a TLB entry when appropriate before
  * altering an in-memory page table entry.
  */
-struct mmuq;
 struct mmuentry {
-       TAILQ_ENTRY(mmuentry)   me_list;        /* usage list link */
+       struct {
+           struct mmuentry *prev, *next;
+       }                       me_list;        /* usage list link */
        TAILQ_ENTRY(mmuentry)   me_pmchain;     /* pmap owner link */
        struct  pmap *me_pmap;          /* pmap, if in use */
-       struct  mmuq *me_queue;         /* where do we live */
        u_short me_vreg;                /* associated virtual region/segment */
        u_short me_vseg;                /* associated virtual region/segment */
        u_short me_cookie;              /* hardware SMEG/PMEG number */
@@ -295,24 +295,54 @@
 struct mmuentry *mmusegments;  /* allocated in pmap_bootstrap */
 struct mmuentry *mmuregions;   /* allocated in pmap_bootstrap */
 
-TAILQ_HEAD(mmuq, mmuentry);
-struct mmuq segm_freelist, segm_lru, segm_locked;
-struct mmuq region_freelist, region_lru, region_locked;
-
-#define MMUQ_INIT(head)                        TAILQ_INIT(head)
-
-#define MMUQ_REMOVE(elm, field)                do {    \
-       TAILQ_REMOVE(elm->me_queue, elm,field); \
-       elm->me_queue = NULL;                   \
-} while (/*CONSTCOND*/0)
-
-#define MMUQ_INSERT_TAIL(head, elm, field) do {        \
-       TAILQ_INSERT_TAIL(head, elm, field);    \
-       elm->me_queue = head;                   \
-} while (/*CONSTCOND*/0)
-
-#define MMUQ_EMPTY(head)               TAILQ_EMPTY(head)
-#define MMUQ_FIRST(head)               TAILQ_FIRST(head)
+#if defined(SUN4) || defined(SUN4C)
+struct mmuentry segm_freelist, segm_lru, segm_locked;
+#if defined(SUN4_MMU3L)
+struct mmuentry region_freelist, region_lru, region_locked;
+#endif
+/*
+ * We use a double linked list looping through its static head (which
+ * alway remains on the list), so we can remove any other member from
+ * a list without knowing which list it is on.
+ */
+static void inline
+mmuq_remove(struct mmuentry *e)
+{
+       e->me_list.next->me_list.prev = e->me_list.prev;
+       e->me_list.prev->me_list.next = e->me_list.next;
+}
+
+static void inline
+mmuq_init(struct mmuentry *e)
+{
+       memset(e, 0, sizeof(*e));
+       e->me_list.next = e;
+       e->me_list.prev = e;
+}
+
+static inline struct mmuentry *
+mmuq_first(struct mmuentry *head)
+{
+       KASSERT(head->me_list.next != head);
+       return head->me_list.next;
+}
+
+static inline bool
+mmuq_empty(struct mmuentry *head)
+{
+       return head->me_list.next == head;
+}
+
+static inline void
+mmuq_insert_tail(struct mmuentry *head, struct mmuentry *e)
+{
+       e->me_list.prev = head->me_list.prev;
+       e->me_list.next = head;
+       head->me_list.prev->me_list.next = e;
+       head->me_list.prev = e;
+}
+#endif
+
 
 int    seginval;               /* [4/4c] the invalid segment number */
 int    reginval;               /* [4/3mmu] the invalid region number */
@@ -912,7 +942,7 @@
 {
        vaddr_t va;
        paddr_t pa;
-       bool rv __diagused;
+       bool rv;
 
        va = (vaddr_t)v;
        rv = pmap_extract(pmap_kernel(), va, &pa);
@@ -1545,10 +1575,10 @@
 /*
  * MMU management.
  */
-static int     me_alloc(struct mmuq *, struct pmap *, int, int);
+static int     me_alloc(struct mmuentry *, struct pmap *, int, int);
 static void    me_free(struct pmap *, u_int);
 #if defined(SUN4_MMU3L)
-static int     region_alloc(struct mmuq *, struct pmap *, int);
+static int     region_alloc(struct mmuentry *, struct pmap *, int);
 static void    region_free(struct pmap *, u_int);
 #endif
 
@@ -1568,7 +1598,7 @@
  */
 
 static inline int
-me_alloc(struct mmuq *mh, struct pmap *newpm, int newvreg, int newvseg)
+me_alloc(struct mmuentry *mh, struct pmap *newpm, int newvreg, int newvseg)
 {
        struct mmuentry *me;
        struct pmap *pm;
@@ -1578,16 +1608,16 @@
        struct segmap *sp;
 
        /* try free list first */
-       if (!MMUQ_EMPTY(&segm_freelist)) {
-               me = MMUQ_FIRST(&segm_freelist);
-               MMUQ_REMOVE(me, me_list);
+       if (!mmuq_empty(&segm_freelist)) {
+               me = mmuq_first(&segm_freelist);
+               mmuq_remove(me);
 #ifdef DEBUG
                if (me->me_pmap != NULL)
                        panic("me_alloc: freelist entry has pmap");
                if (pmapdebug & PDB_MMU_ALLOC)
                        printf("me_alloc: got pmeg %d\n", me->me_cookie);
 #endif
-               MMUQ_INSERT_TAIL(mh, me, me_list);
+               mmuq_insert_tail(mh, me);
 
                /* onto on pmap chain; pmap is already locked, if needed */
                TAILQ_INSERT_TAIL(&newpm->pm_seglist, me, me_pmchain);
@@ -1611,10 +1641,10 @@
        }
 
        /* no luck, take head of LRU list */
-       if (MMUQ_EMPTY(&segm_lru))
+       if (mmuq_empty(&segm_lru))
                panic("me_alloc: all pmegs gone");
 
-       me = MMUQ_FIRST(&segm_lru);
+       me = mmuq_first(&segm_lru);
        pm = me->me_pmap;
 #ifdef DEBUG
        if (pmapdebug & (PDB_MMU_ALLOC | PDB_MMU_STEAL))
@@ -1628,8 +1658,8 @@
         * Remove from LRU list, and insert at end of new list
         * (probably the LRU list again, but so what?).
         */
-       MMUQ_REMOVE(me, me_list);
-       MMUQ_INSERT_TAIL(mh, me, me_list);
+       mmuq_remove(me);
+       mmuq_insert_tail(mh, me);
 
 #ifdef DIAGNOSTIC
        if (mh == &segm_locked) {
@@ -1799,7 +1829,7 @@
        TAILQ_REMOVE(&pm->pm_seglist, me, me_pmchain);
 
        /* off LRU or lock chain */
-       MMUQ_REMOVE(me, me_list);
+       mmuq_remove(me);
 #ifdef DIAGNOSTIC
        if (me->me_statp == NULL)
                panic("me_statp");
@@ -1809,7 +1839,7 @@
 
        /* no associated pmap; on free list */
        me->me_pmap = NULL;
-       MMUQ_INSERT_TAIL(&segm_freelist, me, me_list);
+       mmuq_insert_tail(&segm_freelist, me);
 #ifdef DIAGNOSTIC
        pmap_stats.ps_npmeg_free++;
 #endif
@@ -1820,7 +1850,7 @@
 /* XXX - Merge with segm_alloc/segm_free ? */
 
 int
-region_alloc(struct mmuq *mh, struct pmap *newpm, int newvr)
+region_alloc(struct mmuentry *mh, struct pmap *newpm, int newvr)
 {
        struct mmuentry *me;
        struct pmap *pm;
@@ -1828,16 +1858,16 @@
        struct regmap *rp;
 
        /* try free list first */
-       if (!MMUQ_EMPTY(&region_freelist)) {
-               me = MMUQ_FIRST(&region_freelist);
-               MMUQ_REMOVE(me, me_list);
+       if (!mmuq_empty(&region_freelist)) {
+               me = mmuq_first(&region_freelist);
+               mmuq_remove(me);
 #ifdef DEBUG
                if (me->me_pmap != NULL)
                        panic("region_alloc: freelist entry has pmap");
                if (pmapdebug & PDB_MMUREG_ALLOC)
                        printf("region_alloc: got smeg 0x%x\n", me->me_cookie);
 #endif
-               MMUQ_INSERT_TAIL(mh, me, me_list);
+               mmuq_insert_tail(mh, me);
 
                /* onto on pmap chain; pmap is already locked, if needed */
                TAILQ_INSERT_TAIL(&newpm->pm_reglist, me, me_pmchain);
@@ -1850,10 +1880,10 @@
        }
 
        /* no luck, take head of LRU list */
-       if (MMUQ_EMPTY(&region_lru))
+       if (mmuq_empty(&region_lru))
                panic("region_alloc: all smegs gone");
 
-       me = MMUQ_FIRST(&region_lru);
+       me = mmuq_first(&region_lru);
 
        pm = me->me_pmap;
        if (pm == NULL)
@@ -1869,8 +1899,8 @@
         * Remove from LRU list, and insert at end of new list
         * (probably the LRU list again, but so what?).
         */
-       MMUQ_REMOVE(me, me_list);
-       MMUQ_INSERT_TAIL(mh, me, me_list);
+       mmuq_remove(me);
+       mmuq_insert_tail(mh, me);
 
        rp = &pm->pm_regmap[me->me_vreg];
        ctx = getcontext4();
@@ -1925,16 +1955,16 @@
        TAILQ_REMOVE(&pm->pm_reglist, me, me_pmchain);
 
        /* off LRU or lock chain */
-       MMUQ_REMOVE(me, me_list);
+       mmuq_remove(me);
 
        /* no associated pmap; on free list */
        me->me_pmap = NULL;
-       MMUQ_INSERT_TAIL(&region_freelist, me, me_list);
+       mmuq_insert_tail(&region_freelist, me);
 }
 
 static void
 mmu_pagein_reg(struct pmap *pm, struct regmap *rp, vaddr_t va,
-               int vr, struct mmuq *mh)
+               int vr, struct mmuentry *mh)
 {
        int i, s, smeg;
 
@@ -1968,8 +1998,8 @@
 {
        struct mmuentry *me = &mmusegments[pmeg];
 
-       MMUQ_REMOVE(me, me_list);
-       MMUQ_INSERT_TAIL(&segm_locked, me, me_list);
+       mmuq_remove(me);
+       mmuq_insert_tail(&segm_locked, me);
 #ifdef DIAGNOSTIC
        (*me->me_statp)--;
        pmap_stats.ps_npmeg_locked++;
@@ -1982,8 +2012,8 @@
 {
        struct mmuentry *me = &mmusegments[pmeg];
 
-       MMUQ_REMOVE(me, me_list);
-       MMUQ_INSERT_TAIL(&segm_lru, me, me_list);
+       mmuq_remove(me);
+       mmuq_insert_tail(&segm_lru, me);
 #ifdef DIAGNOSTIC
        (*me->me_statp)--;
        pmap_stats.ps_npmeg_lru++;
@@ -1993,7 +2023,7 @@
 
 static void



Home | Main Index | Thread Index | Old Index