www.pudn.com > buffer_1.rar > buffer_1.C


#define GET_INDOS 0x34 
#define GET_CRIT_ERR 0x5d06 
#define FINISHED 0 
#define RUNNING 1 
#define READY 2 
#define BLOCKED 3 
#define NTCB 10 
#define TL 1 
#define NTEXT 10 
#define MSG_NUM 5 
#define SFB_NUM 3 
 
#include  
#include  
#include  
#include  
 
typedef struct{ 
        int value; 
	  struct TCB * wq; 
	  }semaphore; 
 
struct buffer{ 
        int sender; 
        int size; 
        char text[NTEXT]; 
        struct buffer *next; 
        }; 
 
struct TCB{ 
	   unsigned int *stack; 
	   unsigned ss; 
	   unsigned sp; 
	   char state; 
	   char name[10]; 
	   struct TCB * next ; 
	   semaphore mutex;          
	   semaphore sm;              
	   struct buffer *mq;        
	   }tcb[NTCB]; 
 
char far *indos_ptr = 0; 
char far *crit_err_ptr = 0; 
int sfbnumber = SFB_NUM,current,timecount; 
typedef int(far *codeptr)(void); 
 
semaphore mutexfb = {1,NULL};       
semaphore sfb = {SFB_NUM,NULL};    
/*semaphore mutex = {1,NULL};*/        
struct buffer *freebuf;            
 
int DosBusy(void); 
void InitInDos(void); 
void create(char *name,codeptr code,int stacklen); 
void interrupt swtch(void); 
void interrupt (*old_int8)(void); 
void interrupt new_int8(void); 
void over(void); 
void tcb_state(void); 
int all_finished(); 
void receive(int n); 
void send(char *receiver,char *a,int size); 
void block(struct TCB **t); 
void wakeup_first(struct TCB **t); 
 
/*解决DOS的不可重入性*/ 
void InitInDos(void) 
{ 
	union REGS regs; 
	struct SREGS segregs; 
 
      /*调用DOS的34H号系统功能,得到INDOS标志的地址*/ 
	regs.h.ah = GET_INDOS; 
	intdosx(®s,®s,&segregs); 
	indos_ptr = MK_FP(segregs.es,regs.x.bx); 
 
	if(_osmajor < 3) 
		crit_err_ptr = indos_ptr + 1; 
	else if(_osmajor == 3 && _osminor == 0) 
		crit_err_ptr = indos_ptr - 1 ; 
	else{ 
		regs.x.ax = GET_CRIT_ERR; 
		intdosx(®s,®s,&segregs); 
		crit_err_ptr = MK_FP(segregs.ds,regs.x.si); 
	} 
} 
 
/*若系统忙,则返回非零值*/ 
int DosBusy(void) 
{ 
	if(indos_ptr && crit_err_ptr) 
		return(*indos_ptr || *crit_err_ptr); 
	else 
		return(-1); 
} 
 
void create(char *name,codeptr code,int stacklen) 
{ 
	int i; 
 
	for(i = 0;i < NTCB;++ i) 
	{ 
	  if(tcb[i].state == FINISHED) 
	     { 
		tcb[i].stack = (unsigned int*)malloc(stacklen*sizeof(unsigned int)); 
		tcb[i].ss = FP_SEG(tcb[i].stack); 
		tcb[i].sp = FP_OFF(tcb[i].stack+1024-14);     
  
		strcpy(tcb[i].name,name); 
		tcb[i].state = READY; 
		tcb[i].mutex.value = 1; 
		tcb[i].sm.value = 0; 
		tcb[i].mutex.wq = NULL; 
		tcb[i].sm.wq = NULL; 
		tcb[i].mq = NULL; 
 
            /*将over()的入口地址压入线程的堆栈中*/ 
		tcb[i].stack[stacklen-1] = FP_SEG(over); 
		tcb[i].stack[stacklen-2] = FP_OFF(over); 
 
		tcb[i].stack[stacklen-3] = 0x200; /*允许中断位标志(如允许时间中断)*/ 
 
		tcb[i].stack[stacklen-4] = FP_SEG(code); /*CS*/ 
		tcb[i].stack[stacklen-5] = FP_OFF(code); /*IP*/ 
 
		tcb[i].stack[stacklen-10] = tcb[i].ss; 
		tcb[i].stack[stacklen-11] = tcb[i].ss; 
		break; 
	     } 
	  } 
} 
 
/*current线程已经完成,并切换线程*/ 
void over(void) 
{ 
	tcb[current].state = FINISHED; 
	tcb[current].ss = _SS; 
	tcb[current].sp = _SP; 
	swtch(); 
} 
 
/*其他原因引起的CPU调度*/ 
void interrupt swtch(void) 
{ 
	int i; 
 
	disable(); 
 
	tcb[current].ss = _SS; 
	tcb[current].sp = _SP; 
 
      if(tcb[current].state == RUNNING) 
	    tcb[current].state = READY; 
 
	for(i = 1; i < NTCB;++ i) 
	    if(tcb[i].state == READY) 
	        goto EDD; 
 
	i = 0; 
 
EDD:	       
      _SS = tcb[i].ss; 
      _SP = tcb[i].sp; 
	tcb[i].state = RUNNING; 
 
	current = i; 
	timecount = 0; 
	enable(); 
      tcb_state(); 
} 
 
/*时间片到时引起的CPU调度*/ 
void interrupt new_int8() 
{ 
	int i,flag; 
 
	old_int8(); 
	timecount++; 
 
	if(timecount >= TL) 
	{ 
	    InitInDos(); 
	    flag = DosBusy(); 
 
	    if(!flag) 
	    { 
	        disable(); 
 
	        tcb[current].ss = _SS; 
		  tcb[current].sp = _SP; 
 
		  if(tcb[current].state == RUNNING) 
  		      tcb[current].state = READY; 
 
		  for(i = 1;i < NTCB;i++) 
		      if(tcb[i].state == READY) 
			    goto EDD; 
 
		i = 0; 
 
EDD: 
            _SS = tcb[i].ss; 
		_SP = tcb[i].sp; 
		tcb[i].state = RUNNING; 
		current = i; 
		timecount = 0; 
		enable(); 
		} 
	} 
} 
 
 
void tcb_state(void) 
{ 
	int i; 
	for(i = 0;i < 3;++ i) 
	{ 
	      if(tcb[i].state == RUNNING) 
		printf("\n Thread %s is running!",tcb[i].name); 
	      else if(tcb[i].state == READY) 
		printf("\n Thread %s is ready!",tcb[i].name); 
	      else if(tcb[i].state == FINISHED) 
		printf("\n Thread %s is finished!",tcb[i].name); 
	      else if(tcb[i].state == BLOCKED) 
		printf("\n Thread %s is blocked!",tcb[i].name); 
	} 
} 
 
int all_finished() 
{ 
	int i; 
	for(i = 1;i < NTCB;++ i) 
	{ 
		if(tcb[i].state != FINISHED) 
			return 0; 
	} 
	return 1; 
} 
 
void block(struct TCB **t) 
{ 
	struct TCB *temp; 
	temp = *t; 
 
      /*阻塞当前线程并将它放在唤醒阻塞队列的尾部*/ 
	tcb[current].state = BLOCKED; 
 
	if(temp == NULL)    
	      *t = &tcb[current]; 
	else 
	{ 
		while(temp) 
			temp = temp->next; 
		temp = &tcb[current]; 
	} 
	swtch(); 
} 
 
void wakeup_first(struct TCB **t) 
{ 
	int i; 
	struct TCB *temp; 
 
      /*从唤醒阻塞队列头上摘下一个线程并唤醒它*/ 
	temp = *t; 
	*t = (*t)->next;     
	for(i = 0;iname) == 0) 
		    break; 
	} 
	tcb[i].state = READY; 
} 
 
 
void p(semaphore * sem) 
{ 
	  struct TCB **qp; 
 
	  disable(); 
 
	  sem->value = sem->value -1; 
	  if(sem->value < 0) 
	  { 
		  qp = &(sem->wq); 
		  block(qp); 
              if(sfbnumber <= 4) 
                  if(current == 2) 
                  { 
                       sem->value = sem->value +1; 
                       receive(1); 
                  } 
  	  } 
 
        enable(); 
} 
 
void v(semaphore * sem) 
{ 
	struct TCB **qp; 
 
	disable(); 
 
	qp = &(sem->wq); 
	sem->value = sem->value + 1; 
	if(sem->value <= 0) 
      { 
		wakeup_first(qp); 
      } 
 
	enable(); 
} 
 
struct buffer *getbuf(void) 
{ 
	struct buffer *buff; 
	buff = freebuf; 
	freebuf = freebuf->next; 
	return(buff); 
} 
 
void insert(struct buffer **mq,struct buffer *buff) 
{ 
	struct buffer *temp; 
	if(buff == NULL) 
		return; 
	buff->next = NULL; 
	if(*mq == NULL) 
		*mq=buff; 
	else 
	{ 
		temp = *mq; 
		while(temp->next != NULL) 
			temp = temp->next; 
		temp->next = buff; 
	} 
} 
 
/*将地址a开始的size个字节发送给外部标识符为receiver的线程*/ 
void send(char *receiver,char *a,int size) 
{ 
	int i,id = -1; 
	struct buffer *buff; 
 
	disable(); 
 
      /*判断是否存在消费者线程*/ 
	for(i=0;i < NTCB;i++) 
	{ 
		if(strcmp(receiver,tcb[i].name) == 0) 
		{ 
			id = i; 
			break; 
		} 
	} 
	if(id == -1) 
	{ 
		printf("ERROR:Receiver not exist!\n"); 
		enable(); 
		return; 
	} 
 
	p(&sfb); 
 
      /*申请一个空闲的消息缓冲区*/ 
	p(&mutexfb); 
	buff = getbuf(); 
	v(&mutexfb); 
 
      /*用相应的信息装配上述缓冲区*/ 
	buff->sender = current; 
	buff->size = size; 
	buff->next = NULL; 
	for(i = 0;i < buff->size;++ i,++ a) 
		buff->text[i] = *a; 
 
	p(&tcb[id].mutex); 
	insert(&(tcb[id].mq),buff); 
	v(&tcb[id].mutex); 
 
	v(&tcb[id].sm); 
 
	enable(); 
} 
 
void receive(int n) 
{ 
	int i = 0; 
	struct buffer *temp; 
	temp = tcb[current].mq; 
 
	disable(); 
 
	if(tcb[current].sm.value == 0) 
		if(tcb[n].state == FINISHED) 
		{ 
			tcb[current].state = FINISHED; 
			printf("ERROR:Sender not exist!\n"); 
			swtch(); 
		} 
	p(&tcb[current].sm); 
 
	p(&tcb[current].mutex); 
	if(temp->sender == n) 
	{ 
		printf("\n Found sender "); 
		for(i = 0;i < temp->size;++ i) 
			printf("%c",temp->text[i]); 
		tcb[current].mq = temp->next; 
 
		p(&mutexfb); 
		insert(&freebuf,temp);     
		v(&mutexfb); 
 
		v(&sfb); 
	} 
	v(&tcb[current].mutex); 
 
	enable(); 
} 
 
void producer(void) 
{ 
    int i; 
    char a[NTCB] = "producer"; 
    for(i = 0;i < MSG_NUM;++ i) 
    { 
        send("consumer",a,10); 
        printf(" @"); 
    } 
} 
 
void consumer(void) 
{ 
    int i; 
    for(i = 0;i < MSG_NUM;++ i) 
    { 
        receive(1); 
        printf("#"); 
    } 
} 
 
main() 
{ 
	int i; 
	struct buffer* temp; 
 
	InitInDos(); 
	old_int8 = getvect(8); 
 
	for(i = 0;i < NTCB;++ i) 
		tcb[i].state = FINISHED; 
 
	strcpy(tcb[0].name,"main"); 
	tcb[0].state = RUNNING; 
	current = 0; 
 
	freebuf = (struct buffer*)malloc(sizeof(struct buffer)); 
      temp = freebuf->next; 
 
	for(i = 0;i < sfbnumber;++ i) 
	{ 
		temp = (struct buffer*) malloc(sizeof(struct buffer)); 
		temp->next = NULL; 
		temp = temp->next; 
	} 
 
	create("producer",(codeptr)producer,1024); 
	create("consumer",(codeptr)consumer,1024); 
 
	tcb_state(); 
 
      /*启动多个线程的并发执行*/ 
	setvect(8,new_int8); 
	swtch(); 
 
	while(!all_finished()); 
	tcb[0].state = FINISHED; 
 
	setvect(8,old_int8); 
	tcb_state(); 
	printf("\n Multi_task system has terminated.\n"); 
}