+ -
当前位置:首页 → 问答吧 → struct zone结构中的等待队列问题求教。

struct zone结构中的等待队列问题求教。

时间:2010-04-26

来源:互联网

在struct zone有这样几个成员变量:
struct zone {
......//省略
* wait_table -- the array holding the hash table
* wait_table_hash_nr_entries -- the size of the hash table array
* wait_table_bits -- wait_table_size == (1 << wait_table_bits)
*
* The purpose of all these is to keep track of the people
* waiting for a page to become available and make them
* runnable again when possible. The trouble is that this
* consumes a lot of space, especially when so few things
* wait on pages at a given time. So instead of using
* per-page waitqueues, we use a waitqueue hash table.
*
* The bucket discipline is to sleep on the same queue when
* colliding and wake all in that wait queue when removing.
* When something wakes, it must check to be sure its page is
* truly available, a la thundering herd. The cost of a
* collision is great, but given the expected load of the
* table, they should be so rare as to be outweighed by the
* benefits from the saved space.
*
* __wait_on_page_locked() and unlock_page() in mm/filemap.c, are the
* primary users of these fields, and in mm/page_alloc.c
* free_area_init_core() performs the initialization of them.
*/
wait_queue_head_t * wait_table;
unsigned long wait_table_hash_nr_entries;
unsigned long wait_table_bits;
.......//省略
}


根据结构中的注释:
wait_table是一个数组,类型是wait_queue_head_t,该数组的成员格数是 wait_table_hash_nr_entries.
并且我在源码[2.6.24]mm/page_alloc.c中也找到对应的初始化代码:
......
zone->wait_table_hash_nr_entries =
wait_table_hash_nr_entries(zone_size_pages);
zone->wait_table_bits =
wait_table_bits(zone->wait_table_hash_nr_entries);
alloc_size = zone->wait_table_hash_nr_entries
* sizeof(wait_queue_head_t);

if (system_state == SYSTEM_BOOTING) {
zone->wait_table = (wait_queue_head_t *)
alloc_bootmem_node(pgdat, alloc_size);
......

而对成员wait_table_bits是啥东西就不明白了。上面的解释是wait_table_size == (1 << wait_table_bits),但是我觉得:zone->wait_table_hash_nr_entries*sizeof(wait_queue_head_t) 就可以得到表的大小了,何必要用wait_table_size?

作者: new_new_one   发布时间: 2010-04-26

(1)zone->wait_table_bits存放的内容,是从zone->wait_table_hash_nr_entries
推导得出的。
zone->wait_table_bits = (从低位算,第一个Bit为1的位)(zone->wait_table_hash_nr_entries);


(2)由zone->wait_table_bits,及虚拟内存地址,获得数组zone->wait_table某个子项。
例如,把虚拟内存地址,向右移动(32-zone->wait_table_bits)位后,获得某个其子项。

(3)zone->wait_table_bits记录的是位数,2的zone->wait_table_bits次方,有可能是
zone->wait_table_hash_nr_entries,获得一个Hash值的同时,保证不能越界访问
数组zone->wait_table

作者: linux_sir_huang   发布时间: 2010-04-29

多谢你的解析。

我有看了一遍相关代码。其中zone->wait_table_hash_nr_entries一定是2的n次幂。在函数
static inline unsigned long wait_table_hash_nr_entries(unsigned long pages)
{
unsigned long size = 1;

pages /= PAGES_PER_WAITQUEUE;

while (size < pages)
size <<= 1;

/*
* Once we have dozens or even hundreds of threads sleeping
* on IO we've got bigger problems than wait queue collision.
* Limit the size of the wait table to a reasonable size.
*/
size = min(size, 4096UL);

return max(size, 4UL);
}

所以最后得到的hash表的大小[也就是zone->wait_table数组的大小]一定是2的zone->wait_table_bits次幂。也就是说
1<<zone->wait_table_bits == zone->wait_table_hash_nr_entries

在计算hash函数hash_long中, 通过对某个32位地址 >> (32-zone->wait_table_bits)
求出的是该虚拟地址对应的hash表的索引值。 同时也保证了越界的问题。

真实太感谢了。好几个论坛都发帖了。都没人回,可焦急啊。

作者: new_new_one   发布时间: 2010-04-29

热门下载

更多