原算法中被选中任务每运行一个时间单位便将控制权交给主线程。再判断是否需要切换实时任务。实际上不需这样频繁的时钟中断。
故改进成。只在需要重新调度任务时才返回主控线程。且统计出线程切换次数(主线程切换不计)。
//编译
// pthread库不是Linux系统默认的库,所以在编译中需加-lpthread参数(posix线程库 )
gcc -lpthread -lm test.c -o test.out
#include "math.h"
#include "sched.h"
#include "pthread.h"
#include "stdlib.h"
#include "semaphore.h"
//@author vince
typedef struct{
char task_id;
int call_num; //times has been called
int ci; //processing time
int ti; //T
int ci_left;
int ti_left; //time left to next T
int flag; //isActive,0_no,2_yes
int arg; //argument
pthread_t th; //thread
}task;
void proc(int *args);
void idle();
int select_proc();
int task_num=0;
int idle_num=0;
int alg; //1 for EDF, 2 for RMS
int curr_proc=-1; //index
int demo_time=100; //time for show
task *tasks;
pthread_mutex_t proc_wait[100]; //the one be chosed is unlocked
pthread_mutex_t main_wait,idle_wait;
float sum=0;
pthread_t idle_proc;
int i;
int switchCount=0;
int main(int argc,char **argv)
{
pthread_mutex_init(&main_wait,NULL);
pthread_mutex_lock(&main_wait); //
pthread_mutex_init(&idle_wait,NULL);
pthread_mutex_lock(&idle_wait); //
printf("Please input number of real time tasks : \n");
scanf("%d",&task_num);
tasks=(task*)malloc(task_num*sizeof(task));
for(i=0;i
{
pthread_mutex_init(&proc_wait[i],NULL);
pthread_mutex_lock(&proc_wait[i]);
}
for(i=0;i
{
printf("Please input task id,followed by Ci and Ti: \n");
scanf("\n %c,%d,%d",&tasks[i].task_id,&tasks[i].ci,
&tasks[i].ti);
tasks[i].ci_left=tasks[i].ci;
tasks[i].ti_left=tasks[i].ti;
tasks[i].flag=2;
tasks[i].arg=i;
tasks[i].call_num=1;
sum=sum+(float)tasks[i].ci/(float)tasks[i].ti;
}
printf("Please input algorithm,1 for EDF,2 for RMS: ");
scanf("%d",&alg);
printf("Please input demo time: ");
scanf("%d",&demo_time);
double r=1; //EDF
if(alg==2)
{ //RMS
r=((double)task_num)*(exp(log(2)/(double)task_num)-1);
printf("r is %lf \n",r);
}
if(sum>r)
{ //unschedulable
printf("(sum=%lf > r=%lf),not schedulable!\n",sum,r);
exit(2);
}
pthread_create(&idle_proc,NULL,(void*)idle,NULL);
//create idle proc
for(i=0;i
pthread_create(&tasks[i].th,NULL,(void*)proc,&tasks[i].arg);
i=0;
while(i
//i will be count in proc() and idle()
//for(i=0;i
{
int j;
if((curr_proc=select_proc(alg))!=-1)
{// choose
pthread_mutex_unlock(&proc_wait[curr_proc]);
pthread_mutex_lock(&main_wait);
}
else{
//choose idle
pthread_mutex_unlock(&idle_wait);
pthread_mutex_lock(&main_wait);
}
}
printf("\n the switchCount is %d\n",switchCount);
sleep(5);
}
void proc(int *args)
{
pthread_mutex_lock(&proc_wait[*args]);
switchCount++;
//wait to be chosed when it was just created
while(tasks[*args].ci_left>0)
{
//pthread_mutex_lock(&proc_wait[*args]); //wait to be chosed
if(idle_num!=0)
{
printf("idle(%d)",idle_num);
idle_num=0;
}
printf("%c%d",tasks[*args].task_id,tasks[*args].call_num);
tasks[*args].ci_left--;
if(tasks[*args].ci_left==0)
{
printf("(%d)",tasks[*args].ci);
tasks[*args].flag=0;
tasks[*args].call_num++;
//pthread_mutex_unlock(&main_wait); //wake up main proc
//pthread_mutex_lock(&proc_wait[*args]);
}
int j;
//once it process,count rather than count in main(),coz it need to select in right here!
for(j=0;j
{ //Ti--,till 0 then begin next T
if(--tasks[j].ti_left==0)
{
tasks[j].ti_left=tasks[j].ti;
tasks[j].ci_left=tasks[j].ci;
pthread_create(&tasks[j].th,NULL,(void*)proc,
&tasks[j].arg);
tasks[j].flag=2;
}
}
i++;
if(*args!=select_proc(alg)||i==demo_time){
pthread_mutex_unlock(&main_wait); //wake up main proc
pthread_mutex_lock(&proc_wait[*args]);
switchCount++;
//turn to be other so wait here,next time continue from here too.
}
}
}
void idle()
{
pthread_mutex_lock(&idle_wait);
switchCount++;
while(1)
{
printf("->");
idle_num++;
int j;
//once it process,count rather than count in main(),coz it need to select in right here!
for(j=0;j
{ //Ti--,till 0 then begin next T
if(--tasks[j].ti_left==0)
{
tasks[j].ti_left=tasks[j].ti;
tasks[j].ci_left=tasks[j].ci;
pthread_create(&tasks[j].th,NULL,(void*)proc,
&tasks[j].arg);
tasks[j].flag=2;
}
}
i++;
if(select_proc(alg)!=-1||i==demo_time){
//need to return main when it was not selected,so 'else'
pthread_mutex_unlock(&main_wait);
pthread_mutex_lock(&idle_wait);
switchCount++;
}
}
}
int select_proc(int alg)
{
int j;
int temp1=10000,temp2=-1;
if((alg==2)&&(curr_proc!=-1)&&(tasks[curr_proc].flag!=0))
return curr_proc;
for(j=0;j
{
if(tasks[j].flag==2)
{
switch(alg)
{
case 1: //EDF
if(temp1>tasks[j].ti_left){
temp1=tasks[j].ti_left;
temp2=j;
break; }
case 2: //RMS
if(temp1>tasks[j].ti){
temp1=tasks[j].ti;
temp2=j; }
}
}
}
return temp2;
}
欢迎讨论。