Commit graph

33 commits

Author SHA1 Message Date
cinap_lenrek 6f9838a6a5 kernel: make Page.txtflush into an array
To avoid a MAXMACH limit of 32 and make
txtflush into an array for the bitmap.

Provide portable macros for testing and clearing
the bits: needtxtflush(), donetxtflush().

On pc/pc64, define inittxtflush()/settxtflush()
as no-op macros, avoiding the storage overhead of
the txtflush array alltogether.
2022-01-16 19:25:11 +00:00
cinap_lenrek 295acd7e0d kernel: get rid of physical page bank array and use conf.mem[] instead
We can take advantage of the fact that xinit() allocates
kernel memory from conf.mem[] banks always at the beginning
of a bank, so the separate palloc.mem[] array can be eleminated
as we can calculate the amount of non-kernel memory like:

upages = cm->npage - (PGROUND(cm->klimit - cm->kbase)/BY2PG)

for the number of reserved kernel pages,
we provide the new function: ulong nkpages(Confmem*)

This eleminates the error case of running out of slots in
the array and avoids wasting memory in ports that have simple
memory configurations (compared to pc/pc64).
2021-04-02 20:23:25 +02:00
cinap_lenrek 29f60cace1 kernel: avoid palloc lock during mmurelease()
Previously, mmurelease() was always called with
palloc spinlock held.

This is unneccesary for some mmurelease()
implementations as they wont release pages
to the palloc pool.

This change removes pagechainhead() and
pagechaindone() and replaces them with just
freepages() call, which aquires the palloc
lock internally as needed.

freepages() avoids holding the palloc lock
while walking the linked list of pages,
avoding some lock contention.
2020-12-22 16:29:55 +01:00
cinap_lenrek 94916808dd kernel: remove unused segment argument in freepte() 2020-05-31 17:25:16 +02:00
cinap_lenrek dbfec06bf1 kernel: fix checkpages() and segflush() on SG_PHYSICAL type segments
do not touch s->map on SG_PHYSICAL type segments as they do
not have a pte map (s->mapsize == 0 && s->map == nil).

also remove the SG_PHYSICAL switch in freepte(), this is never
reached.
2020-05-10 16:54:42 +02:00
cinap_lenrek 61a062ee9f kernel: improve page reclaimation strategy and locking
when reclaiming pages from an image, always reclaim all
the hash chains equally. that way, we avoid being biased
towards the chains at the start of the Image.pghash[] array.

images can be in two states: active or inactive. inactive
images are the ones which are not used by program while
active ones aare.

when reclaiming pages, we should try to reclaim pages
from inactive images first and only if that set becomes
exhausted attempt to release text pages and attempt to
reclaim pages from active images.

when we run out of Image structures, it makes only sense
to reclaim pages from inactive images, as reclaiming pages
from active ones will never free any Image structures.

change putimage() to require a image already locked and
make it unlock the image. this avoids many pointless
unlock()/lock() sequences as all callers of putimage()
already had the image locked.
2020-04-26 19:54:46 +02:00
cinap_lenrek fe594760eb kernel: get rid of checkpagerefs() debugging
was only implemented by the pc kernel. does not
account pages used by the mount cache.
2019-05-01 12:40:27 +02:00
cinap_lenrek b452f8857f kernel: export freepages() function so it can be used in mmurelease() 2019-05-01 10:07:39 +02:00
cinap_lenrek 30c05fe3dd kernel: fix memory leak in checkpagerefs() debug function (thanks aiju) 2017-04-04 20:13:31 +02:00
cinap_lenrek 8ed25f24b7 kernel: various cleanups of imagereclaim(), pagereclaim(), freepages(), putimage()
imagereclaim(), pagereclaim():
- move imagereclaim() and pagereclaim() declarations to portfns.h
- consistently use ulong type for page counts
- name number of pages to free "pages" instead of "min"
- check for pages == 0 on entry

freepages():
- move pagechaindone() call to wakeup newpage() consumers inside
  palloc critical section.

putimage():
- use long type for refcount
2015-07-09 00:01:50 +02:00
cinap_lenrek 0dab8869ad kernel: ignore memory pages with singular kernel addresses
addresses va's of 0 and -BY2PG cause trouble with some memmove()/memset()
implementations and possibly other code because of the nil pointer
and end pointers wrapping to zero.
2015-06-18 12:15:33 +02:00
cinap_lenrek 64ed3658d2 kernel: add pagechaindone() to wakeup processes waiting for memory
we keep the details about palloc in page.c, providing pagechaindone()
for mmu code to be called after a series of pagechainhead() calls.
2015-06-15 17:40:47 +02:00
cinap_lenrek 8a3b388ffe kernel: implement separate wait queues for page allocation
give kernel processes and local disk file servers (procs
having noswap flag set) a clear advantage for page allocation
under starved condition by giving them ther own wait queue so
they get readied as soon as pages become available.
2015-06-15 16:05:00 +02:00
cinap_lenrek 972cd5e3fc kernel: get rid of auxpage() and preserve cache index bits in Page.va in mount cache
the mount cache uses Page.va to store cached range offset and
limit, but mips kernel uses cache index bits from Page.va to
maintain page coloring. Page.va was not initialized by auxpage().

this change removes auxpage() which was primarily used only
by the mount cache and use newpage() with cache file offset
page as va so we will get a page of the right color.

mount cache keeps the index bits intact by only using the top
and buttom PGSHIFT bits of Page.va for the range offset/limit.
2015-03-16 05:46:08 +01:00
cinap_lenrek 4d211fdd48 kernel: fix integer overflow in syssegflush(), segment code cleanup
mcountseg(), mfreeseg():
use Pte.first/last pointers when possible and avoid constructs
like s->map[i]->pages[j].

freepte():
do not zero entries in freepte(), the segment is going away and
here is no point in zeroing page pointers. hoist common code at
the top avoiding duplication.

segpage(), fixfault():
avoid load after store for Pte** pointer.

fixfault():
return -1 in default case to avoid the "used but not set" warning
for mmuphys and get rid of the useless initialization.

syssegflush():
due to len being unsigned, the pe = PGROUND(pe) can make "chunk"
bigger than len causing a overflow. rewrite the function and deal
with page alignment and errors at the beginning.

syssegflush(), segpage(), fixfault(), putseg(), relocateseg(),
mcountseg(), mfreeseg():
keep naming consistent.
2015-03-10 18:16:08 +01:00
cinap_lenrek eaf91d0f8e kernel: fix physical segment handling
ignore physical segments in mcountseg() and mfreeseg(). physical
segments are not backed by user pages, and doing putpage() on
physical segment pages in mfreeseg() is an error.

do now allow physical segemnts to be resized. the segment size
is only checked in segattach() to be within the physical segment!

ignore physical segments in portcountpagerefs() as pagenumber()
does not work on the malloced page structures of a physical segment.

get rid of Physseg.pgalloc() and Physseg.pgfree() indirection as
this was never used and if theres a need to do more efficient
allocation, it should be done in a portable way.
2015-03-03 13:08:29 +01:00
cinap_lenrek e8760ba636 kernel: make pagereclaim() a bit less stupid
put recently used pages at the head of ther image hash
chains, and reclaim pages from the tail first.
2015-02-07 03:01:59 +01:00
cinap_lenrek b8cf3cb879 kernel: reduce Page structure size by changing Page.cachectl[]
there are no kernels currently that do page coloring,
so the only use of cachectl[] is flushing the icache
(on arm and ppc).

on pc64, cachectl consumes 32 bytes in each page resulting
in over 200 megabytes of overhead for 32gb of ram with 4K
pages.

this change removes cachectl[] and adds txtflush ulong
that is set to ~0 by pio() to instruct putmmu() to flush
the icache.
2015-02-07 02:52:23 +01:00
cinap_lenrek d4d86df2ab kernel: new pagecache, remove Lock from page, use cmpswap for Ref instead of Lock
make the Page stucture less than half its original size by getting rid of
the Lock and the lru.

The Lock was required to coordinate the unchaining of pages that where
both cached and on the lru freelist.

now pages have a single next pointer that is used for palloc.head
freelist xor for page cache hash chains in Image.pghash[].

cached pages are not on the freelist anymore, but will be reclaimed
from images by the pager when the freelist runs out of pages.

each Image has its own 512 hash chains for cached page lookup. That is
2MB worth of pages and there should be no collisions for most text images.

page reclaiming can be done without holding palloc.lock as the Image is
the owner of the page hash chains protected by the Image's lock.

reclaiming Image structures can be done quickly by only reclaiming pages from
inactive images, that is images which are not currently in use by segments.

the Ref structure has no Lock anymore. Only a single long that is atomically
incremented or decremnted using cmpswap().

there are various other changes as a consequence code. and lots of pikeshedding,
sorry.
2014-06-22 15:12:45 +02:00
cinap_lenrek c9f91d5015 pc64: allocate palloc.pages from upages
the palloc.pages array takes arround 5% of the upages which
gives us:

16GB = ~0.8GB
32GB = ~1.6GB
64GB = ~3.2GB

we only have 2GB of address space above KZERO so this will not
work for long.

instead, pageinit() was altered to accept a preallocated memory
in palloc.pages. and preallocpages() in pc64/main.c allocates the
in upages memory, mapping it in the VMAP area (which has 512GB).

the drawback is that we cannot poke at Page structures now from
/proc/n/mem as the VMAP area is not accessible from it.
2014-06-01 03:13:58 +02:00
cinap_lenrek 66aa949039 kernel: fix printing wrong memory sizes in pageinit(), overflowed on amd64 (thanks aram) 2014-04-15 21:34:41 +02:00
cinap_lenrek 9405f4c95f kernel: getting rid of duppage() (thanks charles)
simplifying paging code by getting rid of duppage(). instead,
fixfault() now always makes a copy of the shared/cached page
and leaves the cache alone. newpage() uncaches pages as
neccesary.

thanks charles forsyth for the suggestion.

from http://9fans.net/archive/2014/03/26:

> It isn't needed at all. When a cached page is written, it's trying hard to
> replace the page in the cache by a new copy,
> to return the previously cached page. Instead, I copy the cached page and
> return the copy, which is what it already
> does in another instance. ...
2014-03-02 20:55:26 +01:00
cinap_lenrek 521a34d33b kernel: keep cached pages continuous at the end of the page list on imagereclaim()
imagereclaim() sabotaged itself by breaking the invariant
that cached pages are kept at the end of the page list.

once we made a hole of uncached pages, we would stop
reclaiming cached pages before it as the loop breaks
once it hits a uncached page. (we iterate backwards from
the tail to the head of the pagelist until pages have been
reclaimed or we hit a uncached page).

the solution is to move pages to the head of the pagelist
after removing them from the image cache.
2014-02-24 22:42:22 +01:00
cinap_lenrek 6c2e983d32 kernel: apply uintptr for ulong when a pointer is stored
this change is in preparation for amd64. the systab calling
convention was also changed to return uintptr (as segattach
returns a pointer) and the arguments are now passed as
va_list which handles amd64 arguments properly (all arguments
are passed in 64bit quantities on the stack, tho the upper
part will not be initialized when the element is smaller
than 8 bytes).

this is partial. xalloc needs to be converted in the future.
2014-01-20 00:47:55 +01:00
cinap_lenrek 2bc9e8e5e3 kernel: make image cache not hold onto the channel, remove nocache flag
the image cache should not hold onto the text file channel
when not neccesary. now, the image keeps track of the number
of page cache references in Image.pgref. if the number of
page cache references and Image.ref are equal, this means
all the references to this image are from the page cache.
so no segments are using this image. in that case, we can
close the channel, but keep the Image in the hash table.

when attachimage() finds our image, it will check if Image.c
is nil and reattach the channel to the image before it is
used.

the Image.nocache flag isnt needed anymore.
2013-11-08 22:31:26 +01:00
cinap_lenrek c7c7e7ee2a kernel: disable freelist page caching for executables run from uncached mount
the image cache has the property of keeping a channel
for the executable binary arround which prevents the
mountpoint from going away.

this can easily be reproduced by running:

@{rfork n; ramfs; cp /bin/echo /tmp; /tmp/echo}

observe how ramfs stays arround until the image is
reclaimed. the echo binary is also cached but is
unreachable from any namespace.

we now restrict the caching to mounts that use the client
cache (-C flag) only. this should always be the case
for /bin. places where this isnt the case might observe
a performance regression.
2013-10-25 02:42:35 +02:00
cinap_lenrek fcacce0f2f kernel: duppage cleanup
remove the sched() call and retry loop from duppage() and just
drop the page lock, then reacquire it after lock(&palloc).
2012-10-16 16:10:26 +02:00
cinap_lenrek 45b99937be kernel: cachedel() lock order, lookpage, cleanup
the lock order of page.Lock -> palloc.hashlock was
violated in cachedel() which is called from the
pager. change the code to do it in the right oder
to prevent deadlock.

change lookpage to retry on false hit. i assume that
a false hit means:

a) we'r low on memory -> cached page got uncached/reused

b) duppage() got called on the page, meaning theres another
cached copy in the image now.

paging in is expensive compared to the hashtable lookup, so
i think retrying is better.

cleanup fixfault, adding comments.
2012-10-16 14:12:21 +02:00
cinap_lenrek 77c21a062c kernel: remove duppage debug, add comments, cleanup 2012-02-16 18:04:08 +01:00
cinap_lenrek 083612b34e kernel: duppage checking 2012-02-16 11:38:50 +01:00
cinap_lenrek cf974eb852 fix kernel: pio()/mfreeseg() race 2011-08-24 14:43:15 +02:00
Taru Karttunen a9060cc06b Import sources from 2011-03-30 iso image - lib 2011-03-30 19:35:09 +03:00
Taru Karttunen e5888a1ffd Import sources from 2011-03-30 iso image 2011-03-30 15:46:40 +03:00