void kunmap_high(struct page *page)一般和kmap_high一起搭配使用,用于unmap highmem page into memory
其源码分析如下:
/**
* kunmap_high - unmap a highmem page into memory
* @page: &struct page to unmap
*
* If ARCH_NEEDS_KMAP_HIGH_GET is not defined then this may be called
* only from user context.
*/
void kunmap_high(struct page *page)
{
unsigned long vaddr;
unsigned long nr;
unsigned long flags;
int need_wakeup;
#根据page得到color,后面会跟你这个color得到一个等待队列
unsigned int color = get_pkmap_color(page);
wait_queue_head_t *pkmap_map_wait;
#一般和unlock_kmap_any 配合使用
lock_kmap_any(flags);
#得到这个page的虚拟地址
vaddr = (unsigned long)page_address(page);
BUG_ON(!vaddr);
#根据这个page的虚拟地址得到这个page在pkmap_count 中的index
nr = PKMAP_NR(vaddr);
/*
* A count must never go down to zero
* without a TLB flush!
*/
need_wakeup = 0;
#看这个page 对应的pkmap_count 是否为零,为零的话就是bug,从注释看对应的pkmap_count是在TLB flush中才会为零的
switch (--pkmap_count[nr]) {
case 0:
BUG();
case 1:
/*
* Avoid an unnecessary wake_up() function call.
* The common case is pkmap_count[] == 1, but
* no waiters.
* The tasks queued in the wait-queue are guarded
* by both the lock in the wait-queue-head and by
* the kmap_lock. As the kmap_lock is held here,
* no need for the wait-queue-head's lock. Simply
* test if the queue is empty.
*/
#正常情况下,根据color得到一个等待队列
pkmap_map_wait = get_pkmap_wait_queue_head(color);
#检查这个队列是否需要wakeup
need_wakeup = waitqueue_active(pkmap_map_wait);
}
unlock_kmap_any(flags);
/* do wake-up, if needed, race-free outside of the spin lock */
#如果需要wakeup的话,则通过wake_up 来唤醒这个等待队列
if (need_wakeup)
wake_up(pkmap_map_wait);
}
内存管理API之kunmap_high
最新推荐文章于 2024-03-18 17:55:36 发布