oskit/oskit-20020317/svm/svm_pager_init.c

269 lines
6.7 KiB
C
Executable File

/*
* Copyright (c) 1996, 1998, 1999 University of Utah and the Flux Group.
* All rights reserved.
*
* This file is part of the Flux OSKit. The OSKit is free software, also known
* as "open source;" you can redistribute it and/or modify it under the terms
* of the GNU General Public License (GPL), version 2, as published by the Free
* Software Foundation (FSF). To explore alternate licensing terms, contact
* the University of Utah at csl-dist@cs.utah.edu or +1-801-585-3271.
*
* The OSKit is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GPL for more details. You should have
* received a copy of the GPL along with the OSKit; see the file COPYING. If
* not, write to the FSF, 59 Temple Place #330, Boston, MA 02111-1307, USA.
*/
#include "svm_internal.h"
#include <oskit/debug.h>
#include <oskit/c/malloc.h>
#include <oskit/io/blkio.h>
#include <oskit/dev/dev.h>
#include <oskit/dev/linux.h>
#include <oskit/diskpart/diskpart.h>
#include <oskit/machine/physmem.h>
/*
* The ptov table stores physical to virtual translations (inverse map).
* Used by the pageout code to implement a simple clock-sweep of the
* physical pages to find candidates for pageout.
*/
oskit_addr_t *svm_ptov;
int svm_ptov_count;
/*
* This table is kinda silly. Basically a free list of disk pages,
* linked by table index.
*/
int *svm_freepages;
int svm_nextfreepage;
/*
* Water marks for pageout. If the lmm has less than this amount
* of free memory, pageout pages. Set as a percentage of real memory.
*/
oskit_size_t svm_lowwater;
oskit_size_t svm_highwater;
/*
* ABSIO or BLKIO of the swap device.
*
* Disk partitions are blkio's, but do not export an absio interface,
* but we still want to support absio interfaces. I know these
* interfacs are identical, but is it wise to depend on that? For now,
* lets assume they are different.
*/
oskit_absio_t *svm_pagerabsio;
oskit_blkio_t *svm_pagerblkio;
/*
* Flag.
*/
int svm_paging;
int
svm_pager_init(oskit_absio_t *absio)
{
int psize;
int dcount, dsize, i;
oskit_off_t disk_size;
void *handle;
oskit_iunknown_t *iunknown = (oskit_iunknown_t *) absio;
if (svm_paging)
panic("svm_pager_init: "
"Already setup for paging to bio:%p\n",
(svm_pagerabsio == ((oskit_absio_t *) 0)) ?
(void *) svm_pagerblkio : (void *) svm_pagerabsio);
/*
* Make sure svm_init is done, but without the absio.
*/
if (!svm_enabled)
svm_init((oskit_absio_t *) 0);
/*
* Make sure we got an absio or a blkio. We add a reference.
*/
if (! oskit_iunknown_query(iunknown, &oskit_absio_iid, &handle))
svm_pagerabsio = (oskit_absio_t *) handle;
else if (! oskit_iunknown_query(iunknown, &oskit_blkio_iid, &handle))
svm_pagerblkio = (oskit_blkio_t *) handle;
else
return OSKIT_EINVAL;
/*
* Allocate the ptov table. We can use just plain old malloc.
*/
svm_ptov_count = (phys_mem_max - phys_mem_min) / PAGE_SIZE;
psize = sizeof(oskit_addr_t) * svm_ptov_count;
if ((svm_ptov = (oskit_addr_t *) smalloc(psize)) == NULL)
panic("svm_pager_init: Could not smalloc ptov table");
#ifdef DEBUG_SVM_PAGEOUT
printf("svm_pager_init: "
"Allocated ptov: 0x%x %d bytes\n", (int) svm_ptov, psize);
#endif
for (i = 0; i < svm_ptov_count; i++)
svm_ptov[i] = SVM_NULL_PTOV;
/*
* Make sure at least 20% of memory is available.
*/
svm_lowwater = (svm_physmem_avail() / 10) * 2;
svm_highwater = (svm_physmem_avail() / 10) * 3;
#ifdef DEBUG_SVM_PAGEOUT
printf("svm_pager_init: "
"Low water = %d bytes, High water = %d bytes\n",
svm_lowwater, svm_highwater);
#endif
if (svm_pagerblkio)
oskit_blkio_getsize(svm_pagerblkio, &disk_size);
else
oskit_absio_getsize(svm_pagerabsio, &disk_size);
#ifdef DEBUG_SVM
printf("svm_pager_init: disksize:%d\n", (int) disk_size);
#endif
/*
* Allocate the freepage table. We can use just plain old malloc.
*/
dcount = (int) disk_size / PAGE_SIZE;
dsize = sizeof(int) * dcount;
if ((svm_freepages = (int *) smalloc(dsize)) == NULL)
panic("svm_pager_init: Could not smalloc freepage table");
printf("svm_pager_init: "
"Allocated freepages: 0x%x %d bytes\n",
(int) svm_freepages, dsize);
/*
* Build the freepage list.
*/
svm_nextfreepage = 0;
for (i = 0; i < (dcount - 1); i++)
svm_freepages[i] = i + 1;
svm_freepages[dcount - 1] = -1;
{
oskit_u64_t before, after;
before = get_tsc();
after = get_tsc();
printf("svm_pager_init: Timer: %d\n", (int) (after - before));
}
svm_paging = 1;
return 0;
}
/*
* Allocate a diskpage from the free list.
*/
int
svm_getdiskpage()
{
int diskpage;
if ((diskpage = svm_nextfreepage) == -1)
panic("svm_getfreepage: No free disk pages\n");
svm_nextfreepage = svm_freepages[diskpage];
svm_freepages[diskpage] = -1;
return diskpage;
}
/*
* Deallocate a diskpage.
*/
void
svm_freediskpage(int diskpage)
{
svm_freepages[diskpage] = svm_nextfreepage;
svm_nextfreepage = diskpage;
}
int svm_swapread_time, svm_swapwrite_time;
int svm_swapwrite_count, svm_swapread_count;
/*
* Read and write pages to the swap partition.
*/
int
svm_swapwrite(int diskpage, oskit_addr_t pa)
{
int err, amt;
oskit_off_t offset = ptob(diskpage);
oskit_size_t size = PAGE_SIZE;
oskit_u32_t before, after;
#ifdef DEBUG_SVM
printf("svm_swapwrite: Writing %d bytes at offset %d 0x%x\n",
size, (int) offset, (int) pa);
#endif
before = get_tsc();
if (svm_pagerabsio)
err = oskit_absio_write(svm_pagerabsio,
(void *)pa, offset, size, &amt);
else
err = oskit_blkio_write(svm_pagerblkio,
(void *)pa, offset, size, &amt);
after = get_tsc();
if (after > before) {
svm_swapwrite_time += (int) ((after - before) / 200);
svm_swapwrite_count++;
}
if (err || amt != size) {
printf(" Read WRITE %08x %d\n", err, amt);
return(1);
}
#ifdef DEBUG_SVM
printf("Write done\n");
#endif
return 0;
}
int
svm_swapread(int diskpage, oskit_addr_t pa)
{
int err, amt;
oskit_off_t offset = ptob(diskpage);
oskit_size_t size = PAGE_SIZE;
oskit_u32_t before, after;
#ifdef DEBUG_SVM
printf("Reading %d bytes at offset %d 0x%x\n",
size, (int) offset, (int) pa);
#endif
before = get_tsc();
if (svm_pagerabsio)
err = oskit_absio_read(svm_pagerabsio,
(void *)pa, offset, size, &amt);
else
err = oskit_blkio_read(svm_pagerblkio,
(void *)pa, offset, size, &amt);
after = get_tsc();
if (after > before) {
svm_swapread_time += (int) ((after - before) / 200);
svm_swapread_count++;
}
if (err || amt != size) {
printf(" Read READ %08x %d\n", err, amt);
return(1);
}
#ifdef DEBUG_SVM
printf("Read done\n");
#endif
return 0;
}