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/52d920f3acfc
branches: trunk
changeset: 325139:52d920f3acfc
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 ef44490f0c8e -r 52d920f3acfc 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(®ion_freelist)) {
- me = MMUQ_FIRST(®ion_freelist);
- MMUQ_REMOVE(me, me_list);
+ if (!mmuq_empty(®ion_freelist)) {
+ me = mmuq_first(®ion_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(®ion_lru))
+ if (mmuq_empty(®ion_lru))
panic("region_alloc: all smegs gone");
- me = MMUQ_FIRST(®ion_lru);
+ me = mmuq_first(®ion_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(®ion_freelist, me, me_list);
+ mmuq_insert_tail(®ion_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