FreeBSD/sys/dev/drm2/ttm/ttm_page_alloc.c
/**
 * Free pages from pool.
 *
 * To prevent hogging the ttm_swap process we only free NUM_PAGES_TO_ALLOC
 * number of pages in one go.
 *
 * @pool: to free the pages from
 * @free_all: If set to true will free all pages in pool
 **/
Free pages from pool.
To prevent hogging the ttm_swap process we only free NUM_PAGES_TO_ALLOC
number of pages in one go.

@pool: to free the pages from
@free_all: If set to true will free all pages in pool
Free pages from pool . To prevent hogging the ttm_swap process we only free NUM_PAGES_TO_ALLOC number of pages in one go . @pool : to free the pages from @free_all : If set to true will free all pages in pool
static int ttm_page_pool_free(struct ttm_page_pool *pool, unsigned nr_free)
{
	vm_page_t p, p1;
	vm_page_t *pages_to_free;
	unsigned freed_pages = 0,
		 npages_to_free = nr_free;
	unsigned i;
	if (NUM_PAGES_TO_ALLOC < nr_free)
		npages_to_free = NUM_PAGES_TO_ALLOC;
	pages_to_free = malloc(npages_to_free * sizeof(vm_page_t),
	    M_TEMP, M_WAITOK | M_ZERO);
restart:
	mtx_lock(&pool->lock);
	TAILQ_FOREACH_REVERSE_SAFE(p, &pool->list, pglist, plinks.q, p1) {
		if (freed_pages >= npages_to_free)
			break;
		pages_to_free[freed_pages++] = p;
		if (freed_pages >= NUM_PAGES_TO_ALLOC) {
			for (i = 0; i < freed_pages; i++)
				TAILQ_REMOVE(&pool->list, pages_to_free[i], plinks.q);
			ttm_pool_update_free_locked(pool, freed_pages);
			mtx_unlock(&pool->lock);
			ttm_pages_put(pages_to_free, freed_pages);
			if (likely(nr_free != FREE_ALL_PAGES))
				nr_free -= freed_pages;
			if (NUM_PAGES_TO_ALLOC >= nr_free)
				npages_to_free = nr_free;
			else
				npages_to_free = NUM_PAGES_TO_ALLOC;
			freed_pages = 0;
			if (nr_free)
				goto restart;
			goto out;
		}
	}
	if (freed_pages) {
		for (i = 0; i < freed_pages; i++)
			TAILQ_REMOVE(&pool->list, pages_to_free[i], plinks.q);
		ttm_pool_update_free_locked(pool, freed_pages);
		nr_free -= freed_pages;
	}
	mtx_unlock(&pool->lock);
	if (freed_pages)
		ttm_pages_put(pages_to_free, freed_pages);
out:
	free(pages_to_free, M_TEMP);
	return nr_free;
}
static int ttm_page_pool_free ( struct ttm_page_pool * pool , unsigned nr_free ) { vm_page_t p , p1 ; vm_page_t * pages_to_free ; unsigned freed_pages = 0 , npages_to_free = nr_free ; unsigned i ; if ( NUM_PAGES_TO_ALLOC < nr_free ) npages_to_free = NUM_PAGES_TO_ALLOC ; pages_to_free = malloc ( npages_to_free * sizeof ( vm_page_t ) , M_TEMP , M_WAITOK | M_ZERO ) ; restart : mtx_lock ( & pool -> lock ) ; TAILQ_FOREACH_REVERSE_SAFE ( p , & pool -> list , pglist , plinks . q , p1 ) { if ( freed_pages >= npages_to_free ) break ; pages_to_free [ freed_pages ++ ] = p ; if ( freed_pages >= NUM_PAGES_TO_ALLOC ) { for ( i = 0 ; i < freed_pages ; i ++ ) TAILQ_REMOVE ( & pool -> list , pages_to_free [ i ] , plinks . q ) ; ttm_pool_update_free_locked ( pool , freed_pages ) ; mtx_unlock ( & pool -> lock ) ; ttm_pages_put ( pages_to_free , freed_pages ) ; if ( likely ( nr_free != FREE_ALL_PAGES ) ) nr_free -= freed_pages ; if ( NUM_PAGES_TO_ALLOC >= nr_free ) npages_to_free = nr_free ; else npages_to_free = NUM_PAGES_TO_ALLOC ; freed_pages = 0 ; if ( nr_free ) goto restart ; goto out ; } } if ( freed_pages ) { for ( i = 0 ; i < freed_pages ; i ++ ) TAILQ_REMOVE ( & pool -> list , pages_to_free [ i ] , plinks . q ) ; ttm_pool_update_free_locked ( pool , freed_pages ) ; nr_free -= freed_pages ; } mtx_unlock ( & pool -> lock ) ; if ( freed_pages ) ttm_pages_put ( pages_to_free , freed_pages ) ; out : free ( pages_to_free , M_TEMP ) ; return nr_free ; }
Free pages from pool.
Free pages from pool .
/* We can only remove NUM_PAGES_TO_ALLOC at a time. */ /* remove range of pages from the pool */ /**
			 * Because changing page caching is costly
			 * we unlock the pool to prevent stalling.
			 */ /* free all so restart the processing */ /* Not allowed to fall through or break because
			 * following context is inside spinlock while we are
			 * outside here.
			 */ /* remove range of pages from the pool */