加入调度队列的情况考虑的比较少,我们只需要判断当前的最高优先级和加入任务优先级之间的关系即可。如果新加入的任务优先级高,那么优先级发生了改变;反之什么也不需要做。反之删除任务则比较复杂一些,我们需要判断移除的任务是不是最高优先级,不是还好处理,如果清除出去的任务正好是最高优先级,我们就需要从bitmap中寻找下一个最高优先级了,这个函数就是bit_search_first_one。函数第一个参数是bitmap数组,第二个参数是当前最高优先级,第三个参数是剩下的优先级总数,返回值为次优先级距离当前最高优先级的偏移值。
/*For 32 bit cpu*/ RAW_S32 bit_search_first_one(RAW_U32 *base, RAW_S32 offset, RAW_S32 width) { register RAW_U32 *cp, v; register RAW_S32 position; cp = base; cp += offset >> 5; if (offset & 31) { #if (CONFIG_RAW_LITTLE_ENDIAN > 0) v = *cp & ~(((RAW_U32)1 << (offset & 31)) - 1); #else v = *cp & (((RAW_U32)1 << (32 - (offset & 31))) - 1); #endif } else { v = *cp; } position = 0; while (position < width) { if (v) { /* includes 1 --> search bit of 1 */ if (!position) position -= (offset & 31); #if (CONFIG_RAW_LITTLE_ENDIAN > 0) if (!(v & 0xffff)) { v >>= 16; position += 16; } if (!(v & 0xff)) { v >>= 8; position += 8; } if (!(v & 0xf)) { v >>= 4; position += 4; } if (!(v & 0x3)) { v >>= 2; position += 2; } if (!(v & 0x1)) { ++position; } #else if (!(v & 0xffff0000)) { v <<= 16; position += 16; } if (!(v & 0xff000000)) { v <<= 8; position += 8; } if (!(v & 0xf0000000)) { v <<= 4; position += 4; } if (!(v & 0xc0000000)) { v <<= 2; position += 2; } if (!(v & 0x80000000)) { ++position; } #endif if (position < width) { return position; } else { return -1; } } else { /* all bits are 0 --> 1 Word skip */ if (position) { position += 32; } else { position = 32 - (offset & 31); } v = *++cp; } } return -1; } |
这个函数其实有两个,其中一个是32位cpu,另一个是为8位cpu准备的。当然,我们这里看到的是前一种情形,这里作者还考虑了大小端的情况,小端就是x86之类的cpu,大端就是powerpc之类的cpu,主要是指字节序不同而已。按照作者的说法,这是目前最快的查找方法,能比ucos查找表的方法快多少,我不太清楚,估计只能按照系统设备性能的平均值来估算了,别的还真不好说。要是本身用户侧的代码写的比较差,那么争取的这点调度性能其实意义也不大。
相关链接: