Print this page
patch segpcache-maxwindow-is-useless
use NULL dump segop as a shorthand for no-op
Instead of forcing every segment driver to implement a dummy function that
does nothing, handle NULL dump segop function pointer as a no-op shorthand.
const-ify make segment ops structures
There is no reason to keep the segment ops structures writable.
use NULL setpagesize segop as a shorthand for ENOTSUP
Instead of forcing every segment driver to implement a dummp function to
return (hopefully) ENOTSUP, handle NULL setpagesize segop function pointer
as "return ENOTSUP" shorthand.
use NULL getmemid segop as a shorthand for ENODEV
Instead of forcing every segment driver to implement a dummy function to
return (hopefully) ENODEV, handle NULL getmemid segop function pointer as
"return ENODEV" shorthand.
use NULL capable segop as a shorthand for no-capabilities
Instead of forcing every segment driver to implement a dummy "return 0"
function, handle NULL capable segop function pointer as "no copabilities
supported" shorthand.
seg_inherit_notsup is redundant since segop_inherit checks for NULL properly
patch lower-case-segops
instead using SEGOP_* macros, define full-fledged segop_* functions
This will allow us to do some sanity checking or even implement stub
functionality in one place instead of duplicating it wherever these wrappers
are used.

*** 124,134 **** /* * The following variables can be tuned via /etc/system. */ int segpcache_enabled = 1; /* if 1, shadow lists are cached */ - pgcnt_t segpcache_maxwindow = 0; /* max # of pages that can be cached */ ulong_t segpcache_hashsize_win = 0; /* # of non wired buckets */ ulong_t segpcache_hashsize_wired = 0; /* # of wired buckets */ int segpcache_reap_sec = 1; /* reap check rate in secs */ clock_t segpcache_reap_ticks = 0; /* reap interval in ticks */ int segpcache_pcp_maxage_sec = 1; /* pcp max age in secs */ --- 124,133 ----
*** 147,164 **** /* * Keep frequently used variables together in one cache line. */ static struct p_ctrl1 { uint_t p_disabled; /* if not 0, caching temporarily off */ - pgcnt_t p_maxwin; /* max # of pages that can be cached */ size_t p_hashwin_sz; /* # of non wired buckets */ struct seg_phash *p_htabwin; /* hash table for non wired entries */ size_t p_hashwired_sz; /* # of wired buckets */ struct seg_phash_wired *p_htabwired; /* hash table for wired entries */ kmem_cache_t *p_kmcache; /* kmem cache for seg_pcache structs */ #ifdef _LP64 ! ulong_t pad[1]; #endif /* _LP64 */ } pctrl1; static struct p_ctrl2 { kmutex_t p_mem_mtx; /* protects window counter and p_halinks */ --- 146,162 ---- /* * Keep frequently used variables together in one cache line. */ static struct p_ctrl1 { uint_t p_disabled; /* if not 0, caching temporarily off */ size_t p_hashwin_sz; /* # of non wired buckets */ struct seg_phash *p_htabwin; /* hash table for non wired entries */ size_t p_hashwired_sz; /* # of wired buckets */ struct seg_phash_wired *p_htabwired; /* hash table for wired entries */ kmem_cache_t *p_kmcache; /* kmem cache for seg_pcache structs */ #ifdef _LP64 ! ulong_t pad[2]; #endif /* _LP64 */ } pctrl1; static struct p_ctrl2 { kmutex_t p_mem_mtx; /* protects window counter and p_halinks */
*** 179,189 **** ulong_t pad[3]; #endif /* _LP64 */ } pctrl3; #define seg_pdisabled pctrl1.p_disabled - #define seg_pmaxwindow pctrl1.p_maxwin #define seg_phashsize_win pctrl1.p_hashwin_sz #define seg_phashtab_win pctrl1.p_htabwin #define seg_phashsize_wired pctrl1.p_hashwired_sz #define seg_phashtab_wired pctrl1.p_htabwired #define seg_pkmcache pctrl1.p_kmcache --- 177,186 ----
*** 203,214 **** #define P_HASHWIRED_MASK (seg_phashsize_wired - 1) #define P_BASESHIFT (6) kthread_t *seg_pasync_thr; ! extern struct seg_ops segvn_ops; ! extern struct seg_ops segspt_shmops; #define IS_PFLAGS_WIRED(flags) ((flags) & SEGP_FORCE_WIRED) #define IS_PCP_WIRED(pcp) IS_PFLAGS_WIRED((pcp)->p_flags) #define LBOLT_DELTA(t) ((ulong_t)(ddi_get_lbolt() - (t))) --- 200,211 ---- #define P_HASHWIRED_MASK (seg_phashsize_wired - 1) #define P_BASESHIFT (6) kthread_t *seg_pasync_thr; ! extern const struct seg_ops segvn_ops; ! extern const struct seg_ops segspt_shmops; #define IS_PFLAGS_WIRED(flags) ((flags) & SEGP_FORCE_WIRED) #define IS_PCP_WIRED(pcp) IS_PFLAGS_WIRED((pcp)->p_flags) #define LBOLT_DELTA(t) ((ulong_t)(ddi_get_lbolt() - (t)))
*** 754,767 **** if (IS_PFLAGS_WIRED(flags)) { return (SEGP_SUCCESS); } - if (seg_plocked_window + btop(len) > seg_pmaxwindow) { - return (SEGP_FAIL); - } - if (freemem < desfree) { return (SEGP_FAIL); } return (SEGP_SUCCESS); --- 751,760 ----
*** 827,840 **** ASSERT((len & PAGEOFFSET) == 0); npages = btop(len); mutex_enter(&seg_pmem_mtx); if (!IS_PFLAGS_WIRED(flags)) { - if (seg_plocked_window + npages > seg_pmaxwindow) { - mutex_exit(&seg_pmem_mtx); - return (SEGP_FAIL); - } seg_plocked_window += npages; } seg_plocked += npages; mutex_exit(&seg_pmem_mtx); --- 820,829 ----
*** 946,956 **** int hlinks = 0; int hlix; pcache_link_t *hlinkp; pcache_link_t *hlnextp = NULL; int lowmem; - int trim; ASSERT(seg_phashsize_win != 0); /* * if the cache is off or empty, return --- 935,944 ----
*** 959,969 **** return; } if (!force) { lowmem = 0; - trim = 0; if (freemem < lotsfree + needfree) { spgcnt_t fmem = MAX((spgcnt_t)(freemem - needfree), 0); if (fmem <= 5 * (desfree >> 2)) { lowmem = 1; } else if (fmem <= 7 * (lotsfree >> 3)) { --- 947,956 ----
*** 976,989 **** 3 * (availrmem_initial >> 2)) { lowmem = 1; } } } ! if (seg_plocked_window >= 7 * (seg_pmaxwindow >> 3)) { ! trim = 1; ! } ! if (!lowmem && !trim) { return; } npgs_to_purge = seg_plocked_window >> seg_pshrink_shift; if (lowmem) { --- 963,973 ---- 3 * (availrmem_initial >> 2)) { lowmem = 1; } } } ! if (!lowmem) { return; } npgs_to_purge = seg_plocked_window >> seg_pshrink_shift; if (lowmem) {
*** 1107,1117 **** } if (!force) { if (npgs_purged >= npgs_to_purge) { break; } ! if (!trim && !(seg_pathr_full_ahb & 15)) { ASSERT(lowmem); if (freemem >= lotsfree + needfree) { break; } } --- 1091,1101 ---- } if (!force) { if (npgs_purged >= npgs_to_purge) { break; } ! if (!(seg_pathr_full_ahb & 15)) { ASSERT(lowmem); if (freemem >= lotsfree + needfree) { break; } }
*** 1468,1496 **** hp->p_hnext = (struct seg_pcache *)hp; hp->p_hprev = (struct seg_pcache *)hp; mutex_init(&hp->p_hmutex, NULL, MUTEX_DEFAULT, NULL); } - if (segpcache_maxwindow == 0) { - if (physmegs < 64) { - /* 3% of memory */ - segpcache_maxwindow = availrmem >> 5; - } else if (physmegs < 512) { - /* 12% of memory */ - segpcache_maxwindow = availrmem >> 3; - } else if (physmegs < 1024) { - /* 25% of memory */ - segpcache_maxwindow = availrmem >> 2; - } else if (physmegs < 2048) { - /* 50% of memory */ - segpcache_maxwindow = availrmem >> 1; - } else { - /* no limit */ - segpcache_maxwindow = (pgcnt_t)-1; - } - } - seg_pmaxwindow = segpcache_maxwindow; seg_pinit_mem_config(); } /* * called by pageout if memory is low --- 1452,1461 ----
*** 1634,1644 **** } /* * Unmap a segment and free it from its associated address space. * This should be called by anybody who's finished with a whole segment's ! * mapping. Just calls SEGOP_UNMAP() on the whole mapping . It is the * responsibility of the segment driver to unlink the the segment * from the address space, and to free public and private data structures * associated with the segment. (This is typically done by a call to * seg_free()). */ --- 1599,1609 ---- } /* * Unmap a segment and free it from its associated address space. * This should be called by anybody who's finished with a whole segment's ! * mapping. Just calls segop_unmap() on the whole mapping . It is the * responsibility of the segment driver to unlink the the segment * from the address space, and to free public and private data structures * associated with the segment. (This is typically done by a call to * seg_free()). */
*** 1654,1667 **** /* Shouldn't have called seg_unmap if mapping isn't yet established */ ASSERT(seg->s_data != NULL); /* Unmap the whole mapping */ #ifdef DEBUG ! ret = SEGOP_UNMAP(seg, seg->s_base, seg->s_size); ASSERT(ret == 0); #else ! SEGOP_UNMAP(seg, seg->s_base, seg->s_size); #endif /* DEBUG */ } /* * Free the segment from its associated as. This should only be called --- 1619,1632 ---- /* Shouldn't have called seg_unmap if mapping isn't yet established */ ASSERT(seg->s_data != NULL); /* Unmap the whole mapping */ #ifdef DEBUG ! ret = segop_unmap(seg, seg->s_base, seg->s_size); ASSERT(ret == 0); #else ! segop_unmap(seg, seg->s_base, seg->s_size); #endif /* DEBUG */ } /* * Free the segment from its associated as. This should only be called
*** 1683,1693 **** /* * If the segment private data field is NULL, * then segment driver is not attached yet. */ if (seg->s_data != NULL) ! SEGOP_FREE(seg); mutex_destroy(&seg->s_pmtx); ASSERT(seg->s_phead.p_lnext == &seg->s_phead); ASSERT(seg->s_phead.p_lprev == &seg->s_phead); kmem_cache_free(seg_cache, seg); --- 1648,1658 ---- /* * If the segment private data field is NULL, * then segment driver is not attached yet. */ if (seg->s_data != NULL) ! segop_free(seg); mutex_destroy(&seg->s_pmtx); ASSERT(seg->s_phead.p_lnext == &seg->s_phead); ASSERT(seg->s_phead.p_lprev == &seg->s_phead); kmem_cache_free(seg_cache, seg);
*** 1852,1864 **** } return (swap); } /* ! * General not supported function for SEGOP_INHERIT */ - /* ARGSUSED */ int ! seg_inherit_notsup(struct seg *seg, caddr_t addr, size_t len, uint_t op) { return (ENOTSUP); } --- 1817,2015 ---- } return (swap); } /* ! * segop wrappers */ int ! segop_dup(struct seg *seg, struct seg *new) ! { ! VERIFY3P(seg->s_ops->dup, !=, NULL); ! ! return (seg->s_ops->dup(seg, new)); ! } ! ! int ! segop_unmap(struct seg *seg, caddr_t addr, size_t len) { + VERIFY3P(seg->s_ops->unmap, !=, NULL); + + return (seg->s_ops->unmap(seg, addr, len)); + } + + void + segop_free(struct seg *seg) + { + VERIFY3P(seg->s_ops->free, !=, NULL); + + seg->s_ops->free(seg); + } + + faultcode_t + segop_fault(struct hat *hat, struct seg *seg, caddr_t addr, size_t len, + enum fault_type type, enum seg_rw rw) + { + VERIFY3P(seg->s_ops->fault, !=, NULL); + + return (seg->s_ops->fault(hat, seg, addr, len, type, rw)); + } + + faultcode_t + segop_faulta(struct seg *seg, caddr_t addr) + { + VERIFY3P(seg->s_ops->faulta, !=, NULL); + + return (seg->s_ops->faulta(seg, addr)); + } + + int + segop_setprot(struct seg *seg, caddr_t addr, size_t len, uint_t prot) + { + VERIFY3P(seg->s_ops->setprot, !=, NULL); + + return (seg->s_ops->setprot(seg, addr, len, prot)); + } + + int + segop_checkprot(struct seg *seg, caddr_t addr, size_t len, uint_t prot) + { + VERIFY3P(seg->s_ops->checkprot, !=, NULL); + + return (seg->s_ops->checkprot(seg, addr, len, prot)); + } + + int + segop_kluster(struct seg *seg, caddr_t addr, ssize_t d) + { + VERIFY3P(seg->s_ops->kluster, !=, NULL); + + return (seg->s_ops->kluster(seg, addr, d)); + } + + int + segop_sync(struct seg *seg, caddr_t addr, size_t len, int atr, uint_t f) + { + VERIFY3P(seg->s_ops->sync, !=, NULL); + + return (seg->s_ops->sync(seg, addr, len, atr, f)); + } + + size_t + segop_incore(struct seg *seg, caddr_t addr, size_t len, char *v) + { + VERIFY3P(seg->s_ops->incore, !=, NULL); + + return (seg->s_ops->incore(seg, addr, len, v)); + } + + int + segop_lockop(struct seg *seg, caddr_t addr, size_t len, int atr, int op, + ulong_t *b, size_t p) + { + VERIFY3P(seg->s_ops->lockop, !=, NULL); + + return (seg->s_ops->lockop(seg, addr, len, atr, op, b, p)); + } + + int + segop_getprot(struct seg *seg, caddr_t addr, size_t len, uint_t *p) + { + VERIFY3P(seg->s_ops->getprot, !=, NULL); + + return (seg->s_ops->getprot(seg, addr, len, p)); + } + + u_offset_t + segop_getoffset(struct seg *seg, caddr_t addr) + { + VERIFY3P(seg->s_ops->getoffset, !=, NULL); + + return (seg->s_ops->getoffset(seg, addr)); + } + + int + segop_gettype(struct seg *seg, caddr_t addr) + { + VERIFY3P(seg->s_ops->gettype, !=, NULL); + + return (seg->s_ops->gettype(seg, addr)); + } + + int + segop_getvp(struct seg *seg, caddr_t addr, struct vnode **vpp) + { + VERIFY3P(seg->s_ops->getvp, !=, NULL); + + return (seg->s_ops->getvp(seg, addr, vpp)); + } + + int + segop_advise(struct seg *seg, caddr_t addr, size_t len, uint_t b) + { + VERIFY3P(seg->s_ops->advise, !=, NULL); + + return (seg->s_ops->advise(seg, addr, len, b)); + } + + void + segop_dump(struct seg *seg) + { + if (seg->s_ops->dump == NULL) + return; + + seg->s_ops->dump(seg); + } + + int + segop_pagelock(struct seg *seg, caddr_t addr, size_t len, struct page ***page, + enum lock_type type, enum seg_rw rw) + { + VERIFY3P(seg->s_ops->pagelock, !=, NULL); + + return (seg->s_ops->pagelock(seg, addr, len, page, type, rw)); + } + + int + segop_setpagesize(struct seg *seg, caddr_t addr, size_t len, uint_t szc) + { + if (seg->s_ops->setpagesize == NULL) + return (ENOTSUP); + + return (seg->s_ops->setpagesize(seg, addr, len, szc)); + } + + int + segop_getmemid(struct seg *seg, caddr_t addr, memid_t *mp) + { + if (seg->s_ops->getmemid == NULL) + return (ENODEV); + + return (seg->s_ops->getmemid(seg, addr, mp)); + } + + struct lgrp_mem_policy_info * + segop_getpolicy(struct seg *seg, caddr_t addr) + { + if (seg->s_ops->getpolicy == NULL) + return (NULL); + + return (seg->s_ops->getpolicy(seg, addr)); + } + + int + segop_capable(struct seg *seg, segcapability_t cap) + { + if (seg->s_ops->capable == NULL) + return (0); + + return (seg->s_ops->capable(seg, cap)); + } + + int + segop_inherit(struct seg *seg, caddr_t addr, size_t len, uint_t op) + { + if (seg->s_ops->inherit == NULL) return (ENOTSUP); + + return (seg->s_ops->inherit(seg, addr, len, op)); }