⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 stram.c

📁 该文件是rt_linux
💻 C
📖 第 1 页 / 共 3 页
字号:
		 * __get_dma_pages() */		addr = (void *)__get_dma_pages(GFP_KERNEL, get_order(size));		flags = BLOCK_GFP;		DPRINTK( "atari_stram_alloc: after mem_init, swapping off, "				 "get_pages=%p\n", addr );	}	if (addr) {		if (!(block = add_region( addr, size ))) {			/* out of memory for BLOCK structure :-( */			DPRINTK( "atari_stram_alloc: out of mem for BLOCK -- "					 "freeing again\n" );#ifdef CONFIG_STRAM_SWAP			if (flags == BLOCK_INSWAP)				free_stram_region( SWAP_NR(addr), N_PAGES(size) );			else#endif				free_pages((unsigned long)addr, get_order(size));			return( NULL );		}		block->owner = owner;		block->flags |= flags;	}	return( addr );}void atari_stram_free( void *addr ){	BLOCK *block;	DPRINTK( "atari_stram_free(addr=%p)\n", addr );	if (!(block = find_region( addr ))) {		printk( KERN_ERR "Attempt to free non-allocated ST-RAM block at %p "				"from %p\n", addr, __builtin_return_address(0) );		return;	}	DPRINTK( "atari_stram_free: found block (%p): size=%08lx, owner=%s, "			 "flags=%02x\n", block, block->size, block->owner, block->flags );	#ifdef CONFIG_STRAM_SWAP	if (!max_swap_size) {#endif		if (block->flags & BLOCK_GFP) {			DPRINTK("atari_stram_free: is kmalloced, order_size=%d\n",				get_order(block->size));			free_pages((unsigned long)addr, get_order(block->size));		}		else			goto fail;#ifdef CONFIG_STRAM_SWAP	}	else if (block->flags & BLOCK_INSWAP) {		DPRINTK( "atari_stram_free: is swap-alloced\n" );		free_stram_region( SWAP_NR(block->start), N_PAGES(block->size) );	}	else		goto fail;#endif	remove_region( block );	return;  fail:	printk( KERN_ERR "atari_stram_free: cannot free block at %p "			"(called from %p)\n", addr, __builtin_return_address(0) );}#ifdef CONFIG_STRAM_SWAP/* ------------------------------------------------------------------------ *//*						   Main Swapping Functions							*//* ------------------------------------------------------------------------ *//* * Initialize ST-RAM swap device * (lots copied and modified from sys_swapon() in mm/swapfile.c) */static int __init swap_init(void *start_mem, void *swap_data){	static struct dentry fake_dentry;	static struct vfsmount fake_vfsmnt;	struct swap_info_struct *p;	struct inode swap_inode;	unsigned int type;	void *addr;	int i, j, k, prev;	DPRINTK("swap_init(start_mem=%p, swap_data=%p)\n",		start_mem, swap_data);		/* need at least one page for swapping to (and this also isn't very	 * much... :-) */	if (swap_end - swap_start < 2*PAGE_SIZE) {		printk( KERN_WARNING "stram_swap_init: swap space too small\n" );		return( 0 );	}		/* find free slot in swap_info */	for( p = swap_info, type = 0; type < nr_swapfiles; type++, p++ )		if (!(p->flags & SWP_USED))			break;	if (type >= MAX_SWAPFILES) {		printk( KERN_WARNING "stram_swap_init: max. number of "				"swap devices exhausted\n" );		return( 0 );	}	if (type >= nr_swapfiles)		nr_swapfiles = type+1;	stram_swap_info = p;	stram_swap_type = type;	/* fake some dir cache entries to give us some name in /dev/swaps */	fake_dentry.d_parent = &fake_dentry;	fake_dentry.d_name.name = "stram (internal)";	fake_dentry.d_name.len = 16;	fake_vfsmnt.mnt_parent = &fake_vfsmnt;		p->flags        = SWP_USED;	p->swap_file    = &fake_dentry;	p->swap_vfsmnt  = &fake_vfsmnt;	p->swap_device  = 0;	p->swap_map	= swap_data;	p->cluster_nr   = 0;	p->next         = -1;	p->prio         = 0x7ff0;	/* a rather high priority, but not the higest								 * to give the user a chance to override */	/* call stram_open() directly, avoids at least the overhead in	 * constructing a dummy file structure... */	p->swap_device = MKDEV( STRAM_MAJOR, STRAM_MINOR );	swap_inode.i_rdev = p->swap_device;	stram_open( &swap_inode, MAGIC_FILE_P );	p->max = SWAP_NR(swap_end);	/* initialize swap_map: set regions that are already allocated or belong	 * to kernel data space to SWAP_MAP_BAD, otherwise to free */	j = 0; /* # of free pages */	k = 0; /* # of already allocated pages (from pre-mem_init stram_alloc()) */	p->lowest_bit = 0;	p->highest_bit = 0;	for( i = 1, addr = SWAP_ADDR(1); i < p->max;		 i++, addr += PAGE_SIZE ) {		if (in_some_region( addr )) {			p->swap_map[i] = SWAP_MAP_BAD;			++k;		}		else if (kernel_in_stram && addr < start_mem ) {			p->swap_map[i] = SWAP_MAP_BAD;		}		else {			p->swap_map[i] = 0;			++j;			if (!p->lowest_bit) p->lowest_bit = i;			p->highest_bit = i;		}	}	/* first page always reserved (and doesn't really belong to swap space) */	p->swap_map[0] = SWAP_MAP_BAD;	/* now swapping to this device ok */	p->pages = j + k;	swap_list_lock();	nr_swap_pages += j;	p->flags = SWP_WRITEOK;	/* insert swap space into swap_list */	prev = -1;	for (i = swap_list.head; i >= 0; i = swap_info[i].next) {		if (p->prio >= swap_info[i].prio) {			break;		}		prev = i;	}	p->next = i;	if (prev < 0) {		swap_list.head = swap_list.next = p - swap_info;	} else {		swap_info[prev].next = p - swap_info;	}	swap_list_unlock();	printk( KERN_INFO "Using %dk (%d pages) of ST-RAM as swap space.\n",			p->pages << 2, p->pages );	return( 1 );}/* * The swap entry has been read in advance, and we return 1 to indicate * that the page has been used or is no longer needed. * * Always set the resulting pte to be nowrite (the same as COW pages * after one process has exited).  We don't know just how many PTEs will * share this swap entry, so be cautious and let do_wp_page work out * what to do if a write is requested later. */static inline void unswap_pte(struct vm_area_struct * vma, unsigned long			      address, pte_t *dir, swp_entry_t entry,			      struct page *page){	pte_t pte = *dir;	if (pte_none(pte))		return;	if (pte_present(pte)) {		/* If this entry is swap-cached, then page must already                   hold the right address for any copies in physical                   memory */		if (pte_page(pte) != page)			return;		/* We will be removing the swap cache in a moment, so... */		set_pte(dir, pte_mkdirty(pte));		return;	}	if (pte_val(pte) != entry.val)		return;	DPRINTK("unswap_pte: replacing entry %08lx by new page %p",		entry.val, page);	set_pte(dir, pte_mkdirty(mk_pte(page, vma->vm_page_prot)));	swap_free(entry);	get_page(page);	++vma->vm_mm->rss;}static inline void unswap_pmd(struct vm_area_struct * vma, pmd_t *dir,			      unsigned long address, unsigned long size,			      unsigned long offset, swp_entry_t entry,			      struct page *page){	pte_t * pte;	unsigned long end;	if (pmd_none(*dir))		return;	if (pmd_bad(*dir)) {		pmd_ERROR(*dir);		pmd_clear(dir);		return;	}	pte = pte_offset(dir, address);	offset += address & PMD_MASK;	address &= ~PMD_MASK;	end = address + size;	if (end > PMD_SIZE)		end = PMD_SIZE;	do {		unswap_pte(vma, offset+address-vma->vm_start, pte, entry, page);		address += PAGE_SIZE;		pte++;	} while (address < end);}static inline void unswap_pgd(struct vm_area_struct * vma, pgd_t *dir,			      unsigned long address, unsigned long size,			      swp_entry_t entry, struct page *page){	pmd_t * pmd;	unsigned long offset, end;	if (pgd_none(*dir))		return;	if (pgd_bad(*dir)) {		pgd_ERROR(*dir);		pgd_clear(dir);		return;	}	pmd = pmd_offset(dir, address);	offset = address & PGDIR_MASK;	address &= ~PGDIR_MASK;	end = address + size;	if (end > PGDIR_SIZE)		end = PGDIR_SIZE;	do {		unswap_pmd(vma, pmd, address, end - address, offset, entry,			   page);		address = (address + PMD_SIZE) & PMD_MASK;		pmd++;	} while (address < end);}static void unswap_vma(struct vm_area_struct * vma, pgd_t *pgdir,		       swp_entry_t entry, struct page *page){	unsigned long start = vma->vm_start, end = vma->vm_end;	do {		unswap_pgd(vma, pgdir, start, end - start, entry, page);		start = (start + PGDIR_SIZE) & PGDIR_MASK;		pgdir++;	} while (start < end);}static void unswap_process(struct mm_struct * mm, swp_entry_t entry, 			   struct page *page){	struct vm_area_struct* vma;	/*	 * Go through process' page directory.	 */	if (!mm)		return;	for (vma = mm->mmap; vma; vma = vma->vm_next) {		pgd_t * pgd = pgd_offset(mm, vma->vm_start);		unswap_vma(vma, pgd, entry, page);	}}static int unswap_by_read(unsigned short *map, unsigned long max,			  unsigned long start, unsigned long n_pages){	struct task_struct *p;	struct page *page;	swp_entry_t entry;	unsigned long i;	DPRINTK( "unswapping %lu..%lu by reading in\n",			 start, start+n_pages-1 );	for( i = start; i < start+n_pages; ++i ) {		if (map[i] == SWAP_MAP_BAD) {			printk( KERN_ERR "get_stram_region: page %lu already "					"reserved??\n", i );			continue;		}		if (map[i]) {			entry = SWP_ENTRY(stram_swap_type, i);			DPRINTK("unswap: map[i=%lu]=%u nr_swap=%u\n",				i, map[i], nr_swap_pages);			swap_device_lock(stram_swap_info);			map[i]++;			swap_device_unlock(stram_swap_info);			/* Get a page for the entry, using the existing			   swap cache page if there is one.  Otherwise,			   get a clean page and read the swap into it. */			page = read_swap_cache_async(entry);			if (!page) {				swap_free(entry);				return -ENOMEM;			}			read_lock(&tasklist_lock);			for_each_task(p)				unswap_process(p->mm, entry, page);			read_unlock(&tasklist_lock);			shmem_unuse(entry, page);			/* Now get rid of the extra reference to the			   temporary page we've been using. */			if (PageSwapCache(page))				delete_from_swap_cache(page);			__free_page(page);	#ifdef DO_PROC			stat_swap_force++;	#endif		}		DPRINTK( "unswap: map[i=%lu]=%u nr_swap=%u\n",				 i, map[i], nr_swap_pages );		swap_list_lock();		swap_device_lock(stram_swap_info);		map[i] = SWAP_MAP_BAD;		if (stram_swap_info->lowest_bit == i)			stram_swap_info->lowest_bit++;		if (stram_swap_info->highest_bit == i)			stram_swap_info->highest_bit--;		--nr_swap_pages;		swap_device_unlock(stram_swap_info);		swap_list_unlock();	}	return 0;}/* * reserve a region in ST-RAM swap space for an allocation */static void *get_stram_region( unsigned long n_pages ){	unsigned short *map = stram_swap_info->swap_map;	unsigned long max = stram_swap_info->max;	unsigned long start, total_free, region_free;	int err;	void *ret = NULL;		DPRINTK( "get_stram_region(n_pages=%lu)\n", n_pages );	down(&stram_swap_sem);	/* disallow writing to the swap device now */	stram_swap_info->flags = SWP_USED;	/* find a region of n_pages pages in the swap space including as much free	 * pages as possible (and excluding any already-reserved pages). */	if (!(start = find_free_region( n_pages, &total_free, &region_free )))		goto end;	DPRINTK( "get_stram_region: region starts at %lu, has %lu free pages\n",			 start, region_free );	err = unswap_by_read(map, max, start, n_pages);	if (err)		goto end;	ret = SWAP_ADDR(start);  end:	/* allow using swap device again */	stram_swap_info->flags = SWP_WRITEOK;	up(&stram_swap_sem);	DPRINTK( "get_stram_region: returning %p\n", ret );	return( ret );

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -