能力强的人善于解决问题,有智慧的人善于绕过问题。 区别很微妙,小心谨慎做后者。
全部博文(399)
分类:
2010-04-21 20:13:11
主要看了linux2.6.x内核进程调度那一块,和大家share一下。
每个cpu都有一个单独的runqueue,每个runqueue中有prio_array_t *active, *expired,他们是特定时间可以互换的两个指针。前者是有timeslice剩余的array,后者是耗尽timeslice的array。prio_array的结构定义如下:
struct prio_array
{
unsigned int nr_active;
unsigned long bitmap[BITMAP_SIZE];
struct list_head queue[MAX_PRIO];
};
static inline int sched_find_first_bit(const unsigned long *b)参数b就是我们传入的bitmap,b[i]可以指的第 i 个long型非负整数,在这里我们视其为32*i~32*(i+1)的位。b[i]若为0,则说明这32位中无1,我们直接可以跳到b[i+1],若b [i]不为0,则说明其中有置位。我们调用__ffs()来找到这一位的相对位置,再加上基地址就能得出第一个置位的位置所在。我们再来看一下__ffs ()函数,我们就可以知道为什么是O(1)了:
{
if (unlikely(b[0]))
return __ffs(b[0]);
if (unlikely(b[1]))
return __ffs(b[1]) + 32;
if (unlikely(b[2]))
return __ffs(b[2]) + 64;
if (b[3])
return __ffs(b[3]) + 96;
return __ffs(b[4]) + 128;
}
static inline unsigned long __ffs(unsigned long word)这是一段AT&T格式的嵌入式汇编代码,意思很简单,就是执行bsfl指令。
{
__asm__("bsfl %1,%0"
:"=r" (word)
:"rm" (word));
return word;
}
array = rq->active;
if (unlikely(!array->nr_active)) {
/*Switch the active and expired arrays.*/
schedstat_inc(rq, sched_switch);
rq->active = rq->expired;
rq->expired = array;
array = rq->active;
rq->expired_timestamp = 0;
rq->best_expired_prio = MAX_PRIO;
}
指针交换的代价是很小的:p
好了,先写到这里吧!