2011-8-1 21:13:48
struct percpu_data {
void *ptrs[NR_CPUS];
};
#define __percpu_disguise(pdata) (struct percpu_data *)~(unsigned long)(pdata)
每cpu数据
void percpu_depopulate(void *__pdata, int cpu)
{
struct percpu_data *pdata = __percpu_disguise(__pdata);
kfree(pdata->ptrs[cpu]);
pdata->ptrs[cpu] = NULL;
}
释放指定CPU的perCpu数据
void __percpu_depopulate_mask(void *__pdata, cpumask_t *mask)
{
int cpu;
for_each_cpu_mask(cpu, *mask)
percpu_depopulate(__pdata, cpu);
}
用掩码的形式指定一些CPU来释放数据
void *percpu_populate(void *__pdata, size_t size, gfp_t gfp, int cpu)
{
struct percpu_data *pdata = __percpu_disguise(__pdata);
int node = cpu_to_node(cpu);
BUG_ON(pdata->ptrs[cpu]);
if (node_online(node)) {
/* FIXME: kzalloc_node(size, gfp, node) */
pdata->ptrs[cpu] = kmalloc_node(size, gfp, node);
if (pdata->ptrs[cpu])
memset(pdata->ptrs[cpu], 0, size);
} else
pdata->ptrs[cpu] = kzalloc(size, gfp);
return pdata->ptrs[cpu];
}
如果CPU有节点就在节点上分配
static wait_queue_head_t congestion_wqh[2] = {
__WAIT_QUEUE_HEAD_INITIALIZER(congestion_wqh[0]),
__WAIT_QUEUE_HEAD_INITIALIZER(congestion_wqh[1])
};
有2个阻塞队列
void clear_bdi_congested(struct backing_dev_info *bdi, int rw)
{
enum bdi_state bit;
wait_queue_head_t *wqh = &congestion_wqh[rw];
bit = (rw == WRITE) ? BDI_write_congested : BDI_read_congested;
clear_bit(bit, &bdi->state);
smp_mb__after_clear_bit();
if (waitqueue_active(wqh))
wake_up(wqh);
}
清除阻塞队列 唤醒阻塞进程
void set_bdi_congested(struct backing_dev_info *bdi, int rw)
{
enum bdi_state bit;
bit = (rw == WRITE) ? BDI_write_congested : BDI_read_congested;
set_bit(bit, &bdi->state);
}
设置阻塞
long congestion_wait(int rw, long timeout)
{
long ret;
DEFINE_WAIT(wait);
wait_queue_head_t *wqh = &congestion_wqh[rw];
prepare_to_wait(wqh, &wait, TASK_UNINTERRUPTIBLE);
ret = io_schedule_timeout(timeout);
finish_wait(wqh, &wait);
return ret;
}
把自己加入到等待队列中,并设置阻塞超时
long congestion_wait_interruptible(int rw, long timeout)
{
long ret;
DEFINE_WAIT(wait);
wait_queue_head_t *wqh = &congestion_wqh[rw];
prepare_to_wait(wqh, &wait, TASK_INTERRUPTIBLE);
if (signal_pending(current))
ret = -ERESTARTSYS;
else
ret = io_schedule_timeout(timeout);
finish_wait(wqh, &wait);
return ret;
}
可信号唤醒的阻塞等待
void congestion_end(int rw)
{
wait_queue_head_t *wqh = &congestion_wqh[rw];
if (waitqueue_active(wqh))
wake_up(wqh);
}
阻塞结束
本文介绍了Linux内核中的Per-CPU数据管理机制,包括如何为每个CPU分配和释放内存空间,以及如何使用掩码指定多个CPU进行操作。此外,还详细描述了阻塞队列的管理和操作,如设置阻塞状态、清除阻塞状态并唤醒等待进程等。

被折叠的 条评论
为什么被折叠?



