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;i name) == 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"); }