线程同步代码,里面包含互斥信号量,这里将它注释了。
// 2.线程的同步与互斥 2015.12.11 #include <dos.h> #include <stdio.h> #include <math.h> #include <stdlib.h> int current; long timecount; #define NTCB 3 #define FINISHED 0 #define RUNNING 1 #define READY 2 #define BLOCKED 3 #define GET_INDOS 0x34 #define GET_CRIT_ERR 0x5d06 #define TIMEINT 0x08 #define TIMESLIP 20 //时间片改大 #define STACKLEN 1024 char far *indos_ptr=0; char far *crit_err_ptr=0; //记录型信号量 typedef struct { int value; // 信号量的值 struct TCB *wq; // 线程阻塞队列队首指针 }semaphore; struct TCB { unsigned char *stack; unsigned int ss; unsigned int sp; int state; char name[10]; int priority; // 增加优先级 semaphore sm; // 增加记录型信号量,用于同步 semaphore mutex; // 增加互斥信号量 struct TCB *next; // 指向下一个线程的指针 }tcb[NTCB]; semaphore mutex; semaphore bufferSem1, bufferSem2; void InitInDos(void); int DosBusy(void); void block(struct TCB **qp); void wakeup_first(struct TCB **qp); void p(semaphore *sem); void v(semaphore *sem); void p1(); void p2(); int Find(); void interrupt new_swtch(); void interrupt swtch(); void interrupt (*old_int8)(void); void interrupt new_int8(void); void interrupt test_int8(void); void over(); void InitTcb(); void show_tcb_state(); int all_finished(); void releaseTcb(); typedef void (far *funcptr)(void); int create(char *name, funcptr func, int stlen); void InitInDos(void) { union REGS regs; struct SREGS segregs; 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 block(struct TCB **qp) { struct TCB *tcbp; tcb[current].state = BLOCKED; if((*qp) == NULL) { (*qp) = &tcb[current]; } // 插入到队尾 else { tcbp = (*qp); while(tcbp->next != NULL) tcbp = tcbp->next; tcbp->next = &tcb[current]; } tcb[current].next = NULL; // 主动切换 swtch(); } // 从阻塞队列中唤醒第一个线程 void wakeup_first(struct TCB **qp) { struct TCB *tcbp; if((*qp) == NULL) return; tcbp = (*qp); (*qp) = (*qp)->next; tcbp->state = READY; tcbp->next = NULL; //swtch(); } // p 操作 void p(semaphore *sem) { struct TCB **qp; disable(); sem->value=sem->value-1; if(sem->value < 0) { qp = &(sem->wq); // 将线程插入到阻塞队列 block(qp); } enable(); } // v 操作 void v(semaphore *sem) { struct TCB **qp; disable(); qp = &(sem->wq); sem->value++; if(sem->value <= 0) { // 从阻塞队列中唤醒第一个线程 wakeup_first(qp); } swtch(); enable(); } // 生产者消费者问题 void p1() { long i, j, k; for(i=0; i<55; i++) { p(&bufferSem1); //p(&mutex); putchar('a'); //v(&mutex); v(&bufferSem2); for(j=0; j<1000; j++) for(k=0; k<20000; k++); } } void p2() { long i, j, k; for(i=0; i<50; i++) { p(&bufferSem2); //p(&mutex); putchar('b'); //v(&mutex); v(&bufferSem1); for(j=0; j<1000; j++) for(k=0;k<20000; k++); } } int Find() { int i,j; i=current; while(tcb[i=((i+1)%NTCB)].state!=READY||i==current); return i; } void interrupt swtch() // 其他原因CPU调度 { int id; id = Find(); if(id ==0) { if(tcb[1].state==FINISHED && tcb[2].state==FINISHED) id=0; else id=1; } disable(); // 保存现场 tcb[current].ss = _SS; tcb[current].sp = _SP; if(tcb[current].state == RUNNING) tcb[current].state = READY; // 切换堆栈 _SS = tcb[id].ss; _SP = tcb[id].sp; tcb[id].state = RUNNING; current = id; timecount = 0; enable(); } void interrupt new_int8(void) { int i; (*old_int8)(); timecount++; if(timecount!=TIMESLIP) return; else { if(DosBusy()) return; else { disable(); // asm CLI tcb[current].ss=_SS; tcb[current].sp=_SP; if(tcb[current].state==RUNNING) tcb[current].state=READY; i=Find(); if(i==current) return; _SS=tcb[i].ss; _SP=tcb[i].sp; tcb[i].state=RUNNING; timecount=0; current=i; enable(); // asm STI } } } void over() { if(tcb[current].state==RUNNING) { disable(); tcb[current].state=FINISHED; strcpy(tcb[current].name,NULL); free(tcb[current].stack); enable(); } swtch(); } void InitTcb() { unsigned int *tmp=0; //for thread 1 //================================================ tcb[1].state=READY; // strcpy(tcb[1].name, "p1"); tcb[1].stack=(unsigned char *)malloc(STACKLEN); memset(tcb[1].stack, 0xff, STACKLEN); tmp=(unsigned int *)(tcb[1].stack+STACKLEN-2); *tmp=FP_SEG(over); *(tmp-1)=FP_OFF(over); *(tmp-2)=0x200; *(tmp-3)=FP_SEG(p1); *(tmp-4)=FP_OFF(p1); *(tmp-9)=_ES; *(tmp-10)=_DS; tcb[1].ss=FP_SEG(tmp-13); tcb[1].sp=FP_OFF(tmp-13); tcb[1].priority=2; // 初始化优先级 tcb[1].sm.value = 0; // 初始化同步信号量 tcb[1].sm.wq = NULL; tcb[1].mutex.value = 1; // 初始化互斥信号量 tcb[1].mutex.wq = NULL; //for thread 2 //================================================ tcb[2].state=READY; // strcpy(tcb[2].name, "p2"); tcb[2].stack=(unsigned char *)malloc(STACKLEN); memset(tcb[2].stack, 0xff, STACKLEN); tmp=(unsigned int *)(tcb[2].stack+STACKLEN-2); *tmp=FP_SEG(over); *(tmp-1)=FP_OFF(over); *(tmp-2)=0x0200; *(tmp-3)=FP_SEG(p2); *(tmp-4)=FP_OFF(p2); *(tmp-9)=_ES; *(tmp-10)=_DS; tcb[2].ss=FP_SEG(tmp-13); tcb[2].sp=FP_OFF(tmp-13); tcb[2].priority=1; // 初始化优先级 tcb[2].sm.value = 0; // 初始化同步信号量 tcb[2].sm.wq = NULL; tcb[2].mutex.value = 1; // 初始化互斥信号量 tcb[2].mutex.wq = NULL; } void show_tcb_state() { int i; for(i=0; i<NTCB; i++) { switch(tcb[i].state) { case FINISHED: printf(" the thread %d is finished! ", i); break; case RUNNING: printf("the thread %d is running! ", i); break; case READY: printf("the thread %d is ready! ", i); break; case BLOCKED: printf("the thread %d is blocked! ", i); break; default: printf("unknown state of thread %! ", i); } } } int all_finished() { if(tcb[1].state!=FINISHED||tcb[2].state!=FINISHED) return -1; else return 0; } void releaseTcb() { int i=0; for(i=1; i<NTCB; i++) { if(tcb[i].stack) free(tcb[i].stack); } } void main() { timecount=0; mutex.value = 1; mutex.wq = NULL; bufferSem1.value = 1; bufferSem1.wq = NULL; bufferSem2.value = 0; bufferSem2.wq = NULL; InitInDos(); InitTcb(); old_int8=getvect(TIMEINT); strcpy(tcb[0].name, "main"); tcb[0].state=RUNNING; tcb[0].priority=3; current=0; show_tcb_state(); disable(); setvect(TIMEINT, new_int8); enable(); while(all_finished()) { // printf("system running! "); } tcb[0].name[0]='