2011-8-1 21:13:48

本文介绍了Linux内核中的Per-CPU数据管理机制,包括如何为每个CPU分配和释放内存空间,以及如何使用掩码指定多个CPU进行操作。此外,还详细描述了阻塞队列的管理和操作,如设置阻塞状态、清除阻塞状态并唤醒等待进程等。
 

 

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);
}

阻塞结束

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值