КДП/К1 2022

Извор: SI Wiki
Пређи на навигацију Пређи на претрагу

1. задатак

Поставка

Написати и објасните[sic] Андерсенов алгоритам за критичну секцију (coarse grain). Реализовати (fine grain) верзију алгоритма уколико би на датом процесору умест FA постојала операција Compare-And-Swap која би недељиво обављала (CAS(a, b, c) : < if (a == c) { c = b; return true; } else { a = c; return false; } >).

Решење

Coarse-grain:

const int N = 100;
int slot = 0;
bool slots[N];

void worker(int id) {
    while (true) {
        < int myslot = slot; slot = slot % N + 1; >
        < await (slots[myslot]); >
        // Критична секција
        < slots[myslot] = false;
        slots[myslot % N + 1] = true; >
        // Некритична секција
    }
}

Fine-grain:

const int N = 100;
int slot = 0;
bool slots[N];

void worker(int id) {
    while (true) {
        int myslot = slot;
        while (!CAS(myslot, myslot % N + 1, slot)) skip();
        while (!slots[myslot]) skip();
        // Критична секција
        slots[myslot] = false;
        slots[myslot % N + 1] = true;
        // Некритична секција
    }
}

2. задатак

Поставка

Посматра се забавни парк са N аутића који могу да приме по једну особу (Bumper Cars Problem). M особа се шета по парку и може да одлучи да се провоза. Особа која жели да се вози стаје у ред и чека слободни ауто. Када се ослободи ауто и претходни возач напусти ауто прва особа из реда добија прилику да вози ауто и да се судара са другим аутима. Након неког времена особа завршава вожњу, враћа ауто на одговарајуће место, напушта ауто и одлази да се шета по парку. Особа може више пута да дође да се вози. Уколико постоји више аута, особа бира онај који је најдуже чекао на вожњу. Уколико тренутно нема особа које желе да се возе ауто стаје у ред и чека да дође особа. Користећи семафоре написати програм који решава овај проблем.

Решење

const int N = 100;
const int M = 100;

// Комуникација између аутомобила и особа
sem carSems[N];
sem peopleSems[M];
// Међусобно искључивање при приступу глобалном стању
sem mutex = 1;
// Подаци заштићени mutex-ом:
list<int> freeCars;
list<int> freePeople;
int mutexId;

void car(int carId) {
    int personId;
    while (true) {
        mutex.wait();
        if (freePeople.size() > 0) {
            personId = freePeople.front();
            freePeople.pop_front();
            mutexId = carId;
            peopleSems[personId].signal();
            // Нема ослобађања mutex, чекамо да особа прочита mutexId
            carSems[carId].wait();
        } else {
            freeCars.push_back(carId);
            mutex.signal();
            carSems[carId].wait();
            personId = mutexId;
            // Ослобађамо mutex који је особа закључала
            mutex.signal();
            // Обавештавамо особу да смо прочитали mutexId
            peopleSems[personId].signal();
        }
        // Особа контролише ауто, чекамо да нас особа обавести кад заврши
        carSems[carId].wait();
        // Враћени смо назад
    }
}

void person(int personId) {
    int carId;
    while (true) {
        // Шетамо
        mutex.wait();
        if (freeCars.size() > 0) {
            carId = freeCars.front();
            freeCars.pop_front();
            mutexId = personId;
            carSems[carId].signal();
            // Нема ослобађања mutex, чекамо да аутомобил прочита mutexId
            peopleSems[personId].wait();
        } else {
            freePeople.push_back(personId);
            mutex.signal();
            peopleSems[personId].wait();
            carId = mutexId;
            // Ослобађамо mutex који је аутомобил закључао
            mutex.signal();
            // Обавештавамо аутомобил да смо прочитали mutexId
            carSems[carId].signal();
        }
        // Возимо и на крају обавестимо аутомобил да смо завршили
        carSems[carId].signal();
        // Настављамо шетњу
    }
}