1. 程式人生 > >軟中斷排程器 c/c++實現(vs2008)

軟中斷排程器 c/c++實現(vs2008)

一、背景介紹
   嵌入式實時作業系統,如何實現實現無上下文及棧切換的高效業務處理,是一個難題。現
在我們一般採用一種稱為軟中斷的執行緒機制。軟中斷具有與中斷類似的特性,支援優先順序及優先順序搶佔,處理過程不能掛起。與硬中斷通過硬體啟用不同,軟中斷需
要通過主動呼叫軟中斷啟用函式進行啟用。
 
二、題目描述
  請模擬實現一個簡單軟中斷排程器。該軟中斷排程器支援32個優先順序(0~31,數值越小,優先順序越高)。並支援如下排程行為:
  1、在低優先順序軟中斷中啟用高優先順序軟中斷,高優先順序軟中斷將立即搶佔執行;
  2、在高優先順序軟中斷中啟用低優先順序軟中斷,需要在高優先順序軟中斷執行完成後才能得到排程;
  3、低優先順序軟中斷需要在所有直接或間接搶佔的所有高優先順序軟中斷執行完成後,再次恢復執行;
  4、同優先順序軟中斷按照先入先出順序進行排程;
  5、同一軟中斷可以連續多次啟用,並響應同樣多次。


三、實現介面
  1、軟中斷建立
   int SwiCreate(unsigned int swiId, unsigned int prio, void (* proc)(void));
    swiId為軟中斷ID,用於唯一標識一個軟中斷。測試用例保證取值範圍[0-99];
    prio為優先順序;
    proc為軟中斷處理函式;處理函式裡面可能會呼叫SwiActivate啟用其它軟中斷,測試用例保證不會出現函式內部死迴圈,或者環狀互相啟用而造成死迴圈;
    成功返回0, 其它情況返回-1(重複建立、優先順序無效、proc為空等)


  2、軟中斷啟用
    int SwiActivate(unsigned int swiId);
     swiId為待啟用軟中斷ID;
     成功返回0, 其它情況返回-1(未建立等)


  3、清空所有資訊
    void Clear(void);
代買實現如下:
#include <queue>
using namespace std;

typedef struct BreakNode
{
	unsigned int swiId;
	void (*proc)(void);
    int state; //指示狀態-sleep 1-running 2-activate
	unsigned int prio;
	BreakNode *next;

}BreakNodeList;
struct PrioNode
{
	BreakNodeList *head;
}PrioList[32];


queue<BreakNodeList *> NodeQue[32];

BreakNodeList *getNodeByID(unsigned int swiId)
{
		struct BreakNode *head=(struct BreakNode*)malloc(sizeof(struct BreakNode)) ;
		struct BreakNode *temp=head;
		for(int i=0;i<32;i++)
		{
			head=PrioList[i].head;
			while(head!=NULL)
			{
				if(head->swiId==swiId)
				{
					free(temp);
					return head;
				}
				head=head->next;
			}
		}
		free(temp);
		return NULL;
}

/*************************************************************************************************
函式說明:建立軟中斷
輸入引數:
      swiId:建立軟中斷ID;
	  prio: 建立軟中斷優先順序;
      proc: 建立軟中斷處理函式。
輸出引數:無
返回值 :成功返回,其它情況返回-1
**************************************************************************************************/

int SwiCreate(unsigned int swiId, unsigned int prio, void (* proc)(void))
{
	if(proc==NULL||prio>31)return -1;
	if(getNodeByID(swiId)!=NULL)return -1;
	BreakNodeList *head=PrioList[prio].head;
	struct BreakNode *node=(struct BreakNode*)malloc(sizeof(struct BreakNode)) ;
	node->next=NULL;
	node->swiId=swiId;
	node->proc=proc;
	node->state=0;
	node->prio=prio;

	if(head==NULL)
	{
		PrioList[prio].head=node;
	}
	else
	{
		while(head->next!=NULL)
		{
			head=head->next;
		}
		head->next=node;
	}
		
	return 0;
}

/*************************************************************************************************
函式說明:軟中斷啟用
輸入引數:swiId:待啟用軟中斷ID
輸出引數:無
返回值 :成功返回,其它情況返回-1
**************************************************************************************************/


BreakNodeList *getCurrentNode()
{
	struct BreakNode *head=(struct BreakNode*)malloc(sizeof(struct BreakNode)) ;
	struct BreakNode *temp=head;
	for(int i=0;i<32;i++)
		{
			head=PrioList[i].head;
			while(head!=NULL)
			{
				if(head->state==1)
				{
						free(temp);
					return head;
				}
				head=head->next;
			}
		}
		free(temp);
	return NULL;
}

int SwiActivate(unsigned int swiId)
{
	struct BreakNode *head=(struct BreakNode*)malloc(sizeof(struct BreakNode));
	head=getNodeByID(swiId);
	
	if(head==NULL) return -1;

	struct BreakNode *cur=(struct BreakNode*)malloc(sizeof(struct BreakNode));
	cur=getCurrentNode();
	
	if(cur==NULL)//沒有執行中斷
	{
		head->state=1;
		(*(head->proc))();
		head->state=0;
	}
	else if(cur->prio<head->prio)//當前優先順序高
	{
		head->state=2;
		NodeQue[head->prio].push(head);
		return 0;
	}
	else if(cur->prio>head->prio)//當前優先順序低
	{
		NodeQue[cur->prio].push(cur);
		head->state=1;//下一中斷執行
		(*(head->proc))();
		head->state=0;
	}
	else //優先順序一致
	{
		head->state=2;//下一中斷處於啟用狀態
		NodeQue[head->prio].push(head);
		return 0;
	}

	for(int i=0;i<32;i++)
	{
		while(NodeQue[i].size()>0)
		{
			BreakNodeList *head=NodeQue[i].front();
			NodeQue[i].pop();
			
			if (head->state==1)
			{
				return 0;
			}
			head->state=1;
			(*(head->proc))();
			head->state=0;
		}
	}

	return 0;
}



/*************************************************************************************************
函式說明:清空所有的資訊
輸入引數:無
輸出引數:無
返回值 :無
**************************************************************************************************/
void Clear(void)
{
	for(int i=0;i<32;i++)
	{
		if(PrioList[i].head!=NULL)
		{		
			BreakNodeList *p=PrioList[i].head;
			BreakNodeList *q=NULL;
			while(NULL!=p)
			{
				q=p;
				p=p->next;
				free(q);
			}
			PrioList[i].head=NULL;
		}
		
	}

}
總結:
寫得不太好,遞迴巢狀把我整暈了,除錯查錯廢了老大的勁,應該有更好、簡單的實現方法,水平有限,大家姑且做個參考吧