приоритет читателя с использованием семафоров

Я упираюсь в стену с проектом, над которым работаю, и мне было интересно, может ли кто-нибудь оказать мне некоторую помощь. Я постараюсь упростить свой код, чтобы вы не смотрели на 100+ строк треп. Я почти уверен, что важен только первый блок кода, остальные - это мои системные вызовы в sys.c для справки.

Я должен создать программу, имитирующую реализацию синхронизации процессов с приоритетом читателя, используя мои собственные семафоры. Когда я запускаю его, я захожу в тупик всякий раз, когда читатель переходит к критическому разделу. Не знаю, что я сделал не так.

Пример вывода:

Writer 0 написал- 6

писатель 1 написал - 4

Писатель 2 написал - 2

Читатель 0 прочитал- 2

а потом зависает.

Насколько я могу судить, семафор критической секции никогда не будет выпущен.

Я считаю, что проблема связана с моей программой, а не с моим семафором и операциями ожидания и сигнала, но я включил их ниже для справки.

Заранее спасибо.

Моя попытка такова: я не учел свою инициализацию и отображение памяти, это базовая структура.

Примечания: RWwait и RWsignal - это методы-оболочки, которые успешно выполняют системные вызовы моих операций с семафором. csMutex предназначен для управления доступом к критическому разделу. nrMutex предназначен для управления очередью читателей в критическую секцию. Оба значения мьютекса изначально равны 1. * число - это указатель на число, к которому и читатели, и писатели имеют доступ.

int i;
//create writers
for(i=0; i < writers; i++){
    if (fork()==0){
        while(1){
            RWwait(csMutex);    //wait for the critical section and lock
            *number = rand() % 10;
            printf("Writer %d wrote- %d\n", i, *number);
            RWsignal(csMutex);//unlock critical section
        }
    }
}

int nr = 0;     //number of readers
//create readers
for(i=0; i < readers; i++){
    if (fork()==0){
            while(1){
            RWwait(nrMutex);
            nr++;

            if (nr == 1) 
                RWwait(csMutex);
            RWsignal(nrMutex);

            printf("Reader %d read- %d\n", i, *number);

            RWwait(nrMutex);
            nr--;
            if (nr == 0)
            RWsignal(csMutex);
                RWsignal(nrMutex);
        }
    }
}

ЭТО МОИ СИСТЕМНЫЕ ВЫЗОВЫ И СТРУКТУРЫ В sys.c ОПЯТЬ, ТОЛЬКО ДЛЯ СПРАВКИ

struct ProcQ {
    struct task_struct *ts;
    struct ProcQ *next;

};

и

struct RW_Sem {
    int value;
    char *type;
    //Front and back nodes for the queue
    struct ProcQ *front;
    struct ProcQ *back;
};

Подождите, операция:

asmlinkage long sys_RW_wait(struct RW_Sem *sem){
spin_lock(&sem_lock);   //locks the program
sem->value -= 1;    //decrement value

if (sem->value < 0){            //insert into queue
    struct ProcQ *node; //create a new node for the queue
    node = (struct ProcQ*)kmalloc(sizeof(struct ProcQ), GFP_KERNEL);
    node->ts = current; //assign this process to task_struct
    node->next = NULL;  //assign the next node to null

    if(sem->front == NULL){ //if the process queue is empty
        sem->front = node;
        sem->back = node;
    }

    else{   //if the queue is NOT empty
        sem->back->next = node;
        sem->back = node;       
    }
    set_current_state(TASK_INTERRUPTIBLE);  //sleep my child
    spin_unlock(&sem_lock);         //unlock
    schedule();
}

else{                   //queue bypass
    spin_unlock(&sem_lock);
}
return 0;
}

Сигнальная операция:

asmlinkage long sys_RW_signal(struct RW_Sem *sem){
spin_lock(&sem_lock);   //locks the program
sem->value += 1;        //increment value


if(sem->value <= 0){                     //wake up process, otherwise bypass
    struct ProcQ *dqProc;            //temporary node pointer for signaled process
    struct task_struct *wake;        //temp for task struct to wake
    dqProc = sem->front;

    if (dqProc != NULL) {          
        wake = dqProc->ts;
        if(sem->front==sem->back){      //if only item in queue
            sem->front = NULL;
            sem->back = NULL;   
        }

        else{
                sem->front = dqProc->next;
        }

        wake_up_process(wake);  //wake up!
        kfree(dqProc);                  //free that space
    }

}

spin_unlock(&sem_lock); //unlock
return 0;       //success!

}

person ReezaCoriza    schedule 24.11.2013    source источник


Ответы (1)


Я бы сказал вашему читателю:

        nr++;

        if (nr == 1) 
            RWwait(csMutex);

Состояние гонки.

Точно не стал бы поступать:

        if (nr == 0)
        RWsignal(csMutex);
person woolstar    schedule 24.11.2013
comment
Без первого, разве тогда читатель не смог бы получить доступ к критическому разделу, когда он уже был там? Идея заключалась в том, что если бы это был первый читатель nr == 1, он бы дождался завершения всех писателей. Тогда писатели не могли получить доступ к CS, пока все читатели не завершили nr == 0. - person ReezaCoriza; 25.11.2013
comment
Это состояние гонки, потому что теоретически два читателя могут каждый выполнить nr ++; перед выполнением строки if (nr == 0) - person woolstar; 25.11.2013
comment
аааааааааааааааааааааааааааа! Ты прав! Есть идеи, как я могу это обойти? Если я уберу эти строки, это избавит от состояния гонки, но даст читателям и писателям равный приоритет, не так ли? - person ReezaCoriza; 25.11.2013
comment
Приоритет - совсем другое дело. Если вы хотите, чтобы читатели разделяли блокировку, вам придется создать для этого дополнительный безопасный для процесса механизм. - person woolstar; 25.11.2013
comment
Это то, чего должен был достичь nrMutex. - person ReezaCoriza; 25.11.2013