ОС1/Модификације јун 2021 — разлика између измена

Извор: SI Wiki
Пређи на навигацију Пређи на претрагу
м (Ispravljen test primer)
 
(Нису приказане 4 међуизмене 3 корисника)
Ред 8: Ред 8:
** <syntaxhighlight lang="cpp" inline>void Barrier::close()</syntaxhighlight>: затвара баријеру;
** <syntaxhighlight lang="cpp" inline>void Barrier::close()</syntaxhighlight>: затвара баријеру;
** <syntaxhighlight lang="cpp" inline>void Barrier::open()</syntaxhighlight>: отвара баријеру и евентуално деблокира нит која је на баријери блокирана.
** <syntaxhighlight lang="cpp" inline>void Barrier::open()</syntaxhighlight>: отвара баријеру и евентуално деблокира нит која је на баријери блокирана.
* Написати јавни тест са две нити A и B. Нит A прави глобални семафор са вредношћу 0 и глобалну баријеру са вредношћу 1, а нит B упослено чека док се они не направе. Нит A треба циклично да позива <code>Barrier::open()</code>, <code>Barrier::pass()</code> и <code>Semaphore::signal()</code>, док нит B треба циклично да позива <code>Barrier::close()</code>, <code>Barrier::pass()</code> и <code>Semaphore::wait(0)</code> ''(редослед позива можда није тачан)''.
* Написати јавни тест са две нити A и B. Нит B прави глобални семафор са вредношћу 0 и глобалну баријеру са вредношћу 1, а нит A упослено чека док се они не направе. Нит A треба циклично да позива <code>Barrier::open()</code>, <code>Barrier::pass()</code> и <code>Semaphore::wait(0)</code>, док нит B треба циклично да позива <code>Barrier::pass()</code>, <code>Barrier::close()</code> и <code>Semaphore::signal()</code>.
<syntaxhighlight lang="cpp">
<syntaxhighlight lang="cpp">
class Barrier {
class Barrier {
Ред 21: Ред 21:
=== Решење ===
=== Решење ===
Оквирно решење може се наћи као решење поменутог колоквијума.
Оквирно решење може се наћи као решење поменутог колоквијума.
Тест описан текстом задатка.
<syntaxhighlight lang=cpp>
#include "thread.h"
#include "semaphor.h"
#include "barrier.h"
#include "intLock.h"
Semaphore *s = 0;
Barrier *b = 0;
Semaphore waiter(0);
class MyA : public Thread {
public:
MyA() : Thread() {}
~MyA() { waitToComplete(); }
protected:
void run() {
while (s == 0 || b == 0) {}
while (1) {
b->open();
intLock
cout << "A opened the barrier" << endl;
intUnlock
b->pass();
intLock
cout << "A passed the barrier" << endl;
intUnlock
s->wait(0);
}
}
};
class MyB : public Thread {
public:
MyB() : Thread() {}
~MyB() { waitToComplete(); }
protected:
void run() {
s = new Semaphore(0);
b = new Barrier(1);
while (1) {
b->pass();
intLock
cout << "B passed the barrier" << endl;
intUnlock
b->close();
intLock
cout << "B closed the barrier" << endl;
intUnlock
s->signal();
waiter.wait(30);
}
}
};
void tick() {}
int userMain(int argc, char *argv[]) {
MyA a;
MyB b;
a.start();
b.start();
a.waitToComplete();
b.waitToComplete();
}
</syntaxhighlight>


== 30 поена ==
== 30 поена ==
Ред 43: Ред 113:


=== Решење ===
=== Решење ===
* Решење за бирање детета јесте да се у <code>PCB</code> дода показивач на дете које је изабрано који се поставља на новонаправљено дете у <code>fork()</code>, проверава да ли је <code>nullptr</code> у тајмеру, ако није онда се нит која је следећа за извршавање поставља на то дете и показивач се враћа на <code>nullptr</code>.
* Решење за бирање детета јесте да се у <code>PCB</code> дода показивач на дете које је изабрано који се поставља на новонаправљено дете у <code>fork()</code>, проверава да ли је <code>nullptr</code> у тајмеру (у који се ушло позивом функције <code>dispatch()</code> унутар функције <code>fork()</code>), ако није онда се нит која је следећа за извршавање поставља на то дете и показивач се враћа на <code>nullptr</code>.
* Једно решење за форсирање нити које немају децу јесте да се, уколико се не дешава бирање детета, из <code>Scheduler</code> ваде нити док се не пронађе нит без деце (која се одмах постави као нит за извршавање) или док се не избаце све нити, ако су извађене нити са децом оне се убацују у другу листу и на крају се враћају назад у <code>Scheduler</code>. Уколико нит без деце није пронађена, између вађења и враћања нити проверава се да ли је извучена иједна нит без деце и вади се једна нит са децом уколико није.
* Једно решење за форсирање нити које немају децу јесте да се, уколико се не дешава бирање детета, из <code>Scheduler</code> ваде нити док се не пронађе нит без деце (која се одмах постави као нит за извршавање) или док се не избаце све нити, ако су извађене нити са децом оне се убацују у другу листу и на крају се враћају назад у <code>Scheduler</code>. Уколико нит без деце није пронађена, између вађења и враћања нити проверава се да ли је извучена иједна нит без деце и вади се једна нит са децом уколико није.


[[Категорија:Лабораторијске вежбе]]
[[Категорија:Лабораторијске вежбе]]
[[Категорија:ОС1]]
[[Категорија:ОС1]]

Тренутна верзија на датум 11. септембар 2021. у 22:37

Следеће модификације су се појавиле на одбрани пројекта у јунском року 2021.

20 поена

  • Следећа ставка иста је као 1. задатак са другог колоквијума у јунском року 2017. године: Школско језгро треба проширити концептом баријере ("ограда", "рампа", енгл. barrier) чији је интерфејс дат доле. Семантика овог концепта и операција над њим је следећа:
    • Баријера може бити у једном од два стања: отворена или затворена. Баријера се иницијализује задатим стањем (аргумент конструктора). Нит у чијем контексту се креира баријера (тј. извршава конструктор) је њен власник.
    • void Barrier::pass(): уколико позивајућа нит није власник ове баријере, ова операција нема ефекта - нит наставља своје извршавање; уколико је позивајућа нит власник баријере, а баријера затворена, нит се суспендује (блокира) све док се баријера не отвори; ако је баријера отворена, нит наставља извршавање без блокаде;
    • void Barrier::close(): затвара баријеру;
    • void Barrier::open(): отвара баријеру и евентуално деблокира нит која је на баријери блокирана.
  • Написати јавни тест са две нити A и B. Нит B прави глобални семафор са вредношћу 0 и глобалну баријеру са вредношћу 1, а нит A упослено чека док се они не направе. Нит A треба циклично да позива Barrier::open(), Barrier::pass() и Semaphore::wait(0), док нит B треба циклично да позива Barrier::pass(), Barrier::close() и Semaphore::signal().
class Barrier {
public:
    Barrier (int open=1);
    void open();
    void close();
    void pass();
};

Решење

Оквирно решење може се наћи као решење поменутог колоквијума. Тест описан текстом задатка.

#include "thread.h"
#include "semaphor.h"
#include "barrier.h"
#include "intLock.h"

Semaphore *s = 0;
Barrier *b = 0;
Semaphore waiter(0);

class MyA : public Thread {
public:
	MyA() : Thread() {}
	~MyA() { waitToComplete(); }
protected:
	void run() {
		while (s == 0 || b == 0) {}

		while (1) {
			b->open();
			intLock
			cout << "A opened the barrier" << endl;
			intUnlock
			b->pass();
			intLock
			cout << "A passed the barrier" << endl;
			intUnlock
			s->wait(0);
		}
	}
};


class MyB : public Thread {
public:
	MyB() : Thread() {}
	~MyB() { waitToComplete(); }
protected:
	void run() {
		s = new Semaphore(0);
		b = new Barrier(1);
		while (1) {

			b->pass();
			intLock
			cout << "B passed the barrier" << endl;
			intUnlock
			b->close();
			intLock
			cout << "B closed the barrier" << endl;
			intUnlock
			s->signal();
			waiter.wait(30);
		}
	}
};

void tick() {}

int userMain(int argc, char *argv[]) {
	MyA a;
	MyB b;
	a.start();
	b.start();
	a.waitToComplete();
	b.waitToComplete();
}

30 поена

  • Направити да се након позива fork() као следећа нит за извршавање изабере дете (пре изласка из fork() у родитељској нити). Такође, форсирати да се прво бирају нити без деце.
  • Написати тест пример који тестира задату функционалност. На пример, може да изгледа попут:
int result = Thread::fork();
if (result != -1) {
    if (result == 0) {
        intLock
        cout << "Child!" << endl;
        intUnlock
        Thread::exit();
    } else {
        intLock
        cout << "Parent!" << endl;
        intUnlock
        Thread::waitForForkChildren();
    }
}

Решење

  • Решење за бирање детета јесте да се у PCB дода показивач на дете које је изабрано који се поставља на новонаправљено дете у fork(), проверава да ли је nullptr у тајмеру (у који се ушло позивом функције dispatch() унутар функције fork()), ако није онда се нит која је следећа за извршавање поставља на то дете и показивач се враћа на nullptr.
  • Једно решење за форсирање нити које немају децу јесте да се, уколико се не дешава бирање детета, из Scheduler ваде нити док се не пронађе нит без деце (која се одмах постави као нит за извршавање) или док се не избаце све нити, ако су извађене нити са децом оне се убацују у другу листу и на крају се враћају назад у Scheduler. Уколико нит без деце није пронађена, између вађења и враћања нити проверава се да ли је извучена иједна нит без деце и вади се једна нит са децом уколико није.