0
点赞
收藏
分享

微信扫一扫

随想录(无均衡负载的smp os设计)


    自己以前没有写过smp os,关于这方面的os也看得比较少。如果有,也是关于linux smp的部分,但是Linux上面会涉及到负载均衡,也很复杂,理解上面有一定的难度。然而是等到自己真正写的时候,发现困难也是可以克服的。抛却均衡负载不谈,自己写smp os也是可以做到的。下面就是我在实践中的一些做法。


(1) 每个任务一旦分配到具体cpu上之后,就不再迁移


// scheduler function

STATUS schedule() {

u8 cpuid;
Task* p_task;

cpuid = get_local_cpu();

if(is_in_irq()) {

return IN_IRQ;
}

if(is_sched_lock()) {

return OS_SCHED_LOCKED;
}

DISABLE_IE();

p_task = get_list_entry(g_ready[cpuid].next, Task, rdy);
sched_task[cpuid] = p_task;

if(current_task[cpuid] != p_task){

p_task-> state = RUNNING;
CONTEXT_SWITCH();
}

ENABLE_IE();

return SUCCESS;
}


(2)因为任务无法迁移,所以如果需要唤醒的时候只能是由核间中断来完成,下面的这个信号量可以说明问题,


// create sem

STATUS create_sem(Sem* p_sem, u32 count){

if(NULL == p_sem) {

return PARAM_ERROR;
}

p_sem-> blk_type = SEM_TYPE;

spin_lock_init(&p_sem-> lock);
list_init(&p_sem-> head);
p_sem-> count = count;

return SUCCESS;
}

// get sem

STATUS get_sem(Sem* p_sem, u8 wait){

u8 cpuid;

cpuid = get_local_cpu();

if(is_in_irq()) {

return IN_IRQ;
}

if(NULL == p_sem) {

return PARAM_ERROR;
}

if(SEM_TYPE != p_sem-> blk_type) {

return WRONG_BLOCK_TYPE;
}

DISABLE_IE();
spin_lock(&p_sem-> lock);

if(p_sem-> count) {

p_sem-> count --;

spin_unlock(&p_sem-> lock);
ENABLE_IE();

return SUCCESS;
}

if(is_sched_lock()) {

spin_unlock(&p_sem-> lock);
ENABLE_IE();

return OS_SCHED_LOCKED;
}

if(!wait) {

spin_unlock(&p_sem-> lock);
ENABLE_IE();

return NOT_WAIT;
}

remove_from_rdy_queue(current_task[cpuid]);
add_to_blk_queue(&p_sem-> head, current_task[cpuid]);

current_task[cpuid]-> state = BLOCKED;
current_task[cpuid]-> blk_data = p_sem;

spin_unlock(&p_sem-> lock);
ENABLE_IE();

schedule();

return SUCCESS;
}

// put sem

STATUS put_sem(Sem* p_sem) {

u8 cpuid;
Task* p_task;

if(NULL == p_sem) {

return PARAM_ERROR;
}

if(SEM_TYPE != p_sem-> blk_type){

return WRONG_BLOCK_TYPE;
}

DISABLE_IE();
spin_lock(&p_sem-> lock);

if(is_list_empty(&p_sem-> head)){

p_sem-> count ++;

spin_unlock(&p_sem-> lock);
ENABLE_IE();

return SUCCESS;
}

p_task = get_list_entry(p_sem->head.next, Task, blk);
remove_from_blk_queue(p_task);
list_init(&p_task-> blk);

cpuid = get_local_cpu();

if(cpuid != p_task-> cpuid) {

// send ipi to target cpu

send_ipi(WAKE_UP_TASK, p_task, p_task-> cpuid);

spin_unlock(&p_sem-> lock);
ENABLE_IE();

return SUCCESS;
}


add_to_rdy_queue(&g_ready[cpuid], p_task);
p_task-> state = READY;
p_task-> blk_data = NULL;

spin_unlock(&p_sem-> lock);
ENABLE_IE();

return SUCCESS;
}


(3)核间中断,重新将任务加入就绪队列


// send ipi

void send_ipi(u32 cmd, void* p_data, u8 cpuid) {

spin_lock(&g_ipi_lock[cpuid]);

g_ipi_cmd[cpuid] = cmd;
g_ipi_data[cpuid] = p_data;

ipi_trigger(cpuid);
}


// ipi isr func, for all cores

void ipi_isr_func() {

u8 cpuid;
u32 cmd;
void* p_data;
Task* p_task;

cpuid = get_local_cpu();

cmd = g_ipi_cmd[cpuid];
p_data = g_ipi_data[cpuid];

// ready to get other ipi cmd

spin_unlock(&g_ipi_lock[cpuid]);

DISABLE_IE();

p_task = (Task*) p_data;

if(BLOCKED == p_task-> state) {

add_to_rdy_queue(&g_ready[cpuid], p_task);
p_task-> blk_data = NULL;
p_task-> state = READY;
}

ENABLE_IE();
}


(4)目前大多数pc都是多核形式,用pc写smp os最好不过了,用vc调试起来也方便,


u8 get_local_cpu() {

s32 CPUInfo[4];
__cpuid(CPUInfo, 1);

if ((CPUInfo[3] & (1 << 9)) == 0)
return -1;

return (u8)(CPUInfo[1] >> 24);
}


    其实写代码不用怕,越是大胆写,才越能提高自己的能力,才会进步更大。



举报

相关推荐

0 条评论