Annotation of linux/mm/swap.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  *  linux/mm/swap.c
                      3:  *
                      4:  *  (C) 1991  Linus Torvalds
                      5:  */
                      6: 
                      7: /*
                      8:  * This file should contain most things doing the swapping from/to disk.
                      9:  * Started 18.12.91
                     10:  */
                     11: 
                     12: #include <string.h>
                     13: 
                     14: #include <linux/mm.h>
                     15: #include <linux/sched.h>
                     16: #include <linux/head.h>
                     17: #include <linux/kernel.h>
                     18: 
                     19: #define SWAP_BITS (4096<<3)
                     20: 
                     21: #define bitop(name,op) \
                     22: static inline int name(char * addr,unsigned int nr) \
                     23: { \
                     24: int __res; \
                     25: __asm__ __volatile__("bt" op " %1,%2; adcl $0,%0" \
                     26: :"=g" (__res) \
                     27: :"r" (nr),"m" (*(addr)),"0" (0)); \
                     28: return __res; \
                     29: }
                     30: 
                     31: bitop(bit,"")
                     32: bitop(setbit,"s")
                     33: bitop(clrbit,"r")
                     34: 
                     35: static char * swap_bitmap = NULL;
                     36: int SWAP_DEV = 0;
                     37: 
                     38: /*
                     39:  * We never page the pages in task[0] - kernel memory.
                     40:  * We page all other pages.
                     41:  */
                     42: #define FIRST_VM_PAGE (TASK_SIZE>>12)
                     43: #define LAST_VM_PAGE (1024*1024)
                     44: #define VM_PAGES (LAST_VM_PAGE - FIRST_VM_PAGE)
                     45: 
                     46: static int get_swap_page(void)
                     47: {
                     48:        int nr;
                     49: 
                     50:        if (!swap_bitmap)
                     51:                return 0;
                     52:        for (nr = 1; nr < 32768 ; nr++)
                     53:                if (clrbit(swap_bitmap,nr))
                     54:                        return nr;
                     55:        return 0;
                     56: }
                     57: 
                     58: void swap_free(int swap_nr)
                     59: {
                     60:        if (!swap_nr)
                     61:                return;
                     62:        if (swap_bitmap && swap_nr < SWAP_BITS)
                     63:                if (!setbit(swap_bitmap,swap_nr))
                     64:                        return;
                     65:        printk("Swap-space bad (swap_free())\n\r");
                     66:        return;
                     67: }
                     68: 
                     69: void swap_in(unsigned long *table_ptr)
                     70: {
                     71:        int swap_nr;
                     72:        unsigned long page;
                     73: 
                     74:        if (!swap_bitmap) {
                     75:                printk("Trying to swap in without swap bit-map");
                     76:                return;
                     77:        }
                     78:        if (1 & *table_ptr) {
                     79:                printk("trying to swap in present page\n\r");
                     80:                return;
                     81:        }
                     82:        swap_nr = *table_ptr >> 1;
                     83:        if (!swap_nr) {
                     84:                printk("No swap page in swap_in\n\r");
                     85:                return;
                     86:        }
                     87:        if (!(page = get_free_page()))
                     88:                oom();
                     89:        read_swap_page(swap_nr, (char *) page);
                     90:        if (setbit(swap_bitmap,swap_nr))
                     91:                printk("swapping in multiply from same page\n\r");
                     92:        *table_ptr = page | (PAGE_DIRTY | 7);
                     93: }
                     94: 
                     95: int try_to_swap_out(unsigned long * table_ptr)
                     96: {
                     97:        unsigned long page;
                     98:        unsigned long swap_nr;
                     99: 
                    100:        page = *table_ptr;
                    101:        if (!(PAGE_PRESENT & page))
                    102:                return 0;
                    103:        if (page - LOW_MEM > PAGING_MEMORY)
                    104:                return 0;
                    105:        if (PAGE_DIRTY & page) {
                    106:                page &= 0xfffff000;
                    107:                if (mem_map[MAP_NR(page)] != 1)
                    108:                        return 0;
                    109:                if (!(swap_nr = get_swap_page()))
                    110:                        return 0;
                    111:                *table_ptr = swap_nr<<1;
                    112:                invalidate();
                    113:                write_swap_page(swap_nr, (char *) page);
                    114:                free_page(page);
                    115:                return 1;
                    116:        }
                    117:        *table_ptr = 0;
                    118:        invalidate();
                    119:        free_page(page);
                    120:        return 1;
                    121: }
                    122: 
                    123: /*
                    124:  * Ok, this has a rather intricate logic - the idea is to make good
                    125:  * and fast machine code. If we didn't worry about that, things would
                    126:  * be easier.
                    127:  */
                    128: int swap_out(void)
                    129: {
                    130:        static int dir_entry = FIRST_VM_PAGE>>10;
                    131:        static int page_entry = -1;
                    132:        int counter = VM_PAGES;
                    133:        int pg_table;
                    134: 
                    135:        while (counter>0) {
                    136:                pg_table = pg_dir[dir_entry];
                    137:                if (pg_table & 1)
                    138:                        break;
                    139:                counter -= 1024;
                    140:                dir_entry++;
                    141:                if (dir_entry >= 1024)
                    142:                        dir_entry = FIRST_VM_PAGE>>10;
                    143:        }
                    144:        pg_table &= 0xfffff000;
                    145:        while (counter-- > 0) {
                    146:                page_entry++;
                    147:                if (page_entry >= 1024) {
                    148:                        page_entry = 0;
                    149:                repeat:
                    150:                        dir_entry++;
                    151:                        if (dir_entry >= 1024)
                    152:                                dir_entry = FIRST_VM_PAGE>>10;
                    153:                        pg_table = pg_dir[dir_entry];
                    154:                        if (!(pg_table&1))
                    155:                                if ((counter -= 1024) > 0)
                    156:                                        goto repeat;
                    157:                                else
                    158:                                        break;
                    159:                        pg_table &= 0xfffff000;
                    160:                }
                    161:                if (try_to_swap_out(page_entry + (unsigned long *) pg_table))
                    162:                        return 1;
                    163:        }
                    164:        printk("Out of swap-memory\n\r");
                    165:        return 0;
                    166: }
                    167: 
                    168: /*
                    169:  * Get physical address of first (actually last :-) free page, and mark it
                    170:  * used. If no free pages left, return 0.
                    171:  */
                    172: unsigned long get_free_page(void)
                    173: {
                    174: register unsigned long __res asm("ax");
                    175: 
                    176: repeat:
                    177:        __asm__("std ; repne ; scasb\n\t"
                    178:                "jne 1f\n\t"
                    179:                "movb $1,1(%%edi)\n\t"
                    180:                "sall $12,%%ecx\n\t"
                    181:                "addl %2,%%ecx\n\t"
                    182:                "movl %%ecx,%%edx\n\t"
                    183:                "movl $1024,%%ecx\n\t"
                    184:                "leal 4092(%%edx),%%edi\n\t"
                    185:                "rep ; stosl\n\t"
                    186:                "movl %%edx,%%eax\n"
                    187:                "1:"
                    188:                :"=a" (__res)
                    189:                :"0" (0),"i" (LOW_MEM),"c" (PAGING_PAGES),
                    190:                "D" (mem_map+PAGING_PAGES-1)
                    191:                :"di","cx","dx");
                    192:        if (__res >= HIGH_MEMORY)
                    193:                goto repeat;
                    194:        if (!__res && swap_out())
                    195:                goto repeat;
                    196:        return __res;
                    197: }
                    198: 
                    199: void init_swapping(void)
                    200: {
                    201:        extern int *blk_size[];
                    202:        int swap_size,i,j;
                    203: 
                    204:        if (!SWAP_DEV)
                    205:                return;
                    206:        if (!blk_size[MAJOR(SWAP_DEV)]) {
                    207:                printk("Unable to get size of swap device\n\r");
                    208:                return;
                    209:        }
                    210:        swap_size = blk_size[MAJOR(SWAP_DEV)][MINOR(SWAP_DEV)];
                    211:        if (!swap_size)
                    212:                return;
                    213:        if (swap_size < 100) {
                    214:                printk("Swap device too small (%d blocks)\n\r",swap_size);
                    215:                return;
                    216:        }
                    217:        swap_size >>= 2;
                    218:        if (swap_size > SWAP_BITS)
                    219:                swap_size = SWAP_BITS;
                    220:        swap_bitmap = (char *) get_free_page();
                    221:        if (!swap_bitmap) {
                    222:                printk("Unable to start swapping: out of memory :-)\n\r");
                    223:                return;
                    224:        }
                    225:        read_swap_page(0,swap_bitmap);
                    226:        if (strncmp("SWAP-SPACE",swap_bitmap+4086,10)) {
                    227:                printk("Unable to find swap-space signature\n\r");
                    228:                free_page((long) swap_bitmap);
                    229:                swap_bitmap = NULL;
                    230:                return;
                    231:        }
                    232:        memset(swap_bitmap+4086,0,10);
                    233:        for (i = 0 ; i < SWAP_BITS ; i++) {
                    234:                if (i == 1)
                    235:                        i = swap_size;
                    236:                if (bit(swap_bitmap,i)) {
                    237:                        printk("Bad swap-space bit-map\n\r");
                    238:                        free_page((long) swap_bitmap);
                    239:                        swap_bitmap = NULL;
                    240:                        return;
                    241:                }
                    242:        }
                    243:        j = 0;
                    244:        for (i = 1 ; i < swap_size ; i++)
                    245:                if (bit(swap_bitmap,i))
                    246:                        j++;
                    247:        if (!j) {
                    248:                free_page((long) swap_bitmap);
                    249:                swap_bitmap = NULL;
                    250:                return;
                    251:        }
                    252:        printk("Swap device ok: %d pages (%d bytes) swap-space\n\r",j,j*4096);
                    253: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.