操作系统课程设计 线程的同步与互斥

线程同步代码,里面包含互斥信号量,这里将它注释了。

// 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(&regs, &regs, &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(&regs, &regs, &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("\nthe thread %d is finished!\n", i);
                break;
        case RUNNING:
                printf("the thread %d is running!\n", i);
                break;
        case READY:
                printf("the thread %d is ready!\n", i);
                break;
        case BLOCKED:
                printf("the thread %d is blocked!\n", i);
                break;
        default:
                printf("unknown state of thread %!\n", 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!\n");    
    }

    tcb[0].name[0]='\0';
    tcb[0].state=FINISHED;
    setvect(TIMEINT, old_int8);

    show_tcb_state();

    printf("Multi_task system terminated.\n");

    //system("pause");
}

 

你可能感兴趣的:(操作系统课程设计 线程的同步与互斥)