?? sched.c
字號:
#include <sched.h>
#include <s3c2410.h>
#include <interrupt.h>
#include <init.h>
#include <mmu.h>
#include <string.h>
#include <serial.h>
struct task_struct task[TASK_NR];
struct task_struct* current = NULL;
extern void __switch_to(struct task_struct *pcur,struct task_struct *pnext);
/*****************************************************************************
* 初始化task數組
* 初始化任務0,即task[0]
*****************************************************************************/
void sched_init(void)
{
struct task_struct *p = &task[0];
int i,j;
DPRINTK(KERNEL_DEBUG,"\n\rkernel:sched_init,create task 0\n\r");
for(i = 0; i < TASK_NR; i++,p++){
p->pid = -1;
p->state = TASK_UNALLOCATE;
p->count = 0;
p->priority = 0;
for(j = 0; j < 1024; j++){
p->kernelstack[j] = 0;
}
}
p = &task[0];
p->pid = 0;
p->state = TASK_RUNNING;
p->count = 5;
p->priority = 5;
p->content[0] = (unsigned long)(&task[1]);
p->content[1] = 0x5f; /*cpsr*/
p->content[2] = 0x30100000-1024; /*usr/sys模式堆棧*/
p->content[3] = 0x13; /*svc模式*/
p->content[17]= 0; /*pc*/
current = &task[0];
}
/*****************************************************************************
* 切換到task數組中處于運行狀態的、count值最大的任務
* 如果所有任務的count值都為0,則重新計算count = count / 2 + priority
* 進程0不參與競爭
*****************************************************************************/
void schedule(void)
{
long max = -1;
long i = 0, next = 0;
struct task_struct * ptmp_tsk = NULL;
DPRINTK(KERNEL_DEBUG,"kernel:schedule\n\r");
while(1){
for(i = 1; i < TASK_NR; i++){
if((task[i].state == TASK_RUNNING)&&(max < (long)task[i].count)){
max = (long)task[i].count;
next = i;
}
}
/*如果所有任務都不處于就緒狀態,max = -1,next = 0,跳出循環執行任務0*/
/*如果max = 0,則進行下面的計算count值*/
/*如果max > 0,則跳出循環...*/
/*這種方法太妙了,摘自linux0.11*/
if(max)break;
for(i = 0; i < TASK_NR; i++){
if(task[i].state == TASK_RUNNING)
task[i].count = task[i].priority;
// task[i].count = (task[i].count >> 1) + task[i].priority;
}
}
if(current == &task[next])
return;
if(task[next].pid < 0)
return;
ptmp_tsk = current;
current = &task[next];
DPRINTK(KERNEL_DEBUG,"kernel:__switch_to\n\r");
__switch_to(ptmp_tsk,&task[next]);
DPRINTK(KERNEL_DEBUG,"kernel:return from __switch_to\n\r");
}
/*****************************************************************************
* 當前進程count減1
* 如果當前進程不處于可運行狀態,或count=0,調度進程
*****************************************************************************/
void do_timer(void)
{
int i = 0, b_wakeup = 0;
DPRINTK(KERNEL_DEBUG,"kernel:do_timer\n\r");
if(!current){
DPRINTK(KERNEL_DEBUG,"kernel:leaving do_timer,hasn't init task\n\r");
return;
}
for(i = 1; i < TASK_NR; i++){
if(task[i].state == TASK_SLEEPING){
if(!(--task[i].timer)){
task[i].state = TASK_RUNNING;
b_wakeup = 1;
}
}
}
if(current->count){
current->count--;
}
if((current->state != TASK_RUNNING)|| !current->count || b_wakeup){
schedule();
}
DPRINTK(KERNEL_DEBUG,"kernel:leaving do_timer\n\r");
}
/*******************************************************************************
* linux下,在控制臺下如此運行程序:file param0 param1 ...
* 其中的file param0 param1 ...作為參數傳遞給int main(int argc, char **argc)
* argc為參數個數,即file,param0,param1...的個數
* argv[0]為file字串的地址,argv[1]為param0字串的地址...
*
* OSCreateProcess中參數含義為:
* 1. nand_start_addr:本進程代碼存在nand flash中的位置,len:代碼大小,通過這兩個參數來
* 確定一個文件file
* 2. parameters為"param0 param1 param2 ...",各參數間以空格分開
* 請注意,進程main函數中的file參數就沒什么用處了,我隨便設為pid了
* 3. priority:進程優先級
*
* 本函數用于從nand flash中讀處代碼,設置其main函數執行前的環境:堆棧、參數,設置相應的任務數據結構
**********************************************************************************/
int OSCreateProcess(unsigned long nand_start_addr, unsigned long len, char *parameters, long priority)
{
unsigned long i = 1,pid,j,argc = 0;
unsigned long *p_VA;
char *pDes;
DPRINTK(KERNEL_DEBUG,"kernel:OSCreateProcess\n\r");
for(; i < TASK_NR; i++){
if(!(task[i].state == TASK_UNALLOCATE && VALIDE_TASK_INDEX(i)))
continue;
OS_ENTER_CRITICAL();
pid = i;
/*從NAND Flash中復制代碼到進程號i對應的物理地址*/
/*虛擬地址SDRAM_RAW_RW_VA_BASE + i*0x100000指向PID=i的進程的1M內存,并且此虛擬地址>32M,所以與PID無關*/
DPRINTK(KERNEL_DEBUG,"kernel:OSCreateProcess::nand_read_ll\n\r");
p_VA = (unsigned long *)(SDRAM_RAW_RW_VA_BASE + pid*0x100000);
//清0
for( j = 0; j < 0x100000/4; j++)
p_VA[j] = 0;
nand_read_ll((unsigned char*)p_VA, nand_start_addr,len);
/****************************************************************************************
* 設置用戶函數int main(int argc, char **argc)的參數
* 進程i的1M地址的最后1k空間用于存放參數(地址向上依次為):
* argc,argv[0],argv[1],...,argv[argc-1],NULL,"argv[0]對應的string","argv[1]對應的string",...
*****************************************************************************************/
DPRINTK(KERNEL_DEBUG,"kernel:OSCreateProcess::set the new process's parameters\n\r");
//放參數
p_VA = (unsigned long *)(SDRAM_RAW_RW_VA_BASE + pid*0x100000 + 0x100000 - 1024);
argc = 0;
j = 0;
/*計算paramters中參數個數*/
if(parameters){
while(parameters[j]){
while(parameters[j] == ' ')j++; //吃掉空格
if(!parameters[j])
break;
argc++;
while(parameters[j] && ( parameters[j] != ' '))j++; //吃掉非空格
if(!parameters[j])
break;
}
}
*p_VA++ = argc + 1; /*main函數中的argc*/
*p_VA++ = pid; /*argv[0]*/
pDes = (char *)(p_VA + argc + 1); /*pDes指向"...,argc[argc-1],NULL"后面,用來存放argv[...]對應的字符串*/
for(i = 0, j = 0; i < argc; i++){
*p_VA++ = (unsigned long)pDes -(SDRAM_RAW_RW_VA_BASE + pid*0x100000);
while(parameters[j] == ' ')j++; //吃掉空格
if(!parameters[j])
break;
while(parameters[j] && ( parameters[j] != ' ')){//復制參數
*pDes = parameters[j];
pDes++;
j++;
}
*pDes = '\0';
pDes = (char *)(((unsigned long)pDes + 4)&(~0x3)); //對齊
if(!parameters[j])
break;
}
/************************************************************************************
* 設置參數:
* 進程剛開始處于usr/sys模式
* 參考sched.S中保存進程上下文的順序為:
* sp_svc,cpsr,sp_usr/sys,0x13(表示svc),r0-r12,lr
**************************************************************************************/
DPRINTK(KERNEL_DEBUG,"kernel:OSCreateProcess::set the new process's content\n\r");
task[pid].pid = pid;
task[pid].state = TASK_RUNNING;
task[pid].count = 15;
task[pid].priority = priority;
task[pid].content[0] = (unsigned long)(&task[pid+1]);
task[pid].content[1] = 0x5f; /*cpsr*/
task[pid].content[2] = 0x100000-1024; /*usr/sys模式堆棧*/
task[pid].content[3] = 0x13; /*svc模式*/
task[pid].content[17]= 0; /*pc*/
OS_EXIT_CRITICAL();
return 1;
}
return 0;
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -