add directory kernel
This commit is contained in:
253
kernel/0.1x/linux-0.12/mm/swap.c
Normal file
253
kernel/0.1x/linux-0.12/mm/swap.c
Normal file
@@ -0,0 +1,253 @@
|
||||
/*
|
||||
* linux/mm/swap.c
|
||||
*
|
||||
* (C) 1991 Linus Torvalds
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file should contain most things doing the swapping from/to disk.
|
||||
* Started 18.12.91
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <linux/mm.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/head.h>
|
||||
#include <linux/kernel.h>
|
||||
|
||||
#define SWAP_BITS (4096<<3)
|
||||
|
||||
#define bitop(name,op) \
|
||||
static inline int name(char * addr,unsigned int nr) \
|
||||
{ \
|
||||
int __res; \
|
||||
__asm__ __volatile__("bt" op " %1,%2; adcl $0,%0" \
|
||||
:"=g" (__res) \
|
||||
:"r" (nr),"m" (*(addr)),"0" (0)); \
|
||||
return __res; \
|
||||
}
|
||||
|
||||
bitop(bit,"")
|
||||
bitop(setbit,"s")
|
||||
bitop(clrbit,"r")
|
||||
|
||||
static char * swap_bitmap = NULL;
|
||||
int SWAP_DEV = 0;
|
||||
|
||||
/*
|
||||
* We never page the pages in task[0] - kernel memory.
|
||||
* We page all other pages.
|
||||
*/
|
||||
#define FIRST_VM_PAGE (TASK_SIZE>>12)
|
||||
#define LAST_VM_PAGE (1024*1024)
|
||||
#define VM_PAGES (LAST_VM_PAGE - FIRST_VM_PAGE)
|
||||
|
||||
static int get_swap_page(void)
|
||||
{
|
||||
int nr;
|
||||
|
||||
if (!swap_bitmap)
|
||||
return 0;
|
||||
for (nr = 1; nr < 32768 ; nr++)
|
||||
if (clrbit(swap_bitmap,nr))
|
||||
return nr;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void swap_free(int swap_nr)
|
||||
{
|
||||
if (!swap_nr)
|
||||
return;
|
||||
if (swap_bitmap && swap_nr < SWAP_BITS)
|
||||
if (!setbit(swap_bitmap,swap_nr))
|
||||
return;
|
||||
printk("Swap-space bad (swap_free())\n\r");
|
||||
return;
|
||||
}
|
||||
|
||||
void swap_in(unsigned long *table_ptr)
|
||||
{
|
||||
int swap_nr;
|
||||
unsigned long page;
|
||||
|
||||
if (!swap_bitmap) {
|
||||
printk("Trying to swap in without swap bit-map");
|
||||
return;
|
||||
}
|
||||
if (1 & *table_ptr) {
|
||||
printk("trying to swap in present page\n\r");
|
||||
return;
|
||||
}
|
||||
swap_nr = *table_ptr >> 1;
|
||||
if (!swap_nr) {
|
||||
printk("No swap page in swap_in\n\r");
|
||||
return;
|
||||
}
|
||||
if (!(page = get_free_page()))
|
||||
oom();
|
||||
read_swap_page(swap_nr, (char *) page);
|
||||
if (setbit(swap_bitmap,swap_nr))
|
||||
printk("swapping in multiply from same page\n\r");
|
||||
*table_ptr = page | (PAGE_DIRTY | 7);
|
||||
}
|
||||
|
||||
int try_to_swap_out(unsigned long * table_ptr)
|
||||
{
|
||||
unsigned long page;
|
||||
unsigned long swap_nr;
|
||||
|
||||
page = *table_ptr;
|
||||
if (!(PAGE_PRESENT & page))
|
||||
return 0;
|
||||
if (page - LOW_MEM > PAGING_MEMORY)
|
||||
return 0;
|
||||
if (PAGE_DIRTY & page) {
|
||||
page &= 0xfffff000;
|
||||
if (mem_map[MAP_NR(page)] != 1)
|
||||
return 0;
|
||||
if (!(swap_nr = get_swap_page()))
|
||||
return 0;
|
||||
*table_ptr = swap_nr<<1;
|
||||
invalidate();
|
||||
write_swap_page(swap_nr, (char *) page);
|
||||
free_page(page);
|
||||
return 1;
|
||||
}
|
||||
*table_ptr = 0;
|
||||
invalidate();
|
||||
free_page(page);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Ok, this has a rather intricate logic - the idea is to make good
|
||||
* and fast machine code. If we didn't worry about that, things would
|
||||
* be easier.
|
||||
*/
|
||||
int swap_out(void)
|
||||
{
|
||||
static int dir_entry = FIRST_VM_PAGE>>10;
|
||||
static int page_entry = -1;
|
||||
int counter = VM_PAGES;
|
||||
int pg_table;
|
||||
|
||||
while (counter>0) {
|
||||
pg_table = pg_dir[dir_entry];
|
||||
if (pg_table & 1)
|
||||
break;
|
||||
counter -= 1024;
|
||||
dir_entry++;
|
||||
if (dir_entry >= 1024)
|
||||
dir_entry = FIRST_VM_PAGE>>10;
|
||||
}
|
||||
pg_table &= 0xfffff000;
|
||||
while (counter-- > 0) {
|
||||
page_entry++;
|
||||
if (page_entry >= 1024) {
|
||||
page_entry = 0;
|
||||
repeat:
|
||||
dir_entry++;
|
||||
if (dir_entry >= 1024)
|
||||
dir_entry = FIRST_VM_PAGE>>10;
|
||||
pg_table = pg_dir[dir_entry];
|
||||
if (!(pg_table&1))
|
||||
if ((counter -= 1024) > 0)
|
||||
goto repeat;
|
||||
else
|
||||
break;
|
||||
pg_table &= 0xfffff000;
|
||||
}
|
||||
if (try_to_swap_out(page_entry + (unsigned long *) pg_table))
|
||||
return 1;
|
||||
}
|
||||
printk("Out of swap-memory\n\r");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get physical address of first (actually last :-) free page, and mark it
|
||||
* used. If no free pages left, return 0.
|
||||
*/
|
||||
unsigned long get_free_page(void)
|
||||
{
|
||||
register unsigned long __res asm("ax");
|
||||
|
||||
repeat:
|
||||
__asm__("std ; repne ; scasb\n\t"
|
||||
"jne 1f\n\t"
|
||||
"movb $1,1(%%edi)\n\t"
|
||||
"sall $12,%%ecx\n\t"
|
||||
"addl %2,%%ecx\n\t"
|
||||
"movl %%ecx,%%edx\n\t"
|
||||
"movl $1024,%%ecx\n\t"
|
||||
"leal 4092(%%edx),%%edi\n\t"
|
||||
"rep ; stosl\n\t"
|
||||
"movl %%edx,%%eax\n"
|
||||
"1:"
|
||||
:"=a" (__res)
|
||||
:"0" (0),"i" (LOW_MEM),"c" (PAGING_PAGES),
|
||||
"D" (mem_map+PAGING_PAGES-1)
|
||||
:"di","cx","dx");
|
||||
if (__res >= HIGH_MEMORY)
|
||||
goto repeat;
|
||||
if (!__res && swap_out())
|
||||
goto repeat;
|
||||
return __res;
|
||||
}
|
||||
|
||||
void init_swapping(void)
|
||||
{
|
||||
extern int *blk_size[];
|
||||
int swap_size,i,j;
|
||||
|
||||
if (!SWAP_DEV)
|
||||
return;
|
||||
if (!blk_size[MAJOR(SWAP_DEV)]) {
|
||||
printk("Unable to get size of swap device\n\r");
|
||||
return;
|
||||
}
|
||||
swap_size = blk_size[MAJOR(SWAP_DEV)][MINOR(SWAP_DEV)];
|
||||
if (!swap_size)
|
||||
return;
|
||||
if (swap_size < 100) {
|
||||
printk("Swap device too small (%d blocks)\n\r",swap_size);
|
||||
return;
|
||||
}
|
||||
swap_size >>= 2;
|
||||
if (swap_size > SWAP_BITS)
|
||||
swap_size = SWAP_BITS;
|
||||
swap_bitmap = (char *) get_free_page();
|
||||
if (!swap_bitmap) {
|
||||
printk("Unable to start swapping: out of memory :-)\n\r");
|
||||
return;
|
||||
}
|
||||
read_swap_page(0,swap_bitmap);
|
||||
if (strncmp("SWAP-SPACE",swap_bitmap+4086,10)) {
|
||||
printk("Unable to find swap-space signature\n\r");
|
||||
free_page((long) swap_bitmap);
|
||||
swap_bitmap = NULL;
|
||||
return;
|
||||
}
|
||||
memset(swap_bitmap+4086,0,10);
|
||||
for (i = 0 ; i < SWAP_BITS ; i++) {
|
||||
if (i == 1)
|
||||
i = swap_size;
|
||||
if (bit(swap_bitmap,i)) {
|
||||
printk("Bad swap-space bit-map\n\r");
|
||||
free_page((long) swap_bitmap);
|
||||
swap_bitmap = NULL;
|
||||
return;
|
||||
}
|
||||
}
|
||||
j = 0;
|
||||
for (i = 1 ; i < swap_size ; i++)
|
||||
if (bit(swap_bitmap,i))
|
||||
j++;
|
||||
if (!j) {
|
||||
free_page((long) swap_bitmap);
|
||||
swap_bitmap = NULL;
|
||||
return;
|
||||
}
|
||||
printk("Swap device ok: %d pages (%d bytes) swap-space\n\r",j,j*4096);
|
||||
}
|
||||
Reference in New Issue
Block a user