<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://so.v2.cs.unibo.it/wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=LiberaL</id>
	<title>Sistemi Operativi - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://so.v2.cs.unibo.it/wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=LiberaL"/>
	<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php/Special:Contributions/LiberaL"/>
	<updated>2026-04-30T11:45:14Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.35.5</generator>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=20220906c2&amp;diff=3037</id>
		<title>20220906c2</title>
		<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php?title=20220906c2&amp;diff=3037"/>
		<updated>2023-05-31T06:00:07Z</updated>

		<summary type="html">&lt;p&gt;LiberaL: /* Correzioni proposte */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;In questa pagina sono presenti alcune soluzioni (possibilmente con errore) per l'esercizio C2 dell'esame 2022/09/06.&lt;br /&gt;
Il lettore è invitato a immedesimare il professore al momento della correzione durante la lettura delle soluzioni.&lt;br /&gt;
&lt;br /&gt;
== Consegna ==&lt;br /&gt;
Usando i semafori implementare un servizio che preveda due funzioni:&lt;br /&gt;
   void sumstop(int v)&lt;br /&gt;
   int sumgo(void) &lt;br /&gt;
La funzione sumstop deve mettere il processo chiamante in attesa.&lt;br /&gt;
La funzione sumgo deve sbloccare tutti i processi messi in attesa con la sumstop e restituire la somma algebrica dei valori passati come parametro alla  sumstop dai processi che sono stati sbloccati (zero se la  sumgo viene richiamata quando non c'è nessun processo bloccato).&lt;br /&gt;
== 1 ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
semaphore sem(1);&lt;br /&gt;
int sum=0;&lt;br /&gt;
queue q;&lt;br /&gt;
&lt;br /&gt;
void sumstop(int v):&lt;br /&gt;
	if i &amp;lt; 0:&lt;br /&gt;
		q.enqueue(v)&lt;br /&gt;
		sem.P()&lt;br /&gt;
	else&lt;br /&gt;
		i--&lt;br /&gt;
&lt;br /&gt;
int sumgo(void):&lt;br /&gt;
	for each elem in q:&lt;br /&gt;
		int val=q.dequeue()&lt;br /&gt;
		sum=sum + val&lt;br /&gt;
	return sum&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
== 2 ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
queue values;&lt;br /&gt;
semaphore s(0);&lt;br /&gt;
int sum=0;&lt;br /&gt;
&lt;br /&gt;
void sumstop(int v):&lt;br /&gt;
	s.P()&lt;br /&gt;
	values.enqueue(v)&lt;br /&gt;
&lt;br /&gt;
int sumgo(void):&lt;br /&gt;
	while !value.isEmpty():&lt;br /&gt;
		s.V()&lt;br /&gt;
		mutex.P()&lt;br /&gt;
		sum=sum+values.dequeue()&lt;br /&gt;
		mutex.v()&lt;br /&gt;
	return sum&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
== 3 ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
shared int sum=0;&lt;br /&gt;
semaphore wait(0);&lt;br /&gt;
semaphore mutex(1);&lt;br /&gt;
&lt;br /&gt;
void sumstop(int v):&lt;br /&gt;
	mutex.P();&lt;br /&gt;
	sum = sum + v;&lt;br /&gt;
	mutex.V();&lt;br /&gt;
	wait.P();&lt;br /&gt;
&lt;br /&gt;
int sumgo(void):&lt;br /&gt;
	wait.V();&lt;br /&gt;
	somma = sum;&lt;br /&gt;
	mutex.P()&lt;br /&gt;
	sum = 0&lt;br /&gt;
	mutex.V()&lt;br /&gt;
	return somma;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
== 4 ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
queue&amp;lt;int&amp;gt; processlist;&lt;br /&gt;
semaphore mutex(1);&lt;br /&gt;
semaphore s(0);&lt;br /&gt;
&lt;br /&gt;
void sumstop(int v):&lt;br /&gt;
	mutex.P();&lt;br /&gt;
	processlist.enqueue(v);&lt;br /&gt;
	mutex.P(); // V non P&lt;br /&gt;
	S.P();&lt;br /&gt;
&lt;br /&gt;
int sumgo(void):&lt;br /&gt;
	int sum = 0;&lt;br /&gt;
	mutex.P();&lt;br /&gt;
	while processlist.top() != NULL:&lt;br /&gt;
		sum += processlist.dequeue();&lt;br /&gt;
		S.V();&lt;br /&gt;
	mutex.V()&lt;br /&gt;
	return sum;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 5 ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
int counter = 0;&lt;br /&gt;
int sum = 0;&lt;br /&gt;
semaphore mutex(1);&lt;br /&gt;
semaphore blocked(0);&lt;br /&gt;
&lt;br /&gt;
void sumstop(int v):&lt;br /&gt;
	mutex.P();&lt;br /&gt;
	sum+=v;&lt;br /&gt;
	counter++;&lt;br /&gt;
	mutex.V();&lt;br /&gt;
	blocked.P();&lt;br /&gt;
&lt;br /&gt;
int sumgo(void):&lt;br /&gt;
	mutex.P();&lt;br /&gt;
	intret = sum;&lt;br /&gt;
	sum = 0;&lt;br /&gt;
	for (int i=0; i&amp;lt;counter; i++)&lt;br /&gt;
		blocked.V()&lt;br /&gt;
	counter = 0;&lt;br /&gt;
	mutex.V()&lt;br /&gt;
	return intret&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 6 ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
int sum = 0;&lt;br /&gt;
mutex = new semaphore(1);&lt;br /&gt;
queue q;&lt;br /&gt;
&lt;br /&gt;
void sumstop(int v):&lt;br /&gt;
	mutex.P();&lt;br /&gt;
	sum += v;&lt;br /&gt;
	sintpid = getpid();&lt;br /&gt;
	suspend(pid);&lt;br /&gt;
	mutex.V();&lt;br /&gt;
&lt;br /&gt;
int sumgo(void):&lt;br /&gt;
	mutex.P();&lt;br /&gt;
	while !q.empty():&lt;br /&gt;
		resume(q.dequeue())&lt;br /&gt;
	int value = sum;&lt;br /&gt;
	sum = 0;&lt;br /&gt;
	return value;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
== 7 ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
int nP, nV = -1, 0;&lt;br /&gt;
int somma = 0&lt;br /&gt;
int val[]&lt;br /&gt;
semaphore mutex(1);&lt;br /&gt;
semaphore s(0);&lt;br /&gt;
&lt;br /&gt;
void sumstop(int v):&lt;br /&gt;
	mutex.P()&lt;br /&gt;
	val[nP++].add[v]&lt;br /&gt;
	s.P()&lt;br /&gt;
	np--&lt;br /&gt;
	v[0].delete&lt;br /&gt;
&lt;br /&gt;
int sumgo(void):&lt;br /&gt;
	mutex.P();&lt;br /&gt;
	nV++&lt;br /&gt;
	if nP &amp;gt; 0:&lt;br /&gt;
		s.V()&lt;br /&gt;
		for (int i=0; i&amp;lt;nV; i++)&lt;br /&gt;
			somma += val[i]&lt;br /&gt;
			nv--&lt;br /&gt;
	else&lt;br /&gt;
		mutex.V()&lt;br /&gt;
	return somma&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
== 8 ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
struct blocked {&lt;br /&gt;
	semaphore sem(0);&lt;br /&gt;
	int value = 0;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
semaphore mutex(1);&lt;br /&gt;
list&amp;lt;blocked&amp;gt; procs = new list&amp;lt;blocked&amp;gt;();&lt;br /&gt;
&lt;br /&gt;
void sumstop(int v):&lt;br /&gt;
	mutex.P()&lt;br /&gt;
	blocked bl = new blocked();&lt;br /&gt;
	bl.value = v&lt;br /&gt;
	procs.add(bl)&lt;br /&gt;
	bl.sem.P()&lt;br /&gt;
	mutex.V()&lt;br /&gt;
&lt;br /&gt;
int sumgo(void):&lt;br /&gt;
	mutex.P();&lt;br /&gt;
	int count = 0;&lt;br /&gt;
	foreach proc in procs:&lt;br /&gt;
		count += proc.value&lt;br /&gt;
		procs.remove(proc)&lt;br /&gt;
		proc.sem.V()&lt;br /&gt;
	mutex.V()&lt;br /&gt;
	return count;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
== 9 ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
semaphore s[] new sem(0)&lt;br /&gt;
semaphore s1 new sem(0)&lt;br /&gt;
int tot, waiting = 0;&lt;br /&gt;
&lt;br /&gt;
void sumstop(int v):&lt;br /&gt;
	waiting++&lt;br /&gt;
	s[waiting - 1].P()&lt;br /&gt;
	waiting--&lt;br /&gt;
	tot = tot + v&lt;br /&gt;
	if waiting == 0:&lt;br /&gt;
		s1.V()&lt;br /&gt;
&lt;br /&gt;
int sumgo(void):&lt;br /&gt;
	if waiting = 0:&lt;br /&gt;
		return 0&lt;br /&gt;
	for (i = waiting -1; i == 0; i--)&lt;br /&gt;
		s[i].V()&lt;br /&gt;
	s1.P() // per aspettare che tutti abbiano fatto la somma&lt;br /&gt;
	return tot&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 10 ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
int nw = 0&lt;br /&gt;
int currsum = 0&lt;br /&gt;
semaphore mutex(1)&lt;br /&gt;
semaphore wait2go(0)&lt;br /&gt;
&lt;br /&gt;
void sumstop(int v):&lt;br /&gt;
	mutex.P()&lt;br /&gt;
	currsum += v;&lt;br /&gt;
	nw++;&lt;br /&gt;
	mutex.V()&lt;br /&gt;
	wait2go.P()&lt;br /&gt;
	if --nw &amp;gt; 0:&lt;br /&gt;
		wait2go.V()&lt;br /&gt;
	else&lt;br /&gt;
		mutex.V()&lt;br /&gt;
&lt;br /&gt;
int sumgo(void):&lt;br /&gt;
	mutex.P();&lt;br /&gt;
	if nw == 0:&lt;br /&gt;
		mutex.V()&lt;br /&gt;
		return 0;&lt;br /&gt;
	int sum = cursum;&lt;br /&gt;
	cursum = 0;&lt;br /&gt;
	wait2go.V();&lt;br /&gt;
	return sum&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
== 11==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
semaphore mutex(1);&lt;br /&gt;
semaphore semwait(0);&lt;br /&gt;
int sum=0;&lt;br /&gt;
int wait=0;&lt;br /&gt;
&lt;br /&gt;
void sumstop(int v):&lt;br /&gt;
	mutex.P()&lt;br /&gt;
	wait++&lt;br /&gt;
	sum += v;&lt;br /&gt;
	mutex.V()&lt;br /&gt;
	semwait.P()&lt;br /&gt;
	mutex.P()&lt;br /&gt;
	wait--;&lt;br /&gt;
	mutex.V()&lt;br /&gt;
	if wait &amp;gt; 0:&lt;br /&gt;
		semwait.V()&lt;br /&gt;
&lt;br /&gt;
int sumgo(void):&lt;br /&gt;
	if wait == 0:&lt;br /&gt;
		return 0&lt;br /&gt;
	semwait.V();&lt;br /&gt;
	while (wait &amp;gt; 0) {}&lt;br /&gt;
	int val = sum&lt;br /&gt;
	mutex.P()&lt;br /&gt;
	sum = 0;&lt;br /&gt;
	mutex.V()&lt;br /&gt;
	return val;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
== 12 ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
semaphore mutex(0)&lt;br /&gt;
volatile int counter = 0&lt;br /&gt;
&lt;br /&gt;
void sumstop(int v):&lt;br /&gt;
	counter = counter + v;&lt;br /&gt;
	mutex.P()&lt;br /&gt;
&lt;br /&gt;
int sumgo(void):&lt;br /&gt;
	int val = counter;&lt;br /&gt;
	while (mutex.value != 0)&lt;br /&gt;
		mutex.V()&lt;br /&gt;
	counter = 0;&lt;br /&gt;
	return counter&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
== 13 == &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
semaphore mutex(1)&lt;br /&gt;
int sum = 0;&lt;br /&gt;
queue of semaphore q;&lt;br /&gt;
&lt;br /&gt;
void sumstop(int v):&lt;br /&gt;
	mutex.P()&lt;br /&gt;
	sum += v;&lt;br /&gt;
	s = new semaphore(0);&lt;br /&gt;
	q.enqueue(s)&lt;br /&gt;
	mutex.V()&lt;br /&gt;
	s.P()&lt;br /&gt;
	free(s)&lt;br /&gt;
&lt;br /&gt;
int sumgo(void):&lt;br /&gt;
	mutex.P()&lt;br /&gt;
	int lsum = sum&lt;br /&gt;
	sum = 0&lt;br /&gt;
	while (!q.empty()):&lt;br /&gt;
		semaphore s = q.dequeue()&lt;br /&gt;
		s.V()&lt;br /&gt;
	mutex.V()&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
== 14 ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
semaphore mutex(1)&lt;br /&gt;
int sum = 0;&lt;br /&gt;
queue of semaphore q;&lt;br /&gt;
&lt;br /&gt;
void sumstop(int v):&lt;br /&gt;
	mutex.P()&lt;br /&gt;
	sum += v;&lt;br /&gt;
	s = new semaphore(0);&lt;br /&gt;
	q.enqueue(s)&lt;br /&gt;
	mutex.V()&lt;br /&gt;
	s.P()&lt;br /&gt;
	free(s)&lt;br /&gt;
	if(q.empty())&lt;br /&gt;
		mutex.V()&lt;br /&gt;
	else&lt;br /&gt;
		semaphore s = q.dequeue()&lt;br /&gt;
		s.V()&lt;br /&gt;
&lt;br /&gt;
int sumgo(void):&lt;br /&gt;
	mutex.P()&lt;br /&gt;
	int lsum = sum&lt;br /&gt;
	sum = 0&lt;br /&gt;
	if(q.empty())&lt;br /&gt;
		mutex.V()&lt;br /&gt;
	else&lt;br /&gt;
		semaphore s = q.dequeue()&lt;br /&gt;
		s.V()&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 15 (soluzione proposta su telegram) ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
#include &amp;lt;pthread.h&amp;gt;&lt;br /&gt;
#include &amp;quot;semaphore.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
semaphore s; // semaforo che blocca le somme&lt;br /&gt;
semaphore finished; // semaforo che indica che le somme sono state fatte&lt;br /&gt;
semaphore critical_section; // sarà utilizzata per decidere chi entra nella critical section&lt;br /&gt;
&lt;br /&gt;
volatile int sumstops = 0;&lt;br /&gt;
volatile int result;&lt;br /&gt;
&lt;br /&gt;
void *sumstop(int v) {&lt;br /&gt;
    semaphore_P(critical_section);&lt;br /&gt;
    sumstops++;&lt;br /&gt;
    semaphore_V(critical_section);&lt;br /&gt;
&lt;br /&gt;
    semaphore_P(s);&lt;br /&gt;
    printf(&amp;quot;summed %d\n&amp;quot;, v);&lt;br /&gt;
    result += v;&lt;br /&gt;
    semaphore_V(finished);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int sumgo(void) {&lt;br /&gt;
    semaphore_P(critical_section); // così sumstops è costante all'interno di questa section&lt;br /&gt;
    result = 0;&lt;br /&gt;
    for (int i = 0; i &amp;lt; sumstops; i++) {&lt;br /&gt;
        semaphore_V(s); // permetti alla somma di andare&lt;br /&gt;
        semaphore_P(finished); // aspetta che la somma sia finita prima di continuare&lt;br /&gt;
    }&lt;br /&gt;
    sumstops = 0; // reset number of blocked stops.&lt;br /&gt;
    semaphore_V(critical_section);&lt;br /&gt;
    return result;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void *run_sumgo(void) {&lt;br /&gt;
    int res = sumgo();&lt;br /&gt;
    printf(&amp;quot;the result found is %d\n&amp;quot;, res);&lt;br /&gt;
    printf(&amp;quot;the result found is %d\n&amp;quot;, result);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
    srand(time(NULL));&lt;br /&gt;
    s = semaphore_create(0);&lt;br /&gt;
    critical_section = semaphore_create(1);&lt;br /&gt;
    finished = semaphore_create(0);&lt;br /&gt;
&lt;br /&gt;
    int n = rand() % 50;&lt;br /&gt;
    pthread_t sumg, s[n];&lt;br /&gt;
&lt;br /&gt;
    for (int i = 0; i &amp;lt; n; i++) {&lt;br /&gt;
        pthread_create(&amp;amp;s[i], NULL, sumstop, i);&lt;br /&gt;
    }&lt;br /&gt;
    pthread_create(&amp;amp;sumg, NULL, run_sumgo, NULL);&lt;br /&gt;
&lt;br /&gt;
    for (int i = 0; i &amp;lt; 10; i++) {&lt;br /&gt;
        pthread_join(s[i], NULL);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    pthread_join(sumg, NULL);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== 16 - Soluzione di uno studente ==&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
//Variabili globali&lt;br /&gt;
Queue&amp;lt;Semaphore&amp;gt; processSemaphore = new Queue();&lt;br /&gt;
Semaphore mutex = new Semaphore(1);&lt;br /&gt;
Queue&amp;lt;int&amp;gt; integers = new Queue();&lt;br /&gt;
&lt;br /&gt;
int SumGo() {&lt;br /&gt;
    &lt;br /&gt;
    int sum = 0;&lt;br /&gt;
    mutex.P();&lt;br /&gt;
    while(processSemaphore.isQueueVoid() == false){&lt;br /&gt;
        Semaphore procSem = processSemaphore.dequeue();&lt;br /&gt;
        procSem.V();&lt;br /&gt;
    }&lt;br /&gt;
    while(integers.isQueueVoid() == false){&lt;br /&gt;
        sum = sum + integers.dequeue();&lt;br /&gt;
    }&lt;br /&gt;
    mutex.V();&lt;br /&gt;
    return sum;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void SumStop(int generatedValue){&lt;br /&gt;
    Semaphore sem = new Semaphore(0);&lt;br /&gt;
    mutex.P();&lt;br /&gt;
    integers.enqueue(generatedValue);&lt;br /&gt;
    processSemaphore.enqueue(sem);&lt;br /&gt;
    mutex.V();&lt;br /&gt;
    sem.P();&lt;br /&gt;
    free(sem);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Correzioni proposte ==&lt;br /&gt;
&lt;br /&gt;
Correzione proposta da [https://t.me/flecarts flecart]&lt;br /&gt;
(e poi modificata successivamente da altri studenti ... tra cui: [https://t.me/LLibera LLibera] )&lt;br /&gt;
&lt;br /&gt;
1. la variabile i non è inizializzata, sum e queue non sono protette in critical sections, inoltre la sem.V() non compare mai nel codice della sumgo.&lt;br /&gt;
&lt;br /&gt;
2. la coda value non è in una critical section, può creare errori nell'update di essa, solo sum viene considerata da proteggere, ma devono essere protette entrambe. La enqueue avrebbe senso farla solo prima di bloccarsi nel semaforo, se viene fatta dopo al momento della chiamata di sumgo non ci sono valori all'interno della coda!&lt;br /&gt;
&lt;br /&gt;
3. sumgo libera solamente un singolo sumstop, perché chiama wait.V() una singola volta anche se ci sono più thread in attesa&lt;br /&gt;
&lt;br /&gt;
4. mutex.P() è chiamata due volte in sumstop(), se il secondo fosse mutex.V() credo sia corretto.&lt;br /&gt;
//dopo il commento del prof: supponiamo che sia mutex.V() allora nella sumstop dopo S.P dovremmo ancora rilasciare la mutex...&lt;br /&gt;
ma rilasciando la mutex non riesco a finire di liberare gli altri processi quindi è meglio pensare meglio il while nella sumstop in modo da fare un passaggio del testimone che sblocchi tutti in cascata.&lt;br /&gt;
&lt;br /&gt;
5. mi sembra corretto (ma l'indentazione è poco sensata).&lt;br /&gt;
 &lt;br /&gt;
6. non si possono utilizzare suspend o resume (non si è fatto uso di semafori, e l'implementazione deve essere fatta all'esterno del kernel non all'interno). Oltre a questo pid non è inizializzata e sintpid non è utilizzata. Se anche la suspend fosse una sem.P() e la resume una sem.V() non dovremmo sospendere il processo all'interno della mutua esclusione.&lt;br /&gt;
 &lt;br /&gt;
7. nP e nV mi sembrano superflue, in questo caso sicuramente scorrette perché se chiamo m volte sumstop e una volta sumgo, nV è al massimo 1&lt;br /&gt;
quindi è impossibile che riesca a contare correttamente tutte le somme.&lt;br /&gt;
 &lt;br /&gt;
8. Deadlock perché bl.sem.P() è chiamato prima che ls Critical Section venga rilasciata e sumgo ha bisogno di entrare in una CS.&lt;br /&gt;
 &lt;br /&gt;
9. waiting è una variabile globale modificata senza cs, e tot non è inizializzato.&lt;br /&gt;
 &lt;br /&gt;
10. simile a 3. wait2go è chiamata una volta quindi può liberare solamente un singolo thread di sumstop.&lt;br /&gt;
&lt;br /&gt;
11. busy waiting in sumgo.&lt;br /&gt;
&lt;br /&gt;
12. counter non è protetto da Critical section &lt;br /&gt;
&lt;br /&gt;
13. se sumgo ritornasse il valore  lsum sarebbe tutto apposto.&lt;br /&gt;
&lt;br /&gt;
14. mi sembra corretto, manca solo la return in sumgo&lt;br /&gt;
&lt;br /&gt;
15. mi sembra corretto&lt;/div&gt;</summary>
		<author><name>LiberaL</name></author>
	</entry>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=Prove_scritte_2017&amp;diff=3036</id>
		<title>Prove scritte 2017</title>
		<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php?title=Prove_scritte_2017&amp;diff=3036"/>
		<updated>2023-05-29T04:05:20Z</updated>

		<summary type="html">&lt;p&gt;LiberaL: /* Esercizio c.2 (da controllare) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Esame 11/09/2017 ==&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2017.09.11.tot.pdf 2017.09.11.tot.pdf]&lt;br /&gt;
=== Esercizio c.1 ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
monitor crossing&lt;br /&gt;
&lt;br /&gt;
ok2dir[4];     //NESW&lt;br /&gt;
bool busy = false;&lt;br /&gt;
&lt;br /&gt;
pe entra(int dir)&lt;br /&gt;
   if (busy)&lt;br /&gt;
      ok2dir[dir].wait();&lt;br /&gt;
   busy = true;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
pe esci(int dir)&lt;br /&gt;
   busy = false;&lt;br /&gt;
   ok2dir[(dir + 1) % 4].signal();&lt;br /&gt;
   if (!busy)&lt;br /&gt;
      ok2dir[(dir + 2) % 4].signal();&lt;br /&gt;
   if (!busy)&lt;br /&gt;
      ok2dir[(dir + 3) % 4].signal();&lt;br /&gt;
   if (!busy)&lt;br /&gt;
      ok2dir[(dir + 4) % 4].signal();  //dir&lt;br /&gt;
&lt;br /&gt;
//alternativa più compatta&lt;br /&gt;
pe esci(int dir)&lt;br /&gt;
   busy = false;&lt;br /&gt;
   for (i = 0; i &amp;lt; 4; i++)&lt;br /&gt;
   if (!busy)&lt;br /&gt;
      ok2dir[(dir + i + 1) % 4].signal();&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Soluzione proposta 2 ==== &lt;br /&gt;
Soluzione proposta da [https://t.me/LLibera LLibera] e corretta da  [https://so.v2.cs.unibo.it/wiki/index.php/User:Flecart Flecart]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
const int N_DIRECTION = 4;&lt;br /&gt;
&lt;br /&gt;
// assumo N = 0, E = 1, S = 2, W = 3, oppure shiftati ciclicamente, è equivalente&lt;br /&gt;
&lt;br /&gt;
monitor crossing {&lt;br /&gt;
	bool free;										//l'incrocio è libero?&lt;br /&gt;
	int num_waiting[N_DIRECTION];&lt;br /&gt;
	condition okToCross[N_DIRECTION];				//free == True&lt;br /&gt;
	&lt;br /&gt;
	crossing() {&lt;br /&gt;
		free = True;								//parto con l'incrocio libero&lt;br /&gt;
		for (int i = 0; i &amp;lt; N_DIRECTION; i++) {&lt;br /&gt;
			num_waiting[i] = 0;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	procedure entry enter(int direction) {&lt;br /&gt;
		if(!free) {									//se l'incrocio non è libero&lt;br /&gt;
			num_waiting[direction]++;&lt;br /&gt;
			okToCross[direction].wait();			//aspetto nella mia direzione&lt;br /&gt;
			num_waiting[direction]--;&lt;br /&gt;
		}&lt;br /&gt;
													//ora sono sicurə che sia libero&lt;br /&gt;
		free = False;								//quindi lo dichiaro occupato&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	procedure entry exit(int direction) {&lt;br /&gt;
													//non devo aspettare niente per liberare l'incrocio&lt;br /&gt;
		free = True;								//lo dichiaro libero&lt;br /&gt;
		&lt;br /&gt;
		for (int i = 0; i &amp;lt; N_DIRECTION; i++) {&lt;br /&gt;
			int curr_dir = (direction + i + 1) % N_DIRECTION;&lt;br /&gt;
			if (num_waiting[curr_dir] &amp;gt; 0) {&lt;br /&gt;
				okToCross[curr_dir].signal();&lt;br /&gt;
				break;	// l'onere di risvegliare gli altri è stato passato al nuovo processo risvegliato, quindi esco.&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.2 (da controllare) ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// server[] = array contenente il PID di tutti i server&lt;br /&gt;
&lt;br /&gt;
#define BROADCAST server[0]&lt;br /&gt;
&lt;br /&gt;
server[0]&lt;br /&gt;
{&lt;br /&gt;
    while(true)&lt;br /&gt;
    {&lt;br /&gt;
        &amp;lt;msg, sender&amp;gt; = arecv(*); // ricevo il messaggio&lt;br /&gt;
        if (sender == BROADCAST)&lt;br /&gt;
            print(msg); // se il messaggio l'ho ricevuto da me stesso allora lo stampo&lt;br /&gt;
        else&lt;br /&gt;
            asend(*, &amp;lt;msg, getpid()&amp;gt;); // se il messaggio l'ho ricevuto da un client o da un altro server lo inoltro a tutti i server (compreso me stesso)&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
server[x] // x = 1...N-1&lt;br /&gt;
{&lt;br /&gt;
    while(true)&lt;br /&gt;
    {&lt;br /&gt;
        &amp;lt;msg, sender&amp;gt; = arecv(*); // ricevo il messaggio&lt;br /&gt;
        if (sender == BROADCAST)&lt;br /&gt;
            print(msg); // se il messaggio l'ho ricevuto dal server[0] allora lo stampo&lt;br /&gt;
        else&lt;br /&gt;
            asend(BROADCAST, &amp;lt;msg, getpid()&amp;gt;) // se il messaggio l'ho ricevuto da un client lo inoltro al server[0]&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Soluzione proposta 2 ====&lt;br /&gt;
&lt;br /&gt;
Soluzione proposta da [https://so.v2.cs.unibo.it/wiki/index.php/User:Flecart Flecart]&lt;br /&gt;
Soluzione corretta da [https://so.v2.cs.unibo.it/wiki/index.php/User:Gio Flecart friend]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
process server_0 {&lt;br /&gt;
&lt;br /&gt;
        while (true) {&lt;br /&gt;
                &amp;lt;msg, sender&amp;gt; = arecv(ANY);&lt;br /&gt;
                for (int i = 1 ; i &amp;lt; N; i++) {&lt;br /&gt;
                        asend(&amp;lt;msg, 0&amp;gt;, server[i]);&lt;br /&gt;
                        while(true){&lt;br /&gt;
                          msg = arecv(server[i]); // così so che tutti abbiano stampato.&lt;br /&gt;
                          if(msg==ACK)&lt;br /&gt;
                            break&lt;br /&gt;
                          asend(msg,server[0]);&lt;br /&gt;
                        }&lt;br /&gt;
                }&lt;br /&gt;
                print(msg);&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
process server_[i=1 to N - 1] {&lt;br /&gt;
        while (true) {&lt;br /&gt;
                &amp;lt;msg, sender&amp;gt; = arecv(ANY);&lt;br /&gt;
                if (sender == 0) {&lt;br /&gt;
                        print(msg);&lt;br /&gt;
                        asend(ACK, server[0]);&lt;br /&gt;
                } else {&lt;br /&gt;
                        asend(&amp;lt;msg, i&amp;gt;, server[0]);&lt;br /&gt;
                }&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Esame 17/07/2017 ==&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2017.07.17.tot.pdf 2017.07.17.tot.pdf]&lt;br /&gt;
=== Esercizio c.1 ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
monitor conf {&lt;br /&gt;
        condition finished;&lt;br /&gt;
        condition ready2present[max];&lt;br /&gt;
        bool arrived[max] = false;&lt;br /&gt;
        bool giachiamato[max] = false;&lt;br /&gt;
&lt;br /&gt;
        entry chiama(chiamato){&lt;br /&gt;
        if(arrived[chiamato] == true)&lt;br /&gt;
                ready2present[chiamato].signal;&lt;br /&gt;
                finished.wait;&lt;br /&gt;
                return true;&lt;br /&gt;
        else&lt;br /&gt;
                giachiamato[chiamato]= true&lt;br /&gt;
                return false;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        entry arrivato(nome){&lt;br /&gt;
                if(giachiamato[nome] == true)&lt;br /&gt;
                        return  false;&lt;br /&gt;
&lt;br /&gt;
                arrived[nome] = true;&lt;br /&gt;
                ok2present[nome].wait;&lt;br /&gt;
                return true;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        entry finepresentazione(nome){&lt;br /&gt;
                finished.signal;&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.2 (da controllare) ===&lt;br /&gt;
controllata da [[User:LiberaL|LiberaL]] 14:26, 26 May 2023 (CEST) l'implementazione fornita gestisce solo il caso di arecv(ANY) e non arecv(mittente)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
si, è possibile: &lt;br /&gt;
&lt;br /&gt;
Implementare asend e arecv date bsend e brecv&lt;br /&gt;
&lt;br /&gt;
asend(pid_t dst, msg_type msg){&lt;br /&gt;
    bsend (&amp;lt;dst, msg&amp;gt;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
arecv(*){&lt;br /&gt;
  do {&lt;br /&gt;
    &amp;lt;dst, msg&amp;gt; = brecv(*);&lt;br /&gt;
  } while (dst != getpid())&lt;br /&gt;
  return msg;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
propongo ([[User:LiberaL|LiberaL]] 06:04, 29 May 2023 (CEST)) quindi questa implementazione con gestione arecv da mittente specificato (sempre da controllare)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
//il messaggio mandato è la tripla &amp;lt;destinatario, mittente, messaggio&amp;gt;&lt;br /&gt;
&lt;br /&gt;
asend(pid_t dst, msg_type msg){&lt;br /&gt;
    bsend (&amp;lt;dst, getpid(), msg&amp;gt;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
myDictionaryQueue of &amp;lt;pid_t, msg_type&amp;gt; db; //nota: salvo qui solo se il messaggio è per me, quindi dest non mi serve&lt;br /&gt;
&lt;br /&gt;
arecv(pid_t sender) {&lt;br /&gt;
&lt;br /&gt;
  //devo controllare se nella coda ho già ricevuto il messaggio da quel mittente, ovvero mentre aspettavo un messaggio da qualcun'altro&lt;br /&gt;
  //db.get(sender) cerca una tripla il cui mittente è sender&lt;br /&gt;
  //se trova il messaggio lo rimuove anche dal db.&lt;br /&gt;
  //db.get(ANY) ritorna (ed elimina da db) il primo che trova (FIFO), e if(db.isEmpty()) return NULL;&lt;br /&gt;
  if( ( &amp;lt;mit, msg&amp;gt; = db.get(sender) ) != NULL ) //se lo trova&lt;br /&gt;
    return msg;&lt;br /&gt;
&lt;br /&gt;
  do {&lt;br /&gt;
    &amp;lt;dst, mit, msg&amp;gt; = brecv(*);                 //ricevo&lt;br /&gt;
    if( dst == getpid() ) {                     //il messaggio è per me?&lt;br /&gt;
      if ( mit == sender || sender == ANY )     //se devo ritornare il messaggio&lt;br /&gt;
       return msg;     //esci dal while&lt;br /&gt;
      //se devo salvarlo (sender specificato e messaggio per me)&lt;br /&gt;
      //metto in db i messaggi di altri mittenti, ricevuti quando ne aspettavo uno da un mittente specificato&lt;br /&gt;
      db.add(&amp;lt;mit, msg&amp;gt;);&lt;br /&gt;
    }&lt;br /&gt;
  } while ( true ) //devo uscire solo con il return&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Esame 19/06/2017 ==&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2017.06.19.tot.pdf 2017.06.19.tot.pdf]&lt;br /&gt;
=== Esercizio c.1 (da controllare)===&lt;br /&gt;
&lt;br /&gt;
* Mi sembra che ci sia un errore per il giodice, potrebbe succedere in un caso che il wait non si risvegli mai [[User:Flecart|Flecart]] ([[User talk:Flecart|talk]]) 15:38, 19 January 2023 (CET)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define NATLETI n&lt;br /&gt;
&lt;br /&gt;
condition ok2lancia[NATLETI];&lt;br /&gt;
condition ok2giudice;&lt;br /&gt;
&lt;br /&gt;
int counter[NATLETI];&lt;br /&gt;
int ultimo_tiro;&lt;br /&gt;
float registro[NATLETI][3];&lt;br /&gt;
&lt;br /&gt;
Procedure entry: boolean pronto(int i)&lt;br /&gt;
{&lt;br /&gt;
    if(!(i == 0 &amp;amp;&amp;amp; counter[i] == 0)) // se è il primo lancio non devo metterlo in wait&lt;br /&gt;
        ok2lancia[i].wait()&lt;br /&gt;
    if(counter[i] &amp;lt; 3)&lt;br /&gt;
        return true;&lt;br /&gt;
    else&lt;br /&gt;
        return false;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: void lanciato (int i)&lt;br /&gt;
{&lt;br /&gt;
    counter[i]++;&lt;br /&gt;
    ultimo_tiro = i;&lt;br /&gt;
    ok2giudice.signal();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: int lanciofatto()&lt;br /&gt;
{&lt;br /&gt;
    ok2giudice.wait()&lt;br /&gt;
    if(ultimo_tiro == NATLETI-1 &amp;amp;&amp;amp; counter[0] == 3)&lt;br /&gt;
        return -1;  // devo invalidare la condizione per uscire dal while, quindi se nessuno deve più lanciare ritorno -1&lt;br /&gt;
    else&lt;br /&gt;
        return ultimo_tiro;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: void registraechiama(int i, float m)&lt;br /&gt;
{&lt;br /&gt;
    registro[i][counter[i]-1] = m; // il secondo indice indica l'iesimo lancio -1 (perchè iniziamo a contare da zero)&lt;br /&gt;
    if(i == NATLETI-1) // se ha appena tirato l'ultimo atleta non posso dare il via a NATLETI (perchè non esiste), quindi faccio ricominciare il giro&lt;br /&gt;
        ok2lancia[0].signal();&lt;br /&gt;
    else&lt;br /&gt;
        ok2lancia[i+1].signal();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: int classifica()&lt;br /&gt;
{&lt;br /&gt;
    int best[NATLETI];&lt;br /&gt;
    for(int i = 0; i &amp;lt; NATLETI; i++)&lt;br /&gt;
    {&lt;br /&gt;
        for(int j = 0; j &amp;lt; 3; j++)&lt;br /&gt;
        {&lt;br /&gt;
            if(registro[i][j] &amp;gt; best[i])&lt;br /&gt;
                best[i] = registro[i][j];&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    best.sort_in_descending_order(); // supponiamo nel nostro pseudolinguaggio esista una funzione di ordinamento qualunque&lt;br /&gt;
    return best;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Esame 29/05/2017 ==&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2017.05.29.tot.pdf 2017.05.29.tot.pdf]&lt;br /&gt;
=== Esercizio c.1 ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
condition okpartita&lt;br /&gt;
condition ok2chiama&lt;br /&gt;
condition ok2punteggio&lt;br /&gt;
condition ok2run[2][MAX]&lt;br /&gt;
int numpronti&lt;br /&gt;
int punteggio[2]&lt;br /&gt;
boolean partita=false&lt;br /&gt;
boolean partitafinita=false&lt;br /&gt;
chiamati = []&lt;br /&gt;
contabandiera[2]&lt;br /&gt;
int winner&lt;br /&gt;
&lt;br /&gt;
entry nuovapartita():&lt;br /&gt;
{&lt;br /&gt;
    punteggio[A] = punteggio[B] = 0;&lt;br /&gt;
    numpronti = 0;&lt;br /&gt;
    partita=true;&lt;br /&gt;
    okpartita.signal()&lt;br /&gt;
    chiamati = [];&lt;br /&gt;
}&lt;br /&gt;
entry chiama(l):&lt;br /&gt;
{&lt;br /&gt;
    if (numpronti&amp;lt;2*MAX)&lt;br /&gt;
    {&lt;br /&gt;
        ok2chiama.wait();&lt;br /&gt;
    }&lt;br /&gt;
    chiamati = l;&lt;br /&gt;
    contabandiera[A] = contabandiera[B] = 0&lt;br /&gt;
    winner = -1;&lt;br /&gt;
    for (s in n)&lt;br /&gt;
    {&lt;br /&gt;
        ok2run[A][s].signal();&lt;br /&gt;
        ok2run[B][s].signal()&lt;br /&gt;
    }&lt;br /&gt;
    ok2punteggio.wait();&lt;br /&gt;
    punteggio[winner++]&lt;br /&gt;
    if (max(punteggio) == 10)&lt;br /&gt;
    {&lt;br /&gt;
        partitafinita = true;&lt;br /&gt;
        for (s in A,B)&lt;br /&gt;
        {&lt;br /&gt;
            for (n in range(MAX))&lt;br /&gt;
            {&lt;br /&gt;
                ok2run[s][n].signal();&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    return punteggio;&lt;br /&gt;
}&lt;br /&gt;
entry pronto(s, n):&lt;br /&gt;
{&lt;br /&gt;
    if (partitafinita) return 1;&lt;br /&gt;
    if (!partita)&lt;br /&gt;
    {&lt;br /&gt;
        okpartita.wait();&lt;br /&gt;
    }&lt;br /&gt;
    numpronti++;&lt;br /&gt;
    if (numpronti&amp;gt;=2*MAX)&lt;br /&gt;
    {&lt;br /&gt;
        ok2chiama.signal();&lt;br /&gt;
    }&lt;br /&gt;
    if (!(n in chiamati))&lt;br /&gt;
    {&lt;br /&gt;
        ok2run[s][n].wait();&lt;br /&gt;
    }&lt;br /&gt;
    numpronti--;&lt;br /&gt;
    return 0 if partita else 1;&lt;br /&gt;
}&lt;br /&gt;
allabandiera(s, n):&lt;br /&gt;
{&lt;br /&gt;
    contabandiera[s]++;&lt;br /&gt;
    if (winner == -1 &amp;amp;&amp;amp; contabandiera[s] == len(chiamati))&lt;br /&gt;
    {&lt;br /&gt;
        winner = s;&lt;br /&gt;
    }&lt;br /&gt;
    if (contabandiera[A] == len(chiamati) &amp;amp;&amp;amp; contabandiera[B] == len(chiamati))&lt;br /&gt;
    {&lt;br /&gt;
        ok2punteggio.signal();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
casi da discutere:    &lt;br /&gt;
se arrivano studenti a pronto prima che il prof dichiara nuovapartita succedono guai.&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>LiberaL</name></author>
	</entry>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=Prove_scritte_2017&amp;diff=3035</id>
		<title>Prove scritte 2017</title>
		<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php?title=Prove_scritte_2017&amp;diff=3035"/>
		<updated>2023-05-29T04:04:17Z</updated>

		<summary type="html">&lt;p&gt;LiberaL: /* Esercizio c.2 (da controllare) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Esame 11/09/2017 ==&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2017.09.11.tot.pdf 2017.09.11.tot.pdf]&lt;br /&gt;
=== Esercizio c.1 ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
monitor crossing&lt;br /&gt;
&lt;br /&gt;
ok2dir[4];     //NESW&lt;br /&gt;
bool busy = false;&lt;br /&gt;
&lt;br /&gt;
pe entra(int dir)&lt;br /&gt;
   if (busy)&lt;br /&gt;
      ok2dir[dir].wait();&lt;br /&gt;
   busy = true;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
pe esci(int dir)&lt;br /&gt;
   busy = false;&lt;br /&gt;
   ok2dir[(dir + 1) % 4].signal();&lt;br /&gt;
   if (!busy)&lt;br /&gt;
      ok2dir[(dir + 2) % 4].signal();&lt;br /&gt;
   if (!busy)&lt;br /&gt;
      ok2dir[(dir + 3) % 4].signal();&lt;br /&gt;
   if (!busy)&lt;br /&gt;
      ok2dir[(dir + 4) % 4].signal();  //dir&lt;br /&gt;
&lt;br /&gt;
//alternativa più compatta&lt;br /&gt;
pe esci(int dir)&lt;br /&gt;
   busy = false;&lt;br /&gt;
   for (i = 0; i &amp;lt; 4; i++)&lt;br /&gt;
   if (!busy)&lt;br /&gt;
      ok2dir[(dir + i + 1) % 4].signal();&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Soluzione proposta 2 ==== &lt;br /&gt;
Soluzione proposta da [https://t.me/LLibera LLibera] e corretta da  [https://so.v2.cs.unibo.it/wiki/index.php/User:Flecart Flecart]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
const int N_DIRECTION = 4;&lt;br /&gt;
&lt;br /&gt;
// assumo N = 0, E = 1, S = 2, W = 3, oppure shiftati ciclicamente, è equivalente&lt;br /&gt;
&lt;br /&gt;
monitor crossing {&lt;br /&gt;
	bool free;										//l'incrocio è libero?&lt;br /&gt;
	int num_waiting[N_DIRECTION];&lt;br /&gt;
	condition okToCross[N_DIRECTION];				//free == True&lt;br /&gt;
	&lt;br /&gt;
	crossing() {&lt;br /&gt;
		free = True;								//parto con l'incrocio libero&lt;br /&gt;
		for (int i = 0; i &amp;lt; N_DIRECTION; i++) {&lt;br /&gt;
			num_waiting[i] = 0;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	procedure entry enter(int direction) {&lt;br /&gt;
		if(!free) {									//se l'incrocio non è libero&lt;br /&gt;
			num_waiting[direction]++;&lt;br /&gt;
			okToCross[direction].wait();			//aspetto nella mia direzione&lt;br /&gt;
			num_waiting[direction]--;&lt;br /&gt;
		}&lt;br /&gt;
													//ora sono sicurə che sia libero&lt;br /&gt;
		free = False;								//quindi lo dichiaro occupato&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	procedure entry exit(int direction) {&lt;br /&gt;
													//non devo aspettare niente per liberare l'incrocio&lt;br /&gt;
		free = True;								//lo dichiaro libero&lt;br /&gt;
		&lt;br /&gt;
		for (int i = 0; i &amp;lt; N_DIRECTION; i++) {&lt;br /&gt;
			int curr_dir = (direction + i + 1) % N_DIRECTION;&lt;br /&gt;
			if (num_waiting[curr_dir] &amp;gt; 0) {&lt;br /&gt;
				okToCross[curr_dir].signal();&lt;br /&gt;
				break;	// l'onere di risvegliare gli altri è stato passato al nuovo processo risvegliato, quindi esco.&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.2 (da controllare) ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// server[] = array contenente il PID di tutti i server&lt;br /&gt;
&lt;br /&gt;
#define BROADCAST server[0]&lt;br /&gt;
&lt;br /&gt;
server[0]&lt;br /&gt;
{&lt;br /&gt;
    while(true)&lt;br /&gt;
    {&lt;br /&gt;
        &amp;lt;msg, sender&amp;gt; = arecv(*); // ricevo il messaggio&lt;br /&gt;
        if (sender == BROADCAST)&lt;br /&gt;
            print(msg); // se il messaggio l'ho ricevuto da me stesso allora lo stampo&lt;br /&gt;
        else&lt;br /&gt;
            asend(*, &amp;lt;msg, getpid()&amp;gt;); // se il messaggio l'ho ricevuto da un client o da un altro server lo inoltro a tutti i server (compreso me stesso)&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
server[x] // x = 1...N-1&lt;br /&gt;
{&lt;br /&gt;
    while(true)&lt;br /&gt;
    {&lt;br /&gt;
        &amp;lt;msg, sender&amp;gt; = arecv(*); // ricevo il messaggio&lt;br /&gt;
        if (sender == BROADCAST)&lt;br /&gt;
            print(msg); // se il messaggio l'ho ricevuto dal server[0] allora lo stampo&lt;br /&gt;
        else&lt;br /&gt;
            asend(BROADCAST, &amp;lt;msg, getpid()&amp;gt;) // se il messaggio l'ho ricevuto da un client lo inoltro al server[0]&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Soluzione proposta 2 ====&lt;br /&gt;
&lt;br /&gt;
Soluzione proposta da [https://so.v2.cs.unibo.it/wiki/index.php/User:Flecart Flecart]&lt;br /&gt;
Soluzione corretta da [https://so.v2.cs.unibo.it/wiki/index.php/User:Gio Flecart friend]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
process server_0 {&lt;br /&gt;
&lt;br /&gt;
        while (true) {&lt;br /&gt;
                &amp;lt;msg, sender&amp;gt; = arecv(ANY);&lt;br /&gt;
                for (int i = 1 ; i &amp;lt; N; i++) {&lt;br /&gt;
                        asend(&amp;lt;msg, 0&amp;gt;, server[i]);&lt;br /&gt;
                        while(true){&lt;br /&gt;
                          msg = arecv(server[i]); // così so che tutti abbiano stampato.&lt;br /&gt;
                          if(msg==ACK)&lt;br /&gt;
                            break&lt;br /&gt;
                          asend(msg,server[0]);&lt;br /&gt;
                        }&lt;br /&gt;
                }&lt;br /&gt;
                print(msg);&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
process server_[i=1 to N - 1] {&lt;br /&gt;
        while (true) {&lt;br /&gt;
                &amp;lt;msg, sender&amp;gt; = arecv(ANY);&lt;br /&gt;
                if (sender == 0) {&lt;br /&gt;
                        print(msg);&lt;br /&gt;
                        asend(ACK, server[0]);&lt;br /&gt;
                } else {&lt;br /&gt;
                        asend(&amp;lt;msg, i&amp;gt;, server[0]);&lt;br /&gt;
                }&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Esame 17/07/2017 ==&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2017.07.17.tot.pdf 2017.07.17.tot.pdf]&lt;br /&gt;
=== Esercizio c.1 ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
monitor conf {&lt;br /&gt;
        condition finished;&lt;br /&gt;
        condition ready2present[max];&lt;br /&gt;
        bool arrived[max] = false;&lt;br /&gt;
        bool giachiamato[max] = false;&lt;br /&gt;
&lt;br /&gt;
        entry chiama(chiamato){&lt;br /&gt;
        if(arrived[chiamato] == true)&lt;br /&gt;
                ready2present[chiamato].signal;&lt;br /&gt;
                finished.wait;&lt;br /&gt;
                return true;&lt;br /&gt;
        else&lt;br /&gt;
                giachiamato[chiamato]= true&lt;br /&gt;
                return false;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        entry arrivato(nome){&lt;br /&gt;
                if(giachiamato[nome] == true)&lt;br /&gt;
                        return  false;&lt;br /&gt;
&lt;br /&gt;
                arrived[nome] = true;&lt;br /&gt;
                ok2present[nome].wait;&lt;br /&gt;
                return true;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        entry finepresentazione(nome){&lt;br /&gt;
                finished.signal;&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.2 (da controllare) ===&lt;br /&gt;
controllata da [[User:LiberaL|LiberaL]] 14:26, 26 May 2023 (CEST) l'implementazione fornita gestisce solo il caso di arecv(ANY) e non arecv(mittente)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
si, è possibile: &lt;br /&gt;
&lt;br /&gt;
Implementare asend e arecv date bsend e brecv&lt;br /&gt;
&lt;br /&gt;
asend(pid_t dst, msg_type msg){&lt;br /&gt;
    bsend (&amp;lt;dst, msg&amp;gt;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
arecv(*){&lt;br /&gt;
  do {&lt;br /&gt;
    &amp;lt;dst, msg&amp;gt; = brecv(*);&lt;br /&gt;
  } while (dst != getpid())&lt;br /&gt;
  return msg;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
propongo ([[User:LiberaL|LiberaL]] 06:04, 29 May 2023 (CEST)) quindi questa implementazione con gestione arecv da mittente specificato (sempre da controllare)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
//il messaggio mandato è la tripla &amp;lt;destinatario, mittente, messaggio&amp;gt;&lt;br /&gt;
&lt;br /&gt;
asend(pid_t dst, msg_type msg){&lt;br /&gt;
    bsend (&amp;lt;dst, getpid(), msg&amp;gt;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Queue of &amp;lt;pid_t, msg_type&amp;gt; db; //nota: salvo qui solo se il messaggio è per me, quindi dest non mi serve&lt;br /&gt;
&lt;br /&gt;
arecv(pid_t sender) {&lt;br /&gt;
&lt;br /&gt;
  //devo controllare se nella coda ho già ricevuto il messaggio da quel mittente, ovvero mentre aspettavo un messaggio da qualcun'altro&lt;br /&gt;
  //db.get(sender) cerca una tripla il cui mittente è sender&lt;br /&gt;
  //se trova il messaggio lo rimuove anche dal db.&lt;br /&gt;
  //db.get(ANY) ritorna (ed elimina da db) il primo che trova (FIFO), e if(db.isEmpty()) return NULL;&lt;br /&gt;
  if( ( &amp;lt;mit, msg&amp;gt; = db.get(sender) ) != NULL ) //se lo trova&lt;br /&gt;
    return msg;&lt;br /&gt;
&lt;br /&gt;
  do {&lt;br /&gt;
    &amp;lt;dst, mit, msg&amp;gt; = brecv(*);                 //ricevo&lt;br /&gt;
    if( dst == getpid() ) {                     //il messaggio è per me?&lt;br /&gt;
      if ( mit == sender || sender == ANY )     //se devo ritornare il messaggio&lt;br /&gt;
       return msg;     //esci dal while&lt;br /&gt;
      //se devo salvarlo (sender specificato e messaggio per me)&lt;br /&gt;
      //metto in db i messaggi di altri mittenti, ricevuti quando ne aspettavo uno da un mittente specificato&lt;br /&gt;
      db.add(&amp;lt;mit, msg&amp;gt;);&lt;br /&gt;
    }&lt;br /&gt;
  } while ( true ) //devo uscire solo con il return&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Esame 19/06/2017 ==&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2017.06.19.tot.pdf 2017.06.19.tot.pdf]&lt;br /&gt;
=== Esercizio c.1 (da controllare)===&lt;br /&gt;
&lt;br /&gt;
* Mi sembra che ci sia un errore per il giodice, potrebbe succedere in un caso che il wait non si risvegli mai [[User:Flecart|Flecart]] ([[User talk:Flecart|talk]]) 15:38, 19 January 2023 (CET)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define NATLETI n&lt;br /&gt;
&lt;br /&gt;
condition ok2lancia[NATLETI];&lt;br /&gt;
condition ok2giudice;&lt;br /&gt;
&lt;br /&gt;
int counter[NATLETI];&lt;br /&gt;
int ultimo_tiro;&lt;br /&gt;
float registro[NATLETI][3];&lt;br /&gt;
&lt;br /&gt;
Procedure entry: boolean pronto(int i)&lt;br /&gt;
{&lt;br /&gt;
    if(!(i == 0 &amp;amp;&amp;amp; counter[i] == 0)) // se è il primo lancio non devo metterlo in wait&lt;br /&gt;
        ok2lancia[i].wait()&lt;br /&gt;
    if(counter[i] &amp;lt; 3)&lt;br /&gt;
        return true;&lt;br /&gt;
    else&lt;br /&gt;
        return false;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: void lanciato (int i)&lt;br /&gt;
{&lt;br /&gt;
    counter[i]++;&lt;br /&gt;
    ultimo_tiro = i;&lt;br /&gt;
    ok2giudice.signal();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: int lanciofatto()&lt;br /&gt;
{&lt;br /&gt;
    ok2giudice.wait()&lt;br /&gt;
    if(ultimo_tiro == NATLETI-1 &amp;amp;&amp;amp; counter[0] == 3)&lt;br /&gt;
        return -1;  // devo invalidare la condizione per uscire dal while, quindi se nessuno deve più lanciare ritorno -1&lt;br /&gt;
    else&lt;br /&gt;
        return ultimo_tiro;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: void registraechiama(int i, float m)&lt;br /&gt;
{&lt;br /&gt;
    registro[i][counter[i]-1] = m; // il secondo indice indica l'iesimo lancio -1 (perchè iniziamo a contare da zero)&lt;br /&gt;
    if(i == NATLETI-1) // se ha appena tirato l'ultimo atleta non posso dare il via a NATLETI (perchè non esiste), quindi faccio ricominciare il giro&lt;br /&gt;
        ok2lancia[0].signal();&lt;br /&gt;
    else&lt;br /&gt;
        ok2lancia[i+1].signal();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: int classifica()&lt;br /&gt;
{&lt;br /&gt;
    int best[NATLETI];&lt;br /&gt;
    for(int i = 0; i &amp;lt; NATLETI; i++)&lt;br /&gt;
    {&lt;br /&gt;
        for(int j = 0; j &amp;lt; 3; j++)&lt;br /&gt;
        {&lt;br /&gt;
            if(registro[i][j] &amp;gt; best[i])&lt;br /&gt;
                best[i] = registro[i][j];&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    best.sort_in_descending_order(); // supponiamo nel nostro pseudolinguaggio esista una funzione di ordinamento qualunque&lt;br /&gt;
    return best;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Esame 29/05/2017 ==&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2017.05.29.tot.pdf 2017.05.29.tot.pdf]&lt;br /&gt;
=== Esercizio c.1 ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
condition okpartita&lt;br /&gt;
condition ok2chiama&lt;br /&gt;
condition ok2punteggio&lt;br /&gt;
condition ok2run[2][MAX]&lt;br /&gt;
int numpronti&lt;br /&gt;
int punteggio[2]&lt;br /&gt;
boolean partita=false&lt;br /&gt;
boolean partitafinita=false&lt;br /&gt;
chiamati = []&lt;br /&gt;
contabandiera[2]&lt;br /&gt;
int winner&lt;br /&gt;
&lt;br /&gt;
entry nuovapartita():&lt;br /&gt;
{&lt;br /&gt;
    punteggio[A] = punteggio[B] = 0;&lt;br /&gt;
    numpronti = 0;&lt;br /&gt;
    partita=true;&lt;br /&gt;
    okpartita.signal()&lt;br /&gt;
    chiamati = [];&lt;br /&gt;
}&lt;br /&gt;
entry chiama(l):&lt;br /&gt;
{&lt;br /&gt;
    if (numpronti&amp;lt;2*MAX)&lt;br /&gt;
    {&lt;br /&gt;
        ok2chiama.wait();&lt;br /&gt;
    }&lt;br /&gt;
    chiamati = l;&lt;br /&gt;
    contabandiera[A] = contabandiera[B] = 0&lt;br /&gt;
    winner = -1;&lt;br /&gt;
    for (s in n)&lt;br /&gt;
    {&lt;br /&gt;
        ok2run[A][s].signal();&lt;br /&gt;
        ok2run[B][s].signal()&lt;br /&gt;
    }&lt;br /&gt;
    ok2punteggio.wait();&lt;br /&gt;
    punteggio[winner++]&lt;br /&gt;
    if (max(punteggio) == 10)&lt;br /&gt;
    {&lt;br /&gt;
        partitafinita = true;&lt;br /&gt;
        for (s in A,B)&lt;br /&gt;
        {&lt;br /&gt;
            for (n in range(MAX))&lt;br /&gt;
            {&lt;br /&gt;
                ok2run[s][n].signal();&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    return punteggio;&lt;br /&gt;
}&lt;br /&gt;
entry pronto(s, n):&lt;br /&gt;
{&lt;br /&gt;
    if (partitafinita) return 1;&lt;br /&gt;
    if (!partita)&lt;br /&gt;
    {&lt;br /&gt;
        okpartita.wait();&lt;br /&gt;
    }&lt;br /&gt;
    numpronti++;&lt;br /&gt;
    if (numpronti&amp;gt;=2*MAX)&lt;br /&gt;
    {&lt;br /&gt;
        ok2chiama.signal();&lt;br /&gt;
    }&lt;br /&gt;
    if (!(n in chiamati))&lt;br /&gt;
    {&lt;br /&gt;
        ok2run[s][n].wait();&lt;br /&gt;
    }&lt;br /&gt;
    numpronti--;&lt;br /&gt;
    return 0 if partita else 1;&lt;br /&gt;
}&lt;br /&gt;
allabandiera(s, n):&lt;br /&gt;
{&lt;br /&gt;
    contabandiera[s]++;&lt;br /&gt;
    if (winner == -1 &amp;amp;&amp;amp; contabandiera[s] == len(chiamati))&lt;br /&gt;
    {&lt;br /&gt;
        winner = s;&lt;br /&gt;
    }&lt;br /&gt;
    if (contabandiera[A] == len(chiamati) &amp;amp;&amp;amp; contabandiera[B] == len(chiamati))&lt;br /&gt;
    {&lt;br /&gt;
        ok2punteggio.signal();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
casi da discutere:    &lt;br /&gt;
se arrivano studenti a pronto prima che il prof dichiara nuovapartita succedono guai.&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>LiberaL</name></author>
	</entry>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=Prove_scritte_2017&amp;diff=3034</id>
		<title>Prove scritte 2017</title>
		<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php?title=Prove_scritte_2017&amp;diff=3034"/>
		<updated>2023-05-29T03:56:55Z</updated>

		<summary type="html">&lt;p&gt;LiberaL: /* Esercizio c.2 (da controllare) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Esame 11/09/2017 ==&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2017.09.11.tot.pdf 2017.09.11.tot.pdf]&lt;br /&gt;
=== Esercizio c.1 ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
monitor crossing&lt;br /&gt;
&lt;br /&gt;
ok2dir[4];     //NESW&lt;br /&gt;
bool busy = false;&lt;br /&gt;
&lt;br /&gt;
pe entra(int dir)&lt;br /&gt;
   if (busy)&lt;br /&gt;
      ok2dir[dir].wait();&lt;br /&gt;
   busy = true;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
pe esci(int dir)&lt;br /&gt;
   busy = false;&lt;br /&gt;
   ok2dir[(dir + 1) % 4].signal();&lt;br /&gt;
   if (!busy)&lt;br /&gt;
      ok2dir[(dir + 2) % 4].signal();&lt;br /&gt;
   if (!busy)&lt;br /&gt;
      ok2dir[(dir + 3) % 4].signal();&lt;br /&gt;
   if (!busy)&lt;br /&gt;
      ok2dir[(dir + 4) % 4].signal();  //dir&lt;br /&gt;
&lt;br /&gt;
//alternativa più compatta&lt;br /&gt;
pe esci(int dir)&lt;br /&gt;
   busy = false;&lt;br /&gt;
   for (i = 0; i &amp;lt; 4; i++)&lt;br /&gt;
   if (!busy)&lt;br /&gt;
      ok2dir[(dir + i + 1) % 4].signal();&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Soluzione proposta 2 ==== &lt;br /&gt;
Soluzione proposta da [https://t.me/LLibera LLibera] e corretta da  [https://so.v2.cs.unibo.it/wiki/index.php/User:Flecart Flecart]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
const int N_DIRECTION = 4;&lt;br /&gt;
&lt;br /&gt;
// assumo N = 0, E = 1, S = 2, W = 3, oppure shiftati ciclicamente, è equivalente&lt;br /&gt;
&lt;br /&gt;
monitor crossing {&lt;br /&gt;
	bool free;										//l'incrocio è libero?&lt;br /&gt;
	int num_waiting[N_DIRECTION];&lt;br /&gt;
	condition okToCross[N_DIRECTION];				//free == True&lt;br /&gt;
	&lt;br /&gt;
	crossing() {&lt;br /&gt;
		free = True;								//parto con l'incrocio libero&lt;br /&gt;
		for (int i = 0; i &amp;lt; N_DIRECTION; i++) {&lt;br /&gt;
			num_waiting[i] = 0;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	procedure entry enter(int direction) {&lt;br /&gt;
		if(!free) {									//se l'incrocio non è libero&lt;br /&gt;
			num_waiting[direction]++;&lt;br /&gt;
			okToCross[direction].wait();			//aspetto nella mia direzione&lt;br /&gt;
			num_waiting[direction]--;&lt;br /&gt;
		}&lt;br /&gt;
													//ora sono sicurə che sia libero&lt;br /&gt;
		free = False;								//quindi lo dichiaro occupato&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	procedure entry exit(int direction) {&lt;br /&gt;
													//non devo aspettare niente per liberare l'incrocio&lt;br /&gt;
		free = True;								//lo dichiaro libero&lt;br /&gt;
		&lt;br /&gt;
		for (int i = 0; i &amp;lt; N_DIRECTION; i++) {&lt;br /&gt;
			int curr_dir = (direction + i + 1) % N_DIRECTION;&lt;br /&gt;
			if (num_waiting[curr_dir] &amp;gt; 0) {&lt;br /&gt;
				okToCross[curr_dir].signal();&lt;br /&gt;
				break;	// l'onere di risvegliare gli altri è stato passato al nuovo processo risvegliato, quindi esco.&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.2 (da controllare) ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// server[] = array contenente il PID di tutti i server&lt;br /&gt;
&lt;br /&gt;
#define BROADCAST server[0]&lt;br /&gt;
&lt;br /&gt;
server[0]&lt;br /&gt;
{&lt;br /&gt;
    while(true)&lt;br /&gt;
    {&lt;br /&gt;
        &amp;lt;msg, sender&amp;gt; = arecv(*); // ricevo il messaggio&lt;br /&gt;
        if (sender == BROADCAST)&lt;br /&gt;
            print(msg); // se il messaggio l'ho ricevuto da me stesso allora lo stampo&lt;br /&gt;
        else&lt;br /&gt;
            asend(*, &amp;lt;msg, getpid()&amp;gt;); // se il messaggio l'ho ricevuto da un client o da un altro server lo inoltro a tutti i server (compreso me stesso)&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
server[x] // x = 1...N-1&lt;br /&gt;
{&lt;br /&gt;
    while(true)&lt;br /&gt;
    {&lt;br /&gt;
        &amp;lt;msg, sender&amp;gt; = arecv(*); // ricevo il messaggio&lt;br /&gt;
        if (sender == BROADCAST)&lt;br /&gt;
            print(msg); // se il messaggio l'ho ricevuto dal server[0] allora lo stampo&lt;br /&gt;
        else&lt;br /&gt;
            asend(BROADCAST, &amp;lt;msg, getpid()&amp;gt;) // se il messaggio l'ho ricevuto da un client lo inoltro al server[0]&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Soluzione proposta 2 ====&lt;br /&gt;
&lt;br /&gt;
Soluzione proposta da [https://so.v2.cs.unibo.it/wiki/index.php/User:Flecart Flecart]&lt;br /&gt;
Soluzione corretta da [https://so.v2.cs.unibo.it/wiki/index.php/User:Gio Flecart friend]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
process server_0 {&lt;br /&gt;
&lt;br /&gt;
        while (true) {&lt;br /&gt;
                &amp;lt;msg, sender&amp;gt; = arecv(ANY);&lt;br /&gt;
                for (int i = 1 ; i &amp;lt; N; i++) {&lt;br /&gt;
                        asend(&amp;lt;msg, 0&amp;gt;, server[i]);&lt;br /&gt;
                        while(true){&lt;br /&gt;
                          msg = arecv(server[i]); // così so che tutti abbiano stampato.&lt;br /&gt;
                          if(msg==ACK)&lt;br /&gt;
                            break&lt;br /&gt;
                          asend(msg,server[0]);&lt;br /&gt;
                        }&lt;br /&gt;
                }&lt;br /&gt;
                print(msg);&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
process server_[i=1 to N - 1] {&lt;br /&gt;
        while (true) {&lt;br /&gt;
                &amp;lt;msg, sender&amp;gt; = arecv(ANY);&lt;br /&gt;
                if (sender == 0) {&lt;br /&gt;
                        print(msg);&lt;br /&gt;
                        asend(ACK, server[0]);&lt;br /&gt;
                } else {&lt;br /&gt;
                        asend(&amp;lt;msg, i&amp;gt;, server[0]);&lt;br /&gt;
                }&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Esame 17/07/2017 ==&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2017.07.17.tot.pdf 2017.07.17.tot.pdf]&lt;br /&gt;
=== Esercizio c.1 ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
monitor conf {&lt;br /&gt;
        condition finished;&lt;br /&gt;
        condition ready2present[max];&lt;br /&gt;
        bool arrived[max] = false;&lt;br /&gt;
        bool giachiamato[max] = false;&lt;br /&gt;
&lt;br /&gt;
        entry chiama(chiamato){&lt;br /&gt;
        if(arrived[chiamato] == true)&lt;br /&gt;
                ready2present[chiamato].signal;&lt;br /&gt;
                finished.wait;&lt;br /&gt;
                return true;&lt;br /&gt;
        else&lt;br /&gt;
                giachiamato[chiamato]= true&lt;br /&gt;
                return false;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        entry arrivato(nome){&lt;br /&gt;
                if(giachiamato[nome] == true)&lt;br /&gt;
                        return  false;&lt;br /&gt;
&lt;br /&gt;
                arrived[nome] = true;&lt;br /&gt;
                ok2present[nome].wait;&lt;br /&gt;
                return true;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        entry finepresentazione(nome){&lt;br /&gt;
                finished.signal;&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.2 (da controllare) ===&lt;br /&gt;
controllata da [[User:LiberaL|LiberaL]] 14:26, 26 May 2023 (CEST) l'implementazione fornita gestisce solo il caso di arecv(ANY) e non arecv(mittente)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
si, è possibile: &lt;br /&gt;
&lt;br /&gt;
Implementare asend e arecv date bsend e brecv&lt;br /&gt;
&lt;br /&gt;
asend(pid_t dst, msg_type msg){&lt;br /&gt;
    bsend (&amp;lt;dst, msg&amp;gt;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
arecv(*){&lt;br /&gt;
  do {&lt;br /&gt;
    &amp;lt;dst, msg&amp;gt; = brecv(*);&lt;br /&gt;
  } while (dst != getpid())&lt;br /&gt;
  return msg;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
propongo ([[User:LiberaL|LiberaL]] 05:56, 29 May 2023 (CEST)) quindi questa implementazione con gestione arecv da mittente specificato (sempre da controllare)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
//il messaggio mandato è la tripla &amp;lt;destinatario, mittente, messaggio&amp;gt;&lt;br /&gt;
&lt;br /&gt;
asend(pid_t dst, msg_type msg){&lt;br /&gt;
    bsend (&amp;lt;dst, getpid(), msg&amp;gt;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Queue of &amp;lt;pid_t, msg_type&amp;gt; db; //nota: salvo qui solo se il messaggio è per me, quindi dest non mi serve&lt;br /&gt;
&lt;br /&gt;
arecv(pid_t sender) {&lt;br /&gt;
&lt;br /&gt;
  //devo controllare se nella coda ho già ricevuto il messaggio da quel mittente, ovvero mentre aspettavo un messaggio da qualcun'altro&lt;br /&gt;
  //db.get(sender) cerca una tripla il cui mittente è sender&lt;br /&gt;
  //se trova il messaggio lo rimuove anche dal db.&lt;br /&gt;
  //db.get(ANY) ritorna (ed elimina da db) il primo che trova (FIFO), e if(db.isEmpty()) return NULL;&lt;br /&gt;
  if( ( &amp;lt;mit, msg&amp;gt; = db.get(sender) ) != NULL ) //se lo trova&lt;br /&gt;
    return msg;&lt;br /&gt;
&lt;br /&gt;
  do {&lt;br /&gt;
    &amp;lt;dst, mit, msg&amp;gt; = brecv(*);                 //ricevo&lt;br /&gt;
    if( dst == getpid() ) {                     //il messaggio è per me?&lt;br /&gt;
      if ( mit == sender || sender == ANY )     //se devo ritornare il messaggio&lt;br /&gt;
        break;     //esci dal while&lt;br /&gt;
      //se devo salvarlo (sender specificato e messaggio per me)&lt;br /&gt;
      //devo mettere in db i messaggi di altri mittenti, ricevuti quando ne aspettavo uno da un mittente specificato&lt;br /&gt;
      db.add(&amp;lt;mit, msg&amp;gt;);&lt;br /&gt;
      //devo anche continuare a ricevere altri messaggi&lt;br /&gt;
    }&lt;br /&gt;
  } while ( true ) //devo uscire solo con il break&lt;br /&gt;
&lt;br /&gt;
  return msg;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Esame 19/06/2017 ==&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2017.06.19.tot.pdf 2017.06.19.tot.pdf]&lt;br /&gt;
=== Esercizio c.1 (da controllare)===&lt;br /&gt;
&lt;br /&gt;
* Mi sembra che ci sia un errore per il giodice, potrebbe succedere in un caso che il wait non si risvegli mai [[User:Flecart|Flecart]] ([[User talk:Flecart|talk]]) 15:38, 19 January 2023 (CET)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define NATLETI n&lt;br /&gt;
&lt;br /&gt;
condition ok2lancia[NATLETI];&lt;br /&gt;
condition ok2giudice;&lt;br /&gt;
&lt;br /&gt;
int counter[NATLETI];&lt;br /&gt;
int ultimo_tiro;&lt;br /&gt;
float registro[NATLETI][3];&lt;br /&gt;
&lt;br /&gt;
Procedure entry: boolean pronto(int i)&lt;br /&gt;
{&lt;br /&gt;
    if(!(i == 0 &amp;amp;&amp;amp; counter[i] == 0)) // se è il primo lancio non devo metterlo in wait&lt;br /&gt;
        ok2lancia[i].wait()&lt;br /&gt;
    if(counter[i] &amp;lt; 3)&lt;br /&gt;
        return true;&lt;br /&gt;
    else&lt;br /&gt;
        return false;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: void lanciato (int i)&lt;br /&gt;
{&lt;br /&gt;
    counter[i]++;&lt;br /&gt;
    ultimo_tiro = i;&lt;br /&gt;
    ok2giudice.signal();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: int lanciofatto()&lt;br /&gt;
{&lt;br /&gt;
    ok2giudice.wait()&lt;br /&gt;
    if(ultimo_tiro == NATLETI-1 &amp;amp;&amp;amp; counter[0] == 3)&lt;br /&gt;
        return -1;  // devo invalidare la condizione per uscire dal while, quindi se nessuno deve più lanciare ritorno -1&lt;br /&gt;
    else&lt;br /&gt;
        return ultimo_tiro;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: void registraechiama(int i, float m)&lt;br /&gt;
{&lt;br /&gt;
    registro[i][counter[i]-1] = m; // il secondo indice indica l'iesimo lancio -1 (perchè iniziamo a contare da zero)&lt;br /&gt;
    if(i == NATLETI-1) // se ha appena tirato l'ultimo atleta non posso dare il via a NATLETI (perchè non esiste), quindi faccio ricominciare il giro&lt;br /&gt;
        ok2lancia[0].signal();&lt;br /&gt;
    else&lt;br /&gt;
        ok2lancia[i+1].signal();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: int classifica()&lt;br /&gt;
{&lt;br /&gt;
    int best[NATLETI];&lt;br /&gt;
    for(int i = 0; i &amp;lt; NATLETI; i++)&lt;br /&gt;
    {&lt;br /&gt;
        for(int j = 0; j &amp;lt; 3; j++)&lt;br /&gt;
        {&lt;br /&gt;
            if(registro[i][j] &amp;gt; best[i])&lt;br /&gt;
                best[i] = registro[i][j];&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    best.sort_in_descending_order(); // supponiamo nel nostro pseudolinguaggio esista una funzione di ordinamento qualunque&lt;br /&gt;
    return best;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Esame 29/05/2017 ==&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2017.05.29.tot.pdf 2017.05.29.tot.pdf]&lt;br /&gt;
=== Esercizio c.1 ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
condition okpartita&lt;br /&gt;
condition ok2chiama&lt;br /&gt;
condition ok2punteggio&lt;br /&gt;
condition ok2run[2][MAX]&lt;br /&gt;
int numpronti&lt;br /&gt;
int punteggio[2]&lt;br /&gt;
boolean partita=false&lt;br /&gt;
boolean partitafinita=false&lt;br /&gt;
chiamati = []&lt;br /&gt;
contabandiera[2]&lt;br /&gt;
int winner&lt;br /&gt;
&lt;br /&gt;
entry nuovapartita():&lt;br /&gt;
{&lt;br /&gt;
    punteggio[A] = punteggio[B] = 0;&lt;br /&gt;
    numpronti = 0;&lt;br /&gt;
    partita=true;&lt;br /&gt;
    okpartita.signal()&lt;br /&gt;
    chiamati = [];&lt;br /&gt;
}&lt;br /&gt;
entry chiama(l):&lt;br /&gt;
{&lt;br /&gt;
    if (numpronti&amp;lt;2*MAX)&lt;br /&gt;
    {&lt;br /&gt;
        ok2chiama.wait();&lt;br /&gt;
    }&lt;br /&gt;
    chiamati = l;&lt;br /&gt;
    contabandiera[A] = contabandiera[B] = 0&lt;br /&gt;
    winner = -1;&lt;br /&gt;
    for (s in n)&lt;br /&gt;
    {&lt;br /&gt;
        ok2run[A][s].signal();&lt;br /&gt;
        ok2run[B][s].signal()&lt;br /&gt;
    }&lt;br /&gt;
    ok2punteggio.wait();&lt;br /&gt;
    punteggio[winner++]&lt;br /&gt;
    if (max(punteggio) == 10)&lt;br /&gt;
    {&lt;br /&gt;
        partitafinita = true;&lt;br /&gt;
        for (s in A,B)&lt;br /&gt;
        {&lt;br /&gt;
            for (n in range(MAX))&lt;br /&gt;
            {&lt;br /&gt;
                ok2run[s][n].signal();&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    return punteggio;&lt;br /&gt;
}&lt;br /&gt;
entry pronto(s, n):&lt;br /&gt;
{&lt;br /&gt;
    if (partitafinita) return 1;&lt;br /&gt;
    if (!partita)&lt;br /&gt;
    {&lt;br /&gt;
        okpartita.wait();&lt;br /&gt;
    }&lt;br /&gt;
    numpronti++;&lt;br /&gt;
    if (numpronti&amp;gt;=2*MAX)&lt;br /&gt;
    {&lt;br /&gt;
        ok2chiama.signal();&lt;br /&gt;
    }&lt;br /&gt;
    if (!(n in chiamati))&lt;br /&gt;
    {&lt;br /&gt;
        ok2run[s][n].wait();&lt;br /&gt;
    }&lt;br /&gt;
    numpronti--;&lt;br /&gt;
    return 0 if partita else 1;&lt;br /&gt;
}&lt;br /&gt;
allabandiera(s, n):&lt;br /&gt;
{&lt;br /&gt;
    contabandiera[s]++;&lt;br /&gt;
    if (winner == -1 &amp;amp;&amp;amp; contabandiera[s] == len(chiamati))&lt;br /&gt;
    {&lt;br /&gt;
        winner = s;&lt;br /&gt;
    }&lt;br /&gt;
    if (contabandiera[A] == len(chiamati) &amp;amp;&amp;amp; contabandiera[B] == len(chiamati))&lt;br /&gt;
    {&lt;br /&gt;
        ok2punteggio.signal();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
casi da discutere:    &lt;br /&gt;
se arrivano studenti a pronto prima che il prof dichiara nuovapartita succedono guai.&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>LiberaL</name></author>
	</entry>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=Prove_scritte_2017&amp;diff=3033</id>
		<title>Prove scritte 2017</title>
		<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php?title=Prove_scritte_2017&amp;diff=3033"/>
		<updated>2023-05-29T03:50:59Z</updated>

		<summary type="html">&lt;p&gt;LiberaL: /* Esercizio c.2 (da controllare) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Esame 11/09/2017 ==&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2017.09.11.tot.pdf 2017.09.11.tot.pdf]&lt;br /&gt;
=== Esercizio c.1 ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
monitor crossing&lt;br /&gt;
&lt;br /&gt;
ok2dir[4];     //NESW&lt;br /&gt;
bool busy = false;&lt;br /&gt;
&lt;br /&gt;
pe entra(int dir)&lt;br /&gt;
   if (busy)&lt;br /&gt;
      ok2dir[dir].wait();&lt;br /&gt;
   busy = true;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
pe esci(int dir)&lt;br /&gt;
   busy = false;&lt;br /&gt;
   ok2dir[(dir + 1) % 4].signal();&lt;br /&gt;
   if (!busy)&lt;br /&gt;
      ok2dir[(dir + 2) % 4].signal();&lt;br /&gt;
   if (!busy)&lt;br /&gt;
      ok2dir[(dir + 3) % 4].signal();&lt;br /&gt;
   if (!busy)&lt;br /&gt;
      ok2dir[(dir + 4) % 4].signal();  //dir&lt;br /&gt;
&lt;br /&gt;
//alternativa più compatta&lt;br /&gt;
pe esci(int dir)&lt;br /&gt;
   busy = false;&lt;br /&gt;
   for (i = 0; i &amp;lt; 4; i++)&lt;br /&gt;
   if (!busy)&lt;br /&gt;
      ok2dir[(dir + i + 1) % 4].signal();&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Soluzione proposta 2 ==== &lt;br /&gt;
Soluzione proposta da [https://t.me/LLibera LLibera] e corretta da  [https://so.v2.cs.unibo.it/wiki/index.php/User:Flecart Flecart]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
const int N_DIRECTION = 4;&lt;br /&gt;
&lt;br /&gt;
// assumo N = 0, E = 1, S = 2, W = 3, oppure shiftati ciclicamente, è equivalente&lt;br /&gt;
&lt;br /&gt;
monitor crossing {&lt;br /&gt;
	bool free;										//l'incrocio è libero?&lt;br /&gt;
	int num_waiting[N_DIRECTION];&lt;br /&gt;
	condition okToCross[N_DIRECTION];				//free == True&lt;br /&gt;
	&lt;br /&gt;
	crossing() {&lt;br /&gt;
		free = True;								//parto con l'incrocio libero&lt;br /&gt;
		for (int i = 0; i &amp;lt; N_DIRECTION; i++) {&lt;br /&gt;
			num_waiting[i] = 0;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	procedure entry enter(int direction) {&lt;br /&gt;
		if(!free) {									//se l'incrocio non è libero&lt;br /&gt;
			num_waiting[direction]++;&lt;br /&gt;
			okToCross[direction].wait();			//aspetto nella mia direzione&lt;br /&gt;
			num_waiting[direction]--;&lt;br /&gt;
		}&lt;br /&gt;
													//ora sono sicurə che sia libero&lt;br /&gt;
		free = False;								//quindi lo dichiaro occupato&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	procedure entry exit(int direction) {&lt;br /&gt;
													//non devo aspettare niente per liberare l'incrocio&lt;br /&gt;
		free = True;								//lo dichiaro libero&lt;br /&gt;
		&lt;br /&gt;
		for (int i = 0; i &amp;lt; N_DIRECTION; i++) {&lt;br /&gt;
			int curr_dir = (direction + i + 1) % N_DIRECTION;&lt;br /&gt;
			if (num_waiting[curr_dir] &amp;gt; 0) {&lt;br /&gt;
				okToCross[curr_dir].signal();&lt;br /&gt;
				break;	// l'onere di risvegliare gli altri è stato passato al nuovo processo risvegliato, quindi esco.&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.2 (da controllare) ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// server[] = array contenente il PID di tutti i server&lt;br /&gt;
&lt;br /&gt;
#define BROADCAST server[0]&lt;br /&gt;
&lt;br /&gt;
server[0]&lt;br /&gt;
{&lt;br /&gt;
    while(true)&lt;br /&gt;
    {&lt;br /&gt;
        &amp;lt;msg, sender&amp;gt; = arecv(*); // ricevo il messaggio&lt;br /&gt;
        if (sender == BROADCAST)&lt;br /&gt;
            print(msg); // se il messaggio l'ho ricevuto da me stesso allora lo stampo&lt;br /&gt;
        else&lt;br /&gt;
            asend(*, &amp;lt;msg, getpid()&amp;gt;); // se il messaggio l'ho ricevuto da un client o da un altro server lo inoltro a tutti i server (compreso me stesso)&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
server[x] // x = 1...N-1&lt;br /&gt;
{&lt;br /&gt;
    while(true)&lt;br /&gt;
    {&lt;br /&gt;
        &amp;lt;msg, sender&amp;gt; = arecv(*); // ricevo il messaggio&lt;br /&gt;
        if (sender == BROADCAST)&lt;br /&gt;
            print(msg); // se il messaggio l'ho ricevuto dal server[0] allora lo stampo&lt;br /&gt;
        else&lt;br /&gt;
            asend(BROADCAST, &amp;lt;msg, getpid()&amp;gt;) // se il messaggio l'ho ricevuto da un client lo inoltro al server[0]&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Soluzione proposta 2 ====&lt;br /&gt;
&lt;br /&gt;
Soluzione proposta da [https://so.v2.cs.unibo.it/wiki/index.php/User:Flecart Flecart]&lt;br /&gt;
Soluzione corretta da [https://so.v2.cs.unibo.it/wiki/index.php/User:Gio Flecart friend]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
process server_0 {&lt;br /&gt;
&lt;br /&gt;
        while (true) {&lt;br /&gt;
                &amp;lt;msg, sender&amp;gt; = arecv(ANY);&lt;br /&gt;
                for (int i = 1 ; i &amp;lt; N; i++) {&lt;br /&gt;
                        asend(&amp;lt;msg, 0&amp;gt;, server[i]);&lt;br /&gt;
                        while(true){&lt;br /&gt;
                          msg = arecv(server[i]); // così so che tutti abbiano stampato.&lt;br /&gt;
                          if(msg==ACK)&lt;br /&gt;
                            break&lt;br /&gt;
                          asend(msg,server[0]);&lt;br /&gt;
                        }&lt;br /&gt;
                }&lt;br /&gt;
                print(msg);&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
process server_[i=1 to N - 1] {&lt;br /&gt;
        while (true) {&lt;br /&gt;
                &amp;lt;msg, sender&amp;gt; = arecv(ANY);&lt;br /&gt;
                if (sender == 0) {&lt;br /&gt;
                        print(msg);&lt;br /&gt;
                        asend(ACK, server[0]);&lt;br /&gt;
                } else {&lt;br /&gt;
                        asend(&amp;lt;msg, i&amp;gt;, server[0]);&lt;br /&gt;
                }&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Esame 17/07/2017 ==&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2017.07.17.tot.pdf 2017.07.17.tot.pdf]&lt;br /&gt;
=== Esercizio c.1 ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
monitor conf {&lt;br /&gt;
        condition finished;&lt;br /&gt;
        condition ready2present[max];&lt;br /&gt;
        bool arrived[max] = false;&lt;br /&gt;
        bool giachiamato[max] = false;&lt;br /&gt;
&lt;br /&gt;
        entry chiama(chiamato){&lt;br /&gt;
        if(arrived[chiamato] == true)&lt;br /&gt;
                ready2present[chiamato].signal;&lt;br /&gt;
                finished.wait;&lt;br /&gt;
                return true;&lt;br /&gt;
        else&lt;br /&gt;
                giachiamato[chiamato]= true&lt;br /&gt;
                return false;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        entry arrivato(nome){&lt;br /&gt;
                if(giachiamato[nome] == true)&lt;br /&gt;
                        return  false;&lt;br /&gt;
&lt;br /&gt;
                arrived[nome] = true;&lt;br /&gt;
                ok2present[nome].wait;&lt;br /&gt;
                return true;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        entry finepresentazione(nome){&lt;br /&gt;
                finished.signal;&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.2 (da controllare) ===&lt;br /&gt;
controllata da [[User:LiberaL|LiberaL]] 14:26, 26 May 2023 (CEST) l'implementazione fornita gestisce solo il caso di arecv(ANY) e non arecv(mittente)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
si, è possibile: &lt;br /&gt;
&lt;br /&gt;
Implementare asend e arecv date bsend e brecv&lt;br /&gt;
&lt;br /&gt;
asend(pid_t dst, msg_type msg){&lt;br /&gt;
    bsend (&amp;lt;dst, msg&amp;gt;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
arecv(*){&lt;br /&gt;
  do {&lt;br /&gt;
    &amp;lt;dst, msg&amp;gt; = brecv(*);&lt;br /&gt;
  } while (dst != getpid())&lt;br /&gt;
  return msg;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
propongo ([[User:LiberaL|LiberaL]] 05:50, 29 May 2023 (CEST)) quindi questa implementazione con gestione arecv da mittente specificato (sempre da controllare)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
//il messaggio mandato è la tripla &amp;lt;destinatario, mittente, messaggio&amp;gt;&lt;br /&gt;
&lt;br /&gt;
asend(pid_t dst, msg_type msg){&lt;br /&gt;
    bsend (&amp;lt;dst, getpid(), msg&amp;gt;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Queue of &amp;lt;pid_t, msg_type&amp;gt; db; //nota: salvo qui solo se il messaggio è per me, quindi dest non mi serve&lt;br /&gt;
&lt;br /&gt;
arecv(pid_t sender) {&lt;br /&gt;
&lt;br /&gt;
  //devo controllare se nella coda ho già ricevuto il messaggio da quel mittente, ovvero mentre aspettavo un messaggio da qualcun'altro&lt;br /&gt;
  //db.get(sender) cerca una tripla il cui mittente è sender&lt;br /&gt;
  //se trova il messaggio lo rimuove anche dal db.&lt;br /&gt;
  //db.get(ANY) ritorna (ed elimina da db) il primo che trova (FIFO), e if(db.isEmpty()) return NULL;&lt;br /&gt;
  if( ( &amp;lt;mit, msg&amp;gt; = db.get(sender) ) != NULL ) //se lo trova&lt;br /&gt;
    return msg;&lt;br /&gt;
&lt;br /&gt;
  do {&lt;br /&gt;
    &amp;lt;dst, mit, msg&amp;gt; = brecv(*);                 //ricevo&lt;br /&gt;
    if( dst == getpid() ) {                     //il messaggio è per me?&lt;br /&gt;
      if ( mit == sender || sender == ANY )     //se devo ritornare il messaggio&lt;br /&gt;
        break;     //esci dal while&lt;br /&gt;
      else {                                    //se devo salvarlo (sender specificato e messaggio per me)&lt;br /&gt;
        //devo mettere in db i messaggi di altri mittenti, ricevuti quando ne aspettavo uno da un mittente specificato&lt;br /&gt;
        db.add(&amp;lt;mit, msg&amp;gt;);&lt;br /&gt;
        //devo anche continuare a ricevere altri messaggi&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
  } while ( true ) //devo uscire solo con il break&lt;br /&gt;
&lt;br /&gt;
  return msg;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Esame 19/06/2017 ==&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2017.06.19.tot.pdf 2017.06.19.tot.pdf]&lt;br /&gt;
=== Esercizio c.1 (da controllare)===&lt;br /&gt;
&lt;br /&gt;
* Mi sembra che ci sia un errore per il giodice, potrebbe succedere in un caso che il wait non si risvegli mai [[User:Flecart|Flecart]] ([[User talk:Flecart|talk]]) 15:38, 19 January 2023 (CET)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define NATLETI n&lt;br /&gt;
&lt;br /&gt;
condition ok2lancia[NATLETI];&lt;br /&gt;
condition ok2giudice;&lt;br /&gt;
&lt;br /&gt;
int counter[NATLETI];&lt;br /&gt;
int ultimo_tiro;&lt;br /&gt;
float registro[NATLETI][3];&lt;br /&gt;
&lt;br /&gt;
Procedure entry: boolean pronto(int i)&lt;br /&gt;
{&lt;br /&gt;
    if(!(i == 0 &amp;amp;&amp;amp; counter[i] == 0)) // se è il primo lancio non devo metterlo in wait&lt;br /&gt;
        ok2lancia[i].wait()&lt;br /&gt;
    if(counter[i] &amp;lt; 3)&lt;br /&gt;
        return true;&lt;br /&gt;
    else&lt;br /&gt;
        return false;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: void lanciato (int i)&lt;br /&gt;
{&lt;br /&gt;
    counter[i]++;&lt;br /&gt;
    ultimo_tiro = i;&lt;br /&gt;
    ok2giudice.signal();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: int lanciofatto()&lt;br /&gt;
{&lt;br /&gt;
    ok2giudice.wait()&lt;br /&gt;
    if(ultimo_tiro == NATLETI-1 &amp;amp;&amp;amp; counter[0] == 3)&lt;br /&gt;
        return -1;  // devo invalidare la condizione per uscire dal while, quindi se nessuno deve più lanciare ritorno -1&lt;br /&gt;
    else&lt;br /&gt;
        return ultimo_tiro;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: void registraechiama(int i, float m)&lt;br /&gt;
{&lt;br /&gt;
    registro[i][counter[i]-1] = m; // il secondo indice indica l'iesimo lancio -1 (perchè iniziamo a contare da zero)&lt;br /&gt;
    if(i == NATLETI-1) // se ha appena tirato l'ultimo atleta non posso dare il via a NATLETI (perchè non esiste), quindi faccio ricominciare il giro&lt;br /&gt;
        ok2lancia[0].signal();&lt;br /&gt;
    else&lt;br /&gt;
        ok2lancia[i+1].signal();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: int classifica()&lt;br /&gt;
{&lt;br /&gt;
    int best[NATLETI];&lt;br /&gt;
    for(int i = 0; i &amp;lt; NATLETI; i++)&lt;br /&gt;
    {&lt;br /&gt;
        for(int j = 0; j &amp;lt; 3; j++)&lt;br /&gt;
        {&lt;br /&gt;
            if(registro[i][j] &amp;gt; best[i])&lt;br /&gt;
                best[i] = registro[i][j];&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    best.sort_in_descending_order(); // supponiamo nel nostro pseudolinguaggio esista una funzione di ordinamento qualunque&lt;br /&gt;
    return best;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Esame 29/05/2017 ==&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2017.05.29.tot.pdf 2017.05.29.tot.pdf]&lt;br /&gt;
=== Esercizio c.1 ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
condition okpartita&lt;br /&gt;
condition ok2chiama&lt;br /&gt;
condition ok2punteggio&lt;br /&gt;
condition ok2run[2][MAX]&lt;br /&gt;
int numpronti&lt;br /&gt;
int punteggio[2]&lt;br /&gt;
boolean partita=false&lt;br /&gt;
boolean partitafinita=false&lt;br /&gt;
chiamati = []&lt;br /&gt;
contabandiera[2]&lt;br /&gt;
int winner&lt;br /&gt;
&lt;br /&gt;
entry nuovapartita():&lt;br /&gt;
{&lt;br /&gt;
    punteggio[A] = punteggio[B] = 0;&lt;br /&gt;
    numpronti = 0;&lt;br /&gt;
    partita=true;&lt;br /&gt;
    okpartita.signal()&lt;br /&gt;
    chiamati = [];&lt;br /&gt;
}&lt;br /&gt;
entry chiama(l):&lt;br /&gt;
{&lt;br /&gt;
    if (numpronti&amp;lt;2*MAX)&lt;br /&gt;
    {&lt;br /&gt;
        ok2chiama.wait();&lt;br /&gt;
    }&lt;br /&gt;
    chiamati = l;&lt;br /&gt;
    contabandiera[A] = contabandiera[B] = 0&lt;br /&gt;
    winner = -1;&lt;br /&gt;
    for (s in n)&lt;br /&gt;
    {&lt;br /&gt;
        ok2run[A][s].signal();&lt;br /&gt;
        ok2run[B][s].signal()&lt;br /&gt;
    }&lt;br /&gt;
    ok2punteggio.wait();&lt;br /&gt;
    punteggio[winner++]&lt;br /&gt;
    if (max(punteggio) == 10)&lt;br /&gt;
    {&lt;br /&gt;
        partitafinita = true;&lt;br /&gt;
        for (s in A,B)&lt;br /&gt;
        {&lt;br /&gt;
            for (n in range(MAX))&lt;br /&gt;
            {&lt;br /&gt;
                ok2run[s][n].signal();&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    return punteggio;&lt;br /&gt;
}&lt;br /&gt;
entry pronto(s, n):&lt;br /&gt;
{&lt;br /&gt;
    if (partitafinita) return 1;&lt;br /&gt;
    if (!partita)&lt;br /&gt;
    {&lt;br /&gt;
        okpartita.wait();&lt;br /&gt;
    }&lt;br /&gt;
    numpronti++;&lt;br /&gt;
    if (numpronti&amp;gt;=2*MAX)&lt;br /&gt;
    {&lt;br /&gt;
        ok2chiama.signal();&lt;br /&gt;
    }&lt;br /&gt;
    if (!(n in chiamati))&lt;br /&gt;
    {&lt;br /&gt;
        ok2run[s][n].wait();&lt;br /&gt;
    }&lt;br /&gt;
    numpronti--;&lt;br /&gt;
    return 0 if partita else 1;&lt;br /&gt;
}&lt;br /&gt;
allabandiera(s, n):&lt;br /&gt;
{&lt;br /&gt;
    contabandiera[s]++;&lt;br /&gt;
    if (winner == -1 &amp;amp;&amp;amp; contabandiera[s] == len(chiamati))&lt;br /&gt;
    {&lt;br /&gt;
        winner = s;&lt;br /&gt;
    }&lt;br /&gt;
    if (contabandiera[A] == len(chiamati) &amp;amp;&amp;amp; contabandiera[B] == len(chiamati))&lt;br /&gt;
    {&lt;br /&gt;
        ok2punteggio.signal();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
casi da discutere:    &lt;br /&gt;
se arrivano studenti a pronto prima che il prof dichiara nuovapartita succedono guai.&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>LiberaL</name></author>
	</entry>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=Prove_scritte_2017&amp;diff=3032</id>
		<title>Prove scritte 2017</title>
		<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php?title=Prove_scritte_2017&amp;diff=3032"/>
		<updated>2023-05-29T03:38:02Z</updated>

		<summary type="html">&lt;p&gt;LiberaL: /*continuo a ricevere se ho salvato il messaggio in db*/&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Esame 11/09/2017 ==&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2017.09.11.tot.pdf 2017.09.11.tot.pdf]&lt;br /&gt;
=== Esercizio c.1 ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
monitor crossing&lt;br /&gt;
&lt;br /&gt;
ok2dir[4];     //NESW&lt;br /&gt;
bool busy = false;&lt;br /&gt;
&lt;br /&gt;
pe entra(int dir)&lt;br /&gt;
   if (busy)&lt;br /&gt;
      ok2dir[dir].wait();&lt;br /&gt;
   busy = true;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
pe esci(int dir)&lt;br /&gt;
   busy = false;&lt;br /&gt;
   ok2dir[(dir + 1) % 4].signal();&lt;br /&gt;
   if (!busy)&lt;br /&gt;
      ok2dir[(dir + 2) % 4].signal();&lt;br /&gt;
   if (!busy)&lt;br /&gt;
      ok2dir[(dir + 3) % 4].signal();&lt;br /&gt;
   if (!busy)&lt;br /&gt;
      ok2dir[(dir + 4) % 4].signal();  //dir&lt;br /&gt;
&lt;br /&gt;
//alternativa più compatta&lt;br /&gt;
pe esci(int dir)&lt;br /&gt;
   busy = false;&lt;br /&gt;
   for (i = 0; i &amp;lt; 4; i++)&lt;br /&gt;
   if (!busy)&lt;br /&gt;
      ok2dir[(dir + i + 1) % 4].signal();&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Soluzione proposta 2 ==== &lt;br /&gt;
Soluzione proposta da [https://t.me/LLibera LLibera] e corretta da  [https://so.v2.cs.unibo.it/wiki/index.php/User:Flecart Flecart]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
const int N_DIRECTION = 4;&lt;br /&gt;
&lt;br /&gt;
// assumo N = 0, E = 1, S = 2, W = 3, oppure shiftati ciclicamente, è equivalente&lt;br /&gt;
&lt;br /&gt;
monitor crossing {&lt;br /&gt;
	bool free;										//l'incrocio è libero?&lt;br /&gt;
	int num_waiting[N_DIRECTION];&lt;br /&gt;
	condition okToCross[N_DIRECTION];				//free == True&lt;br /&gt;
	&lt;br /&gt;
	crossing() {&lt;br /&gt;
		free = True;								//parto con l'incrocio libero&lt;br /&gt;
		for (int i = 0; i &amp;lt; N_DIRECTION; i++) {&lt;br /&gt;
			num_waiting[i] = 0;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	procedure entry enter(int direction) {&lt;br /&gt;
		if(!free) {									//se l'incrocio non è libero&lt;br /&gt;
			num_waiting[direction]++;&lt;br /&gt;
			okToCross[direction].wait();			//aspetto nella mia direzione&lt;br /&gt;
			num_waiting[direction]--;&lt;br /&gt;
		}&lt;br /&gt;
													//ora sono sicurə che sia libero&lt;br /&gt;
		free = False;								//quindi lo dichiaro occupato&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	procedure entry exit(int direction) {&lt;br /&gt;
													//non devo aspettare niente per liberare l'incrocio&lt;br /&gt;
		free = True;								//lo dichiaro libero&lt;br /&gt;
		&lt;br /&gt;
		for (int i = 0; i &amp;lt; N_DIRECTION; i++) {&lt;br /&gt;
			int curr_dir = (direction + i + 1) % N_DIRECTION;&lt;br /&gt;
			if (num_waiting[curr_dir] &amp;gt; 0) {&lt;br /&gt;
				okToCross[curr_dir].signal();&lt;br /&gt;
				break;	// l'onere di risvegliare gli altri è stato passato al nuovo processo risvegliato, quindi esco.&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.2 (da controllare) ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// server[] = array contenente il PID di tutti i server&lt;br /&gt;
&lt;br /&gt;
#define BROADCAST server[0]&lt;br /&gt;
&lt;br /&gt;
server[0]&lt;br /&gt;
{&lt;br /&gt;
    while(true)&lt;br /&gt;
    {&lt;br /&gt;
        &amp;lt;msg, sender&amp;gt; = arecv(*); // ricevo il messaggio&lt;br /&gt;
        if (sender == BROADCAST)&lt;br /&gt;
            print(msg); // se il messaggio l'ho ricevuto da me stesso allora lo stampo&lt;br /&gt;
        else&lt;br /&gt;
            asend(*, &amp;lt;msg, getpid()&amp;gt;); // se il messaggio l'ho ricevuto da un client o da un altro server lo inoltro a tutti i server (compreso me stesso)&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
server[x] // x = 1...N-1&lt;br /&gt;
{&lt;br /&gt;
    while(true)&lt;br /&gt;
    {&lt;br /&gt;
        &amp;lt;msg, sender&amp;gt; = arecv(*); // ricevo il messaggio&lt;br /&gt;
        if (sender == BROADCAST)&lt;br /&gt;
            print(msg); // se il messaggio l'ho ricevuto dal server[0] allora lo stampo&lt;br /&gt;
        else&lt;br /&gt;
            asend(BROADCAST, &amp;lt;msg, getpid()&amp;gt;) // se il messaggio l'ho ricevuto da un client lo inoltro al server[0]&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Soluzione proposta 2 ====&lt;br /&gt;
&lt;br /&gt;
Soluzione proposta da [https://so.v2.cs.unibo.it/wiki/index.php/User:Flecart Flecart]&lt;br /&gt;
Soluzione corretta da [https://so.v2.cs.unibo.it/wiki/index.php/User:Gio Flecart friend]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
process server_0 {&lt;br /&gt;
&lt;br /&gt;
        while (true) {&lt;br /&gt;
                &amp;lt;msg, sender&amp;gt; = arecv(ANY);&lt;br /&gt;
                for (int i = 1 ; i &amp;lt; N; i++) {&lt;br /&gt;
                        asend(&amp;lt;msg, 0&amp;gt;, server[i]);&lt;br /&gt;
                        while(true){&lt;br /&gt;
                          msg = arecv(server[i]); // così so che tutti abbiano stampato.&lt;br /&gt;
                          if(msg==ACK)&lt;br /&gt;
                            break&lt;br /&gt;
                          asend(msg,server[0]);&lt;br /&gt;
                        }&lt;br /&gt;
                }&lt;br /&gt;
                print(msg);&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
process server_[i=1 to N - 1] {&lt;br /&gt;
        while (true) {&lt;br /&gt;
                &amp;lt;msg, sender&amp;gt; = arecv(ANY);&lt;br /&gt;
                if (sender == 0) {&lt;br /&gt;
                        print(msg);&lt;br /&gt;
                        asend(ACK, server[0]);&lt;br /&gt;
                } else {&lt;br /&gt;
                        asend(&amp;lt;msg, i&amp;gt;, server[0]);&lt;br /&gt;
                }&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Esame 17/07/2017 ==&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2017.07.17.tot.pdf 2017.07.17.tot.pdf]&lt;br /&gt;
=== Esercizio c.1 ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
monitor conf {&lt;br /&gt;
        condition finished;&lt;br /&gt;
        condition ready2present[max];&lt;br /&gt;
        bool arrived[max] = false;&lt;br /&gt;
        bool giachiamato[max] = false;&lt;br /&gt;
&lt;br /&gt;
        entry chiama(chiamato){&lt;br /&gt;
        if(arrived[chiamato] == true)&lt;br /&gt;
                ready2present[chiamato].signal;&lt;br /&gt;
                finished.wait;&lt;br /&gt;
                return true;&lt;br /&gt;
        else&lt;br /&gt;
                giachiamato[chiamato]= true&lt;br /&gt;
                return false;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        entry arrivato(nome){&lt;br /&gt;
                if(giachiamato[nome] == true)&lt;br /&gt;
                        return  false;&lt;br /&gt;
&lt;br /&gt;
                arrived[nome] = true;&lt;br /&gt;
                ok2present[nome].wait;&lt;br /&gt;
                return true;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        entry finepresentazione(nome){&lt;br /&gt;
                finished.signal;&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.2 (da controllare) ===&lt;br /&gt;
controllata da [[User:LiberaL|LiberaL]] 14:26, 26 May 2023 (CEST) l'implementazione fornita gestisce solo il caso di arecv(ANY) e non arecv(mittente)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
si, è possibile: &lt;br /&gt;
&lt;br /&gt;
Implementare asend e arecv date bsend e brecv&lt;br /&gt;
&lt;br /&gt;
asend(pid_t dst, msg_type msg){&lt;br /&gt;
    bsend (&amp;lt;dst, msg&amp;gt;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
arecv(*){&lt;br /&gt;
  do {&lt;br /&gt;
    &amp;lt;dst, msg&amp;gt; = brecv(*);&lt;br /&gt;
  } while (dst != getpid())&lt;br /&gt;
  return msg;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
propongo ([[User:LiberaL|LiberaL]] 05:36, 29 May 2023 (CEST)) quindi questa implementazione con gestione arecv da mittente specificato (sempre da controllare)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
//il messaggio mandato è la tripla &amp;lt;destinatario, mittente, messaggio&amp;gt;&lt;br /&gt;
&lt;br /&gt;
asend(pid_t dst, msg_type msg){&lt;br /&gt;
    bsend (&amp;lt;dst, getpid(), msg&amp;gt;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Queue of &amp;lt;pid_t, msg_type&amp;gt; db; //nota: salvo qui solo se il messaggio è per me, quindi dest non mi serve&lt;br /&gt;
&lt;br /&gt;
arecv(pid_t sender) {&lt;br /&gt;
&lt;br /&gt;
  //devo controllare se nella coda ho già ricevuto il messaggio da quel mittente, ovvero mentre aspettavo un messaggio da qualcun'altro&lt;br /&gt;
  //db.get(sender) cerca una tripla il cui mittente è sender&lt;br /&gt;
  //se trova il messaggio lo rimuove anche dal db.&lt;br /&gt;
  //db.get(ANY) ritorna (ed elimina da db) il primo che trova (FIFO), e if(db.isEmpty()) return NULL;&lt;br /&gt;
  if( ( &amp;lt;mit, msg&amp;gt; = db.get(sender) ) != NULL ) //se lo trova&lt;br /&gt;
    return msg;&lt;br /&gt;
&lt;br /&gt;
  bool message_for_me, continue_save = false;&lt;br /&gt;
  do {&lt;br /&gt;
    &amp;lt;dst, mit, msg&amp;gt; = brecv(*);                 //ricevo&lt;br /&gt;
    message_for_me = (dst == getpid());         //il messaggio è per me?&lt;br /&gt;
    if( message_for_me ) {&lt;br /&gt;
      if ( mit == sender || sender == ANY )     //se devo ritornare il messaggio&lt;br /&gt;
        break;     //esci dal while&lt;br /&gt;
      else {                                    //se devo salvarlo (sender specificato e messaggio per me)&lt;br /&gt;
        //devo mettere in db i messaggi di altri mittenti, ricevuti quando ne aspettavo uno da un mittente specificato&lt;br /&gt;
        db.add(&amp;lt;mit, msg&amp;gt;);&lt;br /&gt;
        continue_save = true; //devo anche continuare a ricevere altri messaggi&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
  } while ( !message_for_me || continue_save )&lt;br /&gt;
&lt;br /&gt;
  return msg;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Esame 19/06/2017 ==&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2017.06.19.tot.pdf 2017.06.19.tot.pdf]&lt;br /&gt;
=== Esercizio c.1 (da controllare)===&lt;br /&gt;
&lt;br /&gt;
* Mi sembra che ci sia un errore per il giodice, potrebbe succedere in un caso che il wait non si risvegli mai [[User:Flecart|Flecart]] ([[User talk:Flecart|talk]]) 15:38, 19 January 2023 (CET)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define NATLETI n&lt;br /&gt;
&lt;br /&gt;
condition ok2lancia[NATLETI];&lt;br /&gt;
condition ok2giudice;&lt;br /&gt;
&lt;br /&gt;
int counter[NATLETI];&lt;br /&gt;
int ultimo_tiro;&lt;br /&gt;
float registro[NATLETI][3];&lt;br /&gt;
&lt;br /&gt;
Procedure entry: boolean pronto(int i)&lt;br /&gt;
{&lt;br /&gt;
    if(!(i == 0 &amp;amp;&amp;amp; counter[i] == 0)) // se è il primo lancio non devo metterlo in wait&lt;br /&gt;
        ok2lancia[i].wait()&lt;br /&gt;
    if(counter[i] &amp;lt; 3)&lt;br /&gt;
        return true;&lt;br /&gt;
    else&lt;br /&gt;
        return false;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: void lanciato (int i)&lt;br /&gt;
{&lt;br /&gt;
    counter[i]++;&lt;br /&gt;
    ultimo_tiro = i;&lt;br /&gt;
    ok2giudice.signal();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: int lanciofatto()&lt;br /&gt;
{&lt;br /&gt;
    ok2giudice.wait()&lt;br /&gt;
    if(ultimo_tiro == NATLETI-1 &amp;amp;&amp;amp; counter[0] == 3)&lt;br /&gt;
        return -1;  // devo invalidare la condizione per uscire dal while, quindi se nessuno deve più lanciare ritorno -1&lt;br /&gt;
    else&lt;br /&gt;
        return ultimo_tiro;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: void registraechiama(int i, float m)&lt;br /&gt;
{&lt;br /&gt;
    registro[i][counter[i]-1] = m; // il secondo indice indica l'iesimo lancio -1 (perchè iniziamo a contare da zero)&lt;br /&gt;
    if(i == NATLETI-1) // se ha appena tirato l'ultimo atleta non posso dare il via a NATLETI (perchè non esiste), quindi faccio ricominciare il giro&lt;br /&gt;
        ok2lancia[0].signal();&lt;br /&gt;
    else&lt;br /&gt;
        ok2lancia[i+1].signal();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: int classifica()&lt;br /&gt;
{&lt;br /&gt;
    int best[NATLETI];&lt;br /&gt;
    for(int i = 0; i &amp;lt; NATLETI; i++)&lt;br /&gt;
    {&lt;br /&gt;
        for(int j = 0; j &amp;lt; 3; j++)&lt;br /&gt;
        {&lt;br /&gt;
            if(registro[i][j] &amp;gt; best[i])&lt;br /&gt;
                best[i] = registro[i][j];&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    best.sort_in_descending_order(); // supponiamo nel nostro pseudolinguaggio esista una funzione di ordinamento qualunque&lt;br /&gt;
    return best;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Esame 29/05/2017 ==&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2017.05.29.tot.pdf 2017.05.29.tot.pdf]&lt;br /&gt;
=== Esercizio c.1 ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
condition okpartita&lt;br /&gt;
condition ok2chiama&lt;br /&gt;
condition ok2punteggio&lt;br /&gt;
condition ok2run[2][MAX]&lt;br /&gt;
int numpronti&lt;br /&gt;
int punteggio[2]&lt;br /&gt;
boolean partita=false&lt;br /&gt;
boolean partitafinita=false&lt;br /&gt;
chiamati = []&lt;br /&gt;
contabandiera[2]&lt;br /&gt;
int winner&lt;br /&gt;
&lt;br /&gt;
entry nuovapartita():&lt;br /&gt;
{&lt;br /&gt;
    punteggio[A] = punteggio[B] = 0;&lt;br /&gt;
    numpronti = 0;&lt;br /&gt;
    partita=true;&lt;br /&gt;
    okpartita.signal()&lt;br /&gt;
    chiamati = [];&lt;br /&gt;
}&lt;br /&gt;
entry chiama(l):&lt;br /&gt;
{&lt;br /&gt;
    if (numpronti&amp;lt;2*MAX)&lt;br /&gt;
    {&lt;br /&gt;
        ok2chiama.wait();&lt;br /&gt;
    }&lt;br /&gt;
    chiamati = l;&lt;br /&gt;
    contabandiera[A] = contabandiera[B] = 0&lt;br /&gt;
    winner = -1;&lt;br /&gt;
    for (s in n)&lt;br /&gt;
    {&lt;br /&gt;
        ok2run[A][s].signal();&lt;br /&gt;
        ok2run[B][s].signal()&lt;br /&gt;
    }&lt;br /&gt;
    ok2punteggio.wait();&lt;br /&gt;
    punteggio[winner++]&lt;br /&gt;
    if (max(punteggio) == 10)&lt;br /&gt;
    {&lt;br /&gt;
        partitafinita = true;&lt;br /&gt;
        for (s in A,B)&lt;br /&gt;
        {&lt;br /&gt;
            for (n in range(MAX))&lt;br /&gt;
            {&lt;br /&gt;
                ok2run[s][n].signal();&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    return punteggio;&lt;br /&gt;
}&lt;br /&gt;
entry pronto(s, n):&lt;br /&gt;
{&lt;br /&gt;
    if (partitafinita) return 1;&lt;br /&gt;
    if (!partita)&lt;br /&gt;
    {&lt;br /&gt;
        okpartita.wait();&lt;br /&gt;
    }&lt;br /&gt;
    numpronti++;&lt;br /&gt;
    if (numpronti&amp;gt;=2*MAX)&lt;br /&gt;
    {&lt;br /&gt;
        ok2chiama.signal();&lt;br /&gt;
    }&lt;br /&gt;
    if (!(n in chiamati))&lt;br /&gt;
    {&lt;br /&gt;
        ok2run[s][n].wait();&lt;br /&gt;
    }&lt;br /&gt;
    numpronti--;&lt;br /&gt;
    return 0 if partita else 1;&lt;br /&gt;
}&lt;br /&gt;
allabandiera(s, n):&lt;br /&gt;
{&lt;br /&gt;
    contabandiera[s]++;&lt;br /&gt;
    if (winner == -1 &amp;amp;&amp;amp; contabandiera[s] == len(chiamati))&lt;br /&gt;
    {&lt;br /&gt;
        winner = s;&lt;br /&gt;
    }&lt;br /&gt;
    if (contabandiera[A] == len(chiamati) &amp;amp;&amp;amp; contabandiera[B] == len(chiamati))&lt;br /&gt;
    {&lt;br /&gt;
        ok2punteggio.signal();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
casi da discutere:    &lt;br /&gt;
se arrivano studenti a pronto prima che il prof dichiara nuovapartita succedono guai.&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>LiberaL</name></author>
	</entry>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=Prove_scritte_2017&amp;diff=3031</id>
		<title>Prove scritte 2017</title>
		<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php?title=Prove_scritte_2017&amp;diff=3031"/>
		<updated>2023-05-29T03:36:50Z</updated>

		<summary type="html">&lt;p&gt;LiberaL: /*continuo a ricevere se ho salvato il messaggio in db*/&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Esame 11/09/2017 ==&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2017.09.11.tot.pdf 2017.09.11.tot.pdf]&lt;br /&gt;
=== Esercizio c.1 ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
monitor crossing&lt;br /&gt;
&lt;br /&gt;
ok2dir[4];     //NESW&lt;br /&gt;
bool busy = false;&lt;br /&gt;
&lt;br /&gt;
pe entra(int dir)&lt;br /&gt;
   if (busy)&lt;br /&gt;
      ok2dir[dir].wait();&lt;br /&gt;
   busy = true;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
pe esci(int dir)&lt;br /&gt;
   busy = false;&lt;br /&gt;
   ok2dir[(dir + 1) % 4].signal();&lt;br /&gt;
   if (!busy)&lt;br /&gt;
      ok2dir[(dir + 2) % 4].signal();&lt;br /&gt;
   if (!busy)&lt;br /&gt;
      ok2dir[(dir + 3) % 4].signal();&lt;br /&gt;
   if (!busy)&lt;br /&gt;
      ok2dir[(dir + 4) % 4].signal();  //dir&lt;br /&gt;
&lt;br /&gt;
//alternativa più compatta&lt;br /&gt;
pe esci(int dir)&lt;br /&gt;
   busy = false;&lt;br /&gt;
   for (i = 0; i &amp;lt; 4; i++)&lt;br /&gt;
   if (!busy)&lt;br /&gt;
      ok2dir[(dir + i + 1) % 4].signal();&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Soluzione proposta 2 ==== &lt;br /&gt;
Soluzione proposta da [https://t.me/LLibera LLibera] e corretta da  [https://so.v2.cs.unibo.it/wiki/index.php/User:Flecart Flecart]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
const int N_DIRECTION = 4;&lt;br /&gt;
&lt;br /&gt;
// assumo N = 0, E = 1, S = 2, W = 3, oppure shiftati ciclicamente, è equivalente&lt;br /&gt;
&lt;br /&gt;
monitor crossing {&lt;br /&gt;
	bool free;										//l'incrocio è libero?&lt;br /&gt;
	int num_waiting[N_DIRECTION];&lt;br /&gt;
	condition okToCross[N_DIRECTION];				//free == True&lt;br /&gt;
	&lt;br /&gt;
	crossing() {&lt;br /&gt;
		free = True;								//parto con l'incrocio libero&lt;br /&gt;
		for (int i = 0; i &amp;lt; N_DIRECTION; i++) {&lt;br /&gt;
			num_waiting[i] = 0;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	procedure entry enter(int direction) {&lt;br /&gt;
		if(!free) {									//se l'incrocio non è libero&lt;br /&gt;
			num_waiting[direction]++;&lt;br /&gt;
			okToCross[direction].wait();			//aspetto nella mia direzione&lt;br /&gt;
			num_waiting[direction]--;&lt;br /&gt;
		}&lt;br /&gt;
													//ora sono sicurə che sia libero&lt;br /&gt;
		free = False;								//quindi lo dichiaro occupato&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	procedure entry exit(int direction) {&lt;br /&gt;
													//non devo aspettare niente per liberare l'incrocio&lt;br /&gt;
		free = True;								//lo dichiaro libero&lt;br /&gt;
		&lt;br /&gt;
		for (int i = 0; i &amp;lt; N_DIRECTION; i++) {&lt;br /&gt;
			int curr_dir = (direction + i + 1) % N_DIRECTION;&lt;br /&gt;
			if (num_waiting[curr_dir] &amp;gt; 0) {&lt;br /&gt;
				okToCross[curr_dir].signal();&lt;br /&gt;
				break;	// l'onere di risvegliare gli altri è stato passato al nuovo processo risvegliato, quindi esco.&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.2 (da controllare) ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// server[] = array contenente il PID di tutti i server&lt;br /&gt;
&lt;br /&gt;
#define BROADCAST server[0]&lt;br /&gt;
&lt;br /&gt;
server[0]&lt;br /&gt;
{&lt;br /&gt;
    while(true)&lt;br /&gt;
    {&lt;br /&gt;
        &amp;lt;msg, sender&amp;gt; = arecv(*); // ricevo il messaggio&lt;br /&gt;
        if (sender == BROADCAST)&lt;br /&gt;
            print(msg); // se il messaggio l'ho ricevuto da me stesso allora lo stampo&lt;br /&gt;
        else&lt;br /&gt;
            asend(*, &amp;lt;msg, getpid()&amp;gt;); // se il messaggio l'ho ricevuto da un client o da un altro server lo inoltro a tutti i server (compreso me stesso)&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
server[x] // x = 1...N-1&lt;br /&gt;
{&lt;br /&gt;
    while(true)&lt;br /&gt;
    {&lt;br /&gt;
        &amp;lt;msg, sender&amp;gt; = arecv(*); // ricevo il messaggio&lt;br /&gt;
        if (sender == BROADCAST)&lt;br /&gt;
            print(msg); // se il messaggio l'ho ricevuto dal server[0] allora lo stampo&lt;br /&gt;
        else&lt;br /&gt;
            asend(BROADCAST, &amp;lt;msg, getpid()&amp;gt;) // se il messaggio l'ho ricevuto da un client lo inoltro al server[0]&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Soluzione proposta 2 ====&lt;br /&gt;
&lt;br /&gt;
Soluzione proposta da [https://so.v2.cs.unibo.it/wiki/index.php/User:Flecart Flecart]&lt;br /&gt;
Soluzione corretta da [https://so.v2.cs.unibo.it/wiki/index.php/User:Gio Flecart friend]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
process server_0 {&lt;br /&gt;
&lt;br /&gt;
        while (true) {&lt;br /&gt;
                &amp;lt;msg, sender&amp;gt; = arecv(ANY);&lt;br /&gt;
                for (int i = 1 ; i &amp;lt; N; i++) {&lt;br /&gt;
                        asend(&amp;lt;msg, 0&amp;gt;, server[i]);&lt;br /&gt;
                        while(true){&lt;br /&gt;
                          msg = arecv(server[i]); // così so che tutti abbiano stampato.&lt;br /&gt;
                          if(msg==ACK)&lt;br /&gt;
                            break&lt;br /&gt;
                          asend(msg,server[0]);&lt;br /&gt;
                        }&lt;br /&gt;
                }&lt;br /&gt;
                print(msg);&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
process server_[i=1 to N - 1] {&lt;br /&gt;
        while (true) {&lt;br /&gt;
                &amp;lt;msg, sender&amp;gt; = arecv(ANY);&lt;br /&gt;
                if (sender == 0) {&lt;br /&gt;
                        print(msg);&lt;br /&gt;
                        asend(ACK, server[0]);&lt;br /&gt;
                } else {&lt;br /&gt;
                        asend(&amp;lt;msg, i&amp;gt;, server[0]);&lt;br /&gt;
                }&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Esame 17/07/2017 ==&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2017.07.17.tot.pdf 2017.07.17.tot.pdf]&lt;br /&gt;
=== Esercizio c.1 ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
monitor conf {&lt;br /&gt;
        condition finished;&lt;br /&gt;
        condition ready2present[max];&lt;br /&gt;
        bool arrived[max] = false;&lt;br /&gt;
        bool giachiamato[max] = false;&lt;br /&gt;
&lt;br /&gt;
        entry chiama(chiamato){&lt;br /&gt;
        if(arrived[chiamato] == true)&lt;br /&gt;
                ready2present[chiamato].signal;&lt;br /&gt;
                finished.wait;&lt;br /&gt;
                return true;&lt;br /&gt;
        else&lt;br /&gt;
                giachiamato[chiamato]= true&lt;br /&gt;
                return false;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        entry arrivato(nome){&lt;br /&gt;
                if(giachiamato[nome] == true)&lt;br /&gt;
                        return  false;&lt;br /&gt;
&lt;br /&gt;
                arrived[nome] = true;&lt;br /&gt;
                ok2present[nome].wait;&lt;br /&gt;
                return true;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        entry finepresentazione(nome){&lt;br /&gt;
                finished.signal;&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.2 (da controllare) ===&lt;br /&gt;
controllata da [[User:LiberaL|LiberaL]] 14:26, 26 May 2023 (CEST) l'implementazione fornita gestisce solo il caso di arecv(ANY) e non arecv(mittente)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
si, è possibile: &lt;br /&gt;
&lt;br /&gt;
Implementare asend e arecv date bsend e brecv&lt;br /&gt;
&lt;br /&gt;
asend(pid_t dst, msg_type msg){&lt;br /&gt;
    bsend (&amp;lt;dst, msg&amp;gt;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
arecv(*){&lt;br /&gt;
  do {&lt;br /&gt;
    &amp;lt;dst, msg&amp;gt; = brecv(*);&lt;br /&gt;
  } while (dst != getpid())&lt;br /&gt;
  return msg;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
propongo ([[User:LiberaL|LiberaL]] 05:36, 29 May 2023 (CEST)) quindi questa implementazione con gestione arecv da mittente specificato (sempre da controllare)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
//il messaggio mandato è la tripla &amp;lt;destinatario, mittente, messaggio&amp;gt;&lt;br /&gt;
&lt;br /&gt;
asend(pid_t dst, msg_type msg){&lt;br /&gt;
    bsend (&amp;lt;dst, getpid(), msg&amp;gt;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Queue of &amp;lt;pid_t, msg_type&amp;gt; db; //nota: salvo qui solo se il messaggio è per me, quindi dest non mi serve&lt;br /&gt;
&lt;br /&gt;
arecv(pid_t sender) {&lt;br /&gt;
&lt;br /&gt;
  //devo controllare se nella coda ho già ricevuto il messaggio da quel mittente, ovvero mentre aspettavo un messaggio da qualcun'altro&lt;br /&gt;
  //db.get(sender) cerca una tripla il cui mittente è sender&lt;br /&gt;
  //se trova il messaggio lo rimuove anche dal db.&lt;br /&gt;
  //db.get(ANY) ritorna (ed elimina da db) il primo che trova (FIFO), e if(db.isEmpty()) return NULL;&lt;br /&gt;
  if( ( &amp;lt;mit, msg&amp;gt; = db.get(sender) ) != NULL ) //se lo trova&lt;br /&gt;
    return msg;&lt;br /&gt;
&lt;br /&gt;
  bool message_for_me, continue = false;&lt;br /&gt;
  do {&lt;br /&gt;
    &amp;lt;dst, mit, msg&amp;gt; = brecv(*);                 //ricevo&lt;br /&gt;
    message_for_me = (dst == getpid());         //il messaggio è per me?&lt;br /&gt;
    if( message_for_me ) {&lt;br /&gt;
      if ( mit == sender || sender == ANY )     //se devo ritornare il messaggio&lt;br /&gt;
        break;     //esci dal while&lt;br /&gt;
      else {                                    //se devo salvarlo (sender specificato e messaggio per me)&lt;br /&gt;
        //devo mettere in db i messaggi di altri mittenti, ricevuti quando ne aspettavo uno da un mittente specificato&lt;br /&gt;
        db.add(&amp;lt;mit, msg&amp;gt;);&lt;br /&gt;
        continue = true; //devo anche continuare a ricevere altri messaggi&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
  } while ( !message_for_me || continue )&lt;br /&gt;
&lt;br /&gt;
  return msg;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Esame 19/06/2017 ==&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2017.06.19.tot.pdf 2017.06.19.tot.pdf]&lt;br /&gt;
=== Esercizio c.1 (da controllare)===&lt;br /&gt;
&lt;br /&gt;
* Mi sembra che ci sia un errore per il giodice, potrebbe succedere in un caso che il wait non si risvegli mai [[User:Flecart|Flecart]] ([[User talk:Flecart|talk]]) 15:38, 19 January 2023 (CET)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define NATLETI n&lt;br /&gt;
&lt;br /&gt;
condition ok2lancia[NATLETI];&lt;br /&gt;
condition ok2giudice;&lt;br /&gt;
&lt;br /&gt;
int counter[NATLETI];&lt;br /&gt;
int ultimo_tiro;&lt;br /&gt;
float registro[NATLETI][3];&lt;br /&gt;
&lt;br /&gt;
Procedure entry: boolean pronto(int i)&lt;br /&gt;
{&lt;br /&gt;
    if(!(i == 0 &amp;amp;&amp;amp; counter[i] == 0)) // se è il primo lancio non devo metterlo in wait&lt;br /&gt;
        ok2lancia[i].wait()&lt;br /&gt;
    if(counter[i] &amp;lt; 3)&lt;br /&gt;
        return true;&lt;br /&gt;
    else&lt;br /&gt;
        return false;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: void lanciato (int i)&lt;br /&gt;
{&lt;br /&gt;
    counter[i]++;&lt;br /&gt;
    ultimo_tiro = i;&lt;br /&gt;
    ok2giudice.signal();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: int lanciofatto()&lt;br /&gt;
{&lt;br /&gt;
    ok2giudice.wait()&lt;br /&gt;
    if(ultimo_tiro == NATLETI-1 &amp;amp;&amp;amp; counter[0] == 3)&lt;br /&gt;
        return -1;  // devo invalidare la condizione per uscire dal while, quindi se nessuno deve più lanciare ritorno -1&lt;br /&gt;
    else&lt;br /&gt;
        return ultimo_tiro;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: void registraechiama(int i, float m)&lt;br /&gt;
{&lt;br /&gt;
    registro[i][counter[i]-1] = m; // il secondo indice indica l'iesimo lancio -1 (perchè iniziamo a contare da zero)&lt;br /&gt;
    if(i == NATLETI-1) // se ha appena tirato l'ultimo atleta non posso dare il via a NATLETI (perchè non esiste), quindi faccio ricominciare il giro&lt;br /&gt;
        ok2lancia[0].signal();&lt;br /&gt;
    else&lt;br /&gt;
        ok2lancia[i+1].signal();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: int classifica()&lt;br /&gt;
{&lt;br /&gt;
    int best[NATLETI];&lt;br /&gt;
    for(int i = 0; i &amp;lt; NATLETI; i++)&lt;br /&gt;
    {&lt;br /&gt;
        for(int j = 0; j &amp;lt; 3; j++)&lt;br /&gt;
        {&lt;br /&gt;
            if(registro[i][j] &amp;gt; best[i])&lt;br /&gt;
                best[i] = registro[i][j];&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    best.sort_in_descending_order(); // supponiamo nel nostro pseudolinguaggio esista una funzione di ordinamento qualunque&lt;br /&gt;
    return best;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Esame 29/05/2017 ==&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2017.05.29.tot.pdf 2017.05.29.tot.pdf]&lt;br /&gt;
=== Esercizio c.1 ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
condition okpartita&lt;br /&gt;
condition ok2chiama&lt;br /&gt;
condition ok2punteggio&lt;br /&gt;
condition ok2run[2][MAX]&lt;br /&gt;
int numpronti&lt;br /&gt;
int punteggio[2]&lt;br /&gt;
boolean partita=false&lt;br /&gt;
boolean partitafinita=false&lt;br /&gt;
chiamati = []&lt;br /&gt;
contabandiera[2]&lt;br /&gt;
int winner&lt;br /&gt;
&lt;br /&gt;
entry nuovapartita():&lt;br /&gt;
{&lt;br /&gt;
    punteggio[A] = punteggio[B] = 0;&lt;br /&gt;
    numpronti = 0;&lt;br /&gt;
    partita=true;&lt;br /&gt;
    okpartita.signal()&lt;br /&gt;
    chiamati = [];&lt;br /&gt;
}&lt;br /&gt;
entry chiama(l):&lt;br /&gt;
{&lt;br /&gt;
    if (numpronti&amp;lt;2*MAX)&lt;br /&gt;
    {&lt;br /&gt;
        ok2chiama.wait();&lt;br /&gt;
    }&lt;br /&gt;
    chiamati = l;&lt;br /&gt;
    contabandiera[A] = contabandiera[B] = 0&lt;br /&gt;
    winner = -1;&lt;br /&gt;
    for (s in n)&lt;br /&gt;
    {&lt;br /&gt;
        ok2run[A][s].signal();&lt;br /&gt;
        ok2run[B][s].signal()&lt;br /&gt;
    }&lt;br /&gt;
    ok2punteggio.wait();&lt;br /&gt;
    punteggio[winner++]&lt;br /&gt;
    if (max(punteggio) == 10)&lt;br /&gt;
    {&lt;br /&gt;
        partitafinita = true;&lt;br /&gt;
        for (s in A,B)&lt;br /&gt;
        {&lt;br /&gt;
            for (n in range(MAX))&lt;br /&gt;
            {&lt;br /&gt;
                ok2run[s][n].signal();&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    return punteggio;&lt;br /&gt;
}&lt;br /&gt;
entry pronto(s, n):&lt;br /&gt;
{&lt;br /&gt;
    if (partitafinita) return 1;&lt;br /&gt;
    if (!partita)&lt;br /&gt;
    {&lt;br /&gt;
        okpartita.wait();&lt;br /&gt;
    }&lt;br /&gt;
    numpronti++;&lt;br /&gt;
    if (numpronti&amp;gt;=2*MAX)&lt;br /&gt;
    {&lt;br /&gt;
        ok2chiama.signal();&lt;br /&gt;
    }&lt;br /&gt;
    if (!(n in chiamati))&lt;br /&gt;
    {&lt;br /&gt;
        ok2run[s][n].wait();&lt;br /&gt;
    }&lt;br /&gt;
    numpronti--;&lt;br /&gt;
    return 0 if partita else 1;&lt;br /&gt;
}&lt;br /&gt;
allabandiera(s, n):&lt;br /&gt;
{&lt;br /&gt;
    contabandiera[s]++;&lt;br /&gt;
    if (winner == -1 &amp;amp;&amp;amp; contabandiera[s] == len(chiamati))&lt;br /&gt;
    {&lt;br /&gt;
        winner = s;&lt;br /&gt;
    }&lt;br /&gt;
    if (contabandiera[A] == len(chiamati) &amp;amp;&amp;amp; contabandiera[B] == len(chiamati))&lt;br /&gt;
    {&lt;br /&gt;
        ok2punteggio.signal();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
casi da discutere:    &lt;br /&gt;
se arrivano studenti a pronto prima che il prof dichiara nuovapartita succedono guai.&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>LiberaL</name></author>
	</entry>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=Prove_scritte_2017&amp;diff=3030</id>
		<title>Prove scritte 2017</title>
		<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php?title=Prove_scritte_2017&amp;diff=3030"/>
		<updated>2023-05-27T11:22:08Z</updated>

		<summary type="html">&lt;p&gt;LiberaL: /* Esercizio c.2 (da controllare) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Esame 11/09/2017 ==&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2017.09.11.tot.pdf 2017.09.11.tot.pdf]&lt;br /&gt;
=== Esercizio c.1 ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
monitor crossing&lt;br /&gt;
&lt;br /&gt;
ok2dir[4];     //NESW&lt;br /&gt;
bool busy = false;&lt;br /&gt;
&lt;br /&gt;
pe entra(int dir)&lt;br /&gt;
   if (busy)&lt;br /&gt;
      ok2dir[dir].wait();&lt;br /&gt;
   busy = true;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
pe esci(int dir)&lt;br /&gt;
   busy = false;&lt;br /&gt;
   ok2dir[(dir + 1) % 4].signal();&lt;br /&gt;
   if (!busy)&lt;br /&gt;
      ok2dir[(dir + 2) % 4].signal();&lt;br /&gt;
   if (!busy)&lt;br /&gt;
      ok2dir[(dir + 3) % 4].signal();&lt;br /&gt;
   if (!busy)&lt;br /&gt;
      ok2dir[(dir + 4) % 4].signal();  //dir&lt;br /&gt;
&lt;br /&gt;
//alternativa più compatta&lt;br /&gt;
pe esci(int dir)&lt;br /&gt;
   busy = false;&lt;br /&gt;
   for (i = 0; i &amp;lt; 4; i++)&lt;br /&gt;
   if (!busy)&lt;br /&gt;
      ok2dir[(dir + i + 1) % 4].signal();&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Soluzione proposta 2 ==== &lt;br /&gt;
Soluzione proposta da [https://t.me/LLibera LLibera] e corretta da  [https://so.v2.cs.unibo.it/wiki/index.php/User:Flecart Flecart]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
const int N_DIRECTION = 4;&lt;br /&gt;
&lt;br /&gt;
// assumo N = 0, E = 1, S = 2, W = 3, oppure shiftati ciclicamente, è equivalente&lt;br /&gt;
&lt;br /&gt;
monitor crossing {&lt;br /&gt;
	bool free;										//l'incrocio è libero?&lt;br /&gt;
	int num_waiting[N_DIRECTION];&lt;br /&gt;
	condition okToCross[N_DIRECTION];				//free == True&lt;br /&gt;
	&lt;br /&gt;
	crossing() {&lt;br /&gt;
		free = True;								//parto con l'incrocio libero&lt;br /&gt;
		for (int i = 0; i &amp;lt; N_DIRECTION; i++) {&lt;br /&gt;
			num_waiting[i] = 0;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	procedure entry enter(int direction) {&lt;br /&gt;
		if(!free) {									//se l'incrocio non è libero&lt;br /&gt;
			num_waiting[direction]++;&lt;br /&gt;
			okToCross[direction].wait();			//aspetto nella mia direzione&lt;br /&gt;
			num_waiting[direction]--;&lt;br /&gt;
		}&lt;br /&gt;
													//ora sono sicurə che sia libero&lt;br /&gt;
		free = False;								//quindi lo dichiaro occupato&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	procedure entry exit(int direction) {&lt;br /&gt;
													//non devo aspettare niente per liberare l'incrocio&lt;br /&gt;
		free = True;								//lo dichiaro libero&lt;br /&gt;
		&lt;br /&gt;
		for (int i = 0; i &amp;lt; N_DIRECTION; i++) {&lt;br /&gt;
			int curr_dir = (direction + i + 1) % N_DIRECTION;&lt;br /&gt;
			if (num_waiting[curr_dir] &amp;gt; 0) {&lt;br /&gt;
				okToCross[curr_dir].signal();&lt;br /&gt;
				break;	// l'onere di risvegliare gli altri è stato passato al nuovo processo risvegliato, quindi esco.&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.2 (da controllare) ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// server[] = array contenente il PID di tutti i server&lt;br /&gt;
&lt;br /&gt;
#define BROADCAST server[0]&lt;br /&gt;
&lt;br /&gt;
server[0]&lt;br /&gt;
{&lt;br /&gt;
    while(true)&lt;br /&gt;
    {&lt;br /&gt;
        &amp;lt;msg, sender&amp;gt; = arecv(*); // ricevo il messaggio&lt;br /&gt;
        if (sender == BROADCAST)&lt;br /&gt;
            print(msg); // se il messaggio l'ho ricevuto da me stesso allora lo stampo&lt;br /&gt;
        else&lt;br /&gt;
            asend(*, &amp;lt;msg, getpid()&amp;gt;); // se il messaggio l'ho ricevuto da un client o da un altro server lo inoltro a tutti i server (compreso me stesso)&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
server[x] // x = 1...N-1&lt;br /&gt;
{&lt;br /&gt;
    while(true)&lt;br /&gt;
    {&lt;br /&gt;
        &amp;lt;msg, sender&amp;gt; = arecv(*); // ricevo il messaggio&lt;br /&gt;
        if (sender == BROADCAST)&lt;br /&gt;
            print(msg); // se il messaggio l'ho ricevuto dal server[0] allora lo stampo&lt;br /&gt;
        else&lt;br /&gt;
            asend(BROADCAST, &amp;lt;msg, getpid()&amp;gt;) // se il messaggio l'ho ricevuto da un client lo inoltro al server[0]&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Soluzione proposta 2 ====&lt;br /&gt;
&lt;br /&gt;
Soluzione proposta da [https://so.v2.cs.unibo.it/wiki/index.php/User:Flecart Flecart]&lt;br /&gt;
Soluzione corretta da [https://so.v2.cs.unibo.it/wiki/index.php/User:Gio Flecart friend]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
process server_0 {&lt;br /&gt;
&lt;br /&gt;
        while (true) {&lt;br /&gt;
                &amp;lt;msg, sender&amp;gt; = arecv(ANY);&lt;br /&gt;
                for (int i = 1 ; i &amp;lt; N; i++) {&lt;br /&gt;
                        asend(&amp;lt;msg, 0&amp;gt;, server[i]);&lt;br /&gt;
                        while(true){&lt;br /&gt;
                          msg = arecv(server[i]); // così so che tutti abbiano stampato.&lt;br /&gt;
                          if(msg==ACK)&lt;br /&gt;
                            break&lt;br /&gt;
                          asend(msg,server[0]);&lt;br /&gt;
                        }&lt;br /&gt;
                }&lt;br /&gt;
                print(msg);&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
process server_[i=1 to N - 1] {&lt;br /&gt;
        while (true) {&lt;br /&gt;
                &amp;lt;msg, sender&amp;gt; = arecv(ANY);&lt;br /&gt;
                if (sender == 0) {&lt;br /&gt;
                        print(msg);&lt;br /&gt;
                        asend(ACK, server[0]);&lt;br /&gt;
                } else {&lt;br /&gt;
                        asend(&amp;lt;msg, i&amp;gt;, server[0]);&lt;br /&gt;
                }&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Esame 17/07/2017 ==&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2017.07.17.tot.pdf 2017.07.17.tot.pdf]&lt;br /&gt;
=== Esercizio c.1 ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
monitor conf {&lt;br /&gt;
        condition finished;&lt;br /&gt;
        condition ready2present[max];&lt;br /&gt;
        bool arrived[max] = false;&lt;br /&gt;
        bool giachiamato[max] = false;&lt;br /&gt;
&lt;br /&gt;
        entry chiama(chiamato){&lt;br /&gt;
        if(arrived[chiamato] == true)&lt;br /&gt;
                ready2present[chiamato].signal;&lt;br /&gt;
                finished.wait;&lt;br /&gt;
                return true;&lt;br /&gt;
        else&lt;br /&gt;
                giachiamato[chiamato]= true&lt;br /&gt;
                return false;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        entry arrivato(nome){&lt;br /&gt;
                if(giachiamato[nome] == true)&lt;br /&gt;
                        return  false;&lt;br /&gt;
&lt;br /&gt;
                arrived[nome] = true;&lt;br /&gt;
                ok2present[nome].wait;&lt;br /&gt;
                return true;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        entry finepresentazione(nome){&lt;br /&gt;
                finished.signal;&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.2 (da controllare) ===&lt;br /&gt;
controllata da [[User:LiberaL|LiberaL]] 14:26, 26 May 2023 (CEST) l'implementazione fornita gestisce solo il caso di arecv(ANY) e non arecv(mittente)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
si, è possibile: &lt;br /&gt;
&lt;br /&gt;
Implementare asend e arecv date bsend e brecv&lt;br /&gt;
&lt;br /&gt;
asend(pid_t dst, msg_type msg){&lt;br /&gt;
    bsend (&amp;lt;dst, msg&amp;gt;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
arecv(*){&lt;br /&gt;
  do {&lt;br /&gt;
    &amp;lt;dst, msg&amp;gt; = brecv(*);&lt;br /&gt;
  } while (dst != getpid())&lt;br /&gt;
  return msg;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
propongo ([[User:LiberaL|LiberaL]] 13:11, 27 May 2023 (CEST)) quindi questa implementazione con gestione arecv da mittente specificato (sempre da controllare)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
//il messaggio mandato è la tripla &amp;lt;destinatario, mittente, messaggio&amp;gt;&lt;br /&gt;
&lt;br /&gt;
asend(pid_t dst, msg_type msg){&lt;br /&gt;
    bsend (&amp;lt;dst, getpid(), msg&amp;gt;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Queue of &amp;lt;pid_t, msg_type&amp;gt; db; //nota: salvo qui solo se il messaggio è per me, quindi dest non mi serve&lt;br /&gt;
&lt;br /&gt;
arecv(pid_t sender) {&lt;br /&gt;
&lt;br /&gt;
  //devo controllare se nella coda ho già ricevuto il messaggio da quel mittente, ovvero mentre aspettavo un messaggio da qualcun'altro&lt;br /&gt;
  //db.get(sender) cerca una tripla il cui mittente è sender&lt;br /&gt;
  //se trova il messaggio lo rimuove anche dal db.&lt;br /&gt;
  //db.get(ANY) ritorna (ed elimina da db) il primo che trova (FIFO), e if(db.isEmpty()) return NULL;&lt;br /&gt;
  if( ( &amp;lt;mit, msg&amp;gt; = db.get(sender) ) != NULL ) //se lo trova&lt;br /&gt;
    return msg;&lt;br /&gt;
&lt;br /&gt;
  bool message_for_me;&lt;br /&gt;
  do {&lt;br /&gt;
    &amp;lt;dst, mit, msg&amp;gt; = brecv(*);                 //ricevo&lt;br /&gt;
    message_for_me = (dst == getpid());         //il messaggio è per me?&lt;br /&gt;
    if( message_for_me ) {&lt;br /&gt;
      if ( mit == sender || sender == ANY )     //se devo ritornare il messaggio&lt;br /&gt;
        break;     //esci dal while&lt;br /&gt;
      else                                      //se devo salvarlo (sender specificato e messaggio per me)&lt;br /&gt;
        //devo mettere in db i messaggi di altri mittenti, ricevuti quando ne aspettavo uno da un mittente specificato&lt;br /&gt;
        db.add(&amp;lt;mit, msg&amp;gt;);&lt;br /&gt;
    }&lt;br /&gt;
  } while (!message_for_me)&lt;br /&gt;
&lt;br /&gt;
  return msg;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Esame 19/06/2017 ==&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2017.06.19.tot.pdf 2017.06.19.tot.pdf]&lt;br /&gt;
=== Esercizio c.1 (da controllare)===&lt;br /&gt;
&lt;br /&gt;
* Mi sembra che ci sia un errore per il giodice, potrebbe succedere in un caso che il wait non si risvegli mai [[User:Flecart|Flecart]] ([[User talk:Flecart|talk]]) 15:38, 19 January 2023 (CET)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define NATLETI n&lt;br /&gt;
&lt;br /&gt;
condition ok2lancia[NATLETI];&lt;br /&gt;
condition ok2giudice;&lt;br /&gt;
&lt;br /&gt;
int counter[NATLETI];&lt;br /&gt;
int ultimo_tiro;&lt;br /&gt;
float registro[NATLETI][3];&lt;br /&gt;
&lt;br /&gt;
Procedure entry: boolean pronto(int i)&lt;br /&gt;
{&lt;br /&gt;
    if(!(i == 0 &amp;amp;&amp;amp; counter[i] == 0)) // se è il primo lancio non devo metterlo in wait&lt;br /&gt;
        ok2lancia[i].wait()&lt;br /&gt;
    if(counter[i] &amp;lt; 3)&lt;br /&gt;
        return true;&lt;br /&gt;
    else&lt;br /&gt;
        return false;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: void lanciato (int i)&lt;br /&gt;
{&lt;br /&gt;
    counter[i]++;&lt;br /&gt;
    ultimo_tiro = i;&lt;br /&gt;
    ok2giudice.signal();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: int lanciofatto()&lt;br /&gt;
{&lt;br /&gt;
    ok2giudice.wait()&lt;br /&gt;
    if(ultimo_tiro == NATLETI-1 &amp;amp;&amp;amp; counter[0] == 3)&lt;br /&gt;
        return -1;  // devo invalidare la condizione per uscire dal while, quindi se nessuno deve più lanciare ritorno -1&lt;br /&gt;
    else&lt;br /&gt;
        return ultimo_tiro;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: void registraechiama(int i, float m)&lt;br /&gt;
{&lt;br /&gt;
    registro[i][counter[i]-1] = m; // il secondo indice indica l'iesimo lancio -1 (perchè iniziamo a contare da zero)&lt;br /&gt;
    if(i == NATLETI-1) // se ha appena tirato l'ultimo atleta non posso dare il via a NATLETI (perchè non esiste), quindi faccio ricominciare il giro&lt;br /&gt;
        ok2lancia[0].signal();&lt;br /&gt;
    else&lt;br /&gt;
        ok2lancia[i+1].signal();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: int classifica()&lt;br /&gt;
{&lt;br /&gt;
    int best[NATLETI];&lt;br /&gt;
    for(int i = 0; i &amp;lt; NATLETI; i++)&lt;br /&gt;
    {&lt;br /&gt;
        for(int j = 0; j &amp;lt; 3; j++)&lt;br /&gt;
        {&lt;br /&gt;
            if(registro[i][j] &amp;gt; best[i])&lt;br /&gt;
                best[i] = registro[i][j];&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    best.sort_in_descending_order(); // supponiamo nel nostro pseudolinguaggio esista una funzione di ordinamento qualunque&lt;br /&gt;
    return best;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Esame 29/05/2017 ==&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2017.05.29.tot.pdf 2017.05.29.tot.pdf]&lt;br /&gt;
=== Esercizio c.1 ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
condition okpartita&lt;br /&gt;
condition ok2chiama&lt;br /&gt;
condition ok2punteggio&lt;br /&gt;
condition ok2run[2][MAX]&lt;br /&gt;
int numpronti&lt;br /&gt;
int punteggio[2]&lt;br /&gt;
boolean partita=false&lt;br /&gt;
boolean partitafinita=false&lt;br /&gt;
chiamati = []&lt;br /&gt;
contabandiera[2]&lt;br /&gt;
int winner&lt;br /&gt;
&lt;br /&gt;
entry nuovapartita():&lt;br /&gt;
{&lt;br /&gt;
    punteggio[A] = punteggio[B] = 0;&lt;br /&gt;
    numpronti = 0;&lt;br /&gt;
    partita=true;&lt;br /&gt;
    okpartita.signal()&lt;br /&gt;
    chiamati = [];&lt;br /&gt;
}&lt;br /&gt;
entry chiama(l):&lt;br /&gt;
{&lt;br /&gt;
    if (numpronti&amp;lt;2*MAX)&lt;br /&gt;
    {&lt;br /&gt;
        ok2chiama.wait();&lt;br /&gt;
    }&lt;br /&gt;
    chiamati = l;&lt;br /&gt;
    contabandiera[A] = contabandiera[B] = 0&lt;br /&gt;
    winner = -1;&lt;br /&gt;
    for (s in n)&lt;br /&gt;
    {&lt;br /&gt;
        ok2run[A][s].signal();&lt;br /&gt;
        ok2run[B][s].signal()&lt;br /&gt;
    }&lt;br /&gt;
    ok2punteggio.wait();&lt;br /&gt;
    punteggio[winner++]&lt;br /&gt;
    if (max(punteggio) == 10)&lt;br /&gt;
    {&lt;br /&gt;
        partitafinita = true;&lt;br /&gt;
        for (s in A,B)&lt;br /&gt;
        {&lt;br /&gt;
            for (n in range(MAX))&lt;br /&gt;
            {&lt;br /&gt;
                ok2run[s][n].signal();&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    return punteggio;&lt;br /&gt;
}&lt;br /&gt;
entry pronto(s, n):&lt;br /&gt;
{&lt;br /&gt;
    if (partitafinita) return 1;&lt;br /&gt;
    if (!partita)&lt;br /&gt;
    {&lt;br /&gt;
        okpartita.wait();&lt;br /&gt;
    }&lt;br /&gt;
    numpronti++;&lt;br /&gt;
    if (numpronti&amp;gt;=2*MAX)&lt;br /&gt;
    {&lt;br /&gt;
        ok2chiama.signal();&lt;br /&gt;
    }&lt;br /&gt;
    if (!(n in chiamati))&lt;br /&gt;
    {&lt;br /&gt;
        ok2run[s][n].wait();&lt;br /&gt;
    }&lt;br /&gt;
    numpronti--;&lt;br /&gt;
    return 0 if partita else 1;&lt;br /&gt;
}&lt;br /&gt;
allabandiera(s, n):&lt;br /&gt;
{&lt;br /&gt;
    contabandiera[s]++;&lt;br /&gt;
    if (winner == -1 &amp;amp;&amp;amp; contabandiera[s] == len(chiamati))&lt;br /&gt;
    {&lt;br /&gt;
        winner = s;&lt;br /&gt;
    }&lt;br /&gt;
    if (contabandiera[A] == len(chiamati) &amp;amp;&amp;amp; contabandiera[B] == len(chiamati))&lt;br /&gt;
    {&lt;br /&gt;
        ok2punteggio.signal();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
casi da discutere:    &lt;br /&gt;
se arrivano studenti a pronto prima che il prof dichiara nuovapartita succedono guai.&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>LiberaL</name></author>
	</entry>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=Prove_scritte_2017&amp;diff=3029</id>
		<title>Prove scritte 2017</title>
		<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php?title=Prove_scritte_2017&amp;diff=3029"/>
		<updated>2023-05-27T11:21:17Z</updated>

		<summary type="html">&lt;p&gt;LiberaL: /* Esercizio c.2 (da controllare) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Esame 11/09/2017 ==&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2017.09.11.tot.pdf 2017.09.11.tot.pdf]&lt;br /&gt;
=== Esercizio c.1 ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
monitor crossing&lt;br /&gt;
&lt;br /&gt;
ok2dir[4];     //NESW&lt;br /&gt;
bool busy = false;&lt;br /&gt;
&lt;br /&gt;
pe entra(int dir)&lt;br /&gt;
   if (busy)&lt;br /&gt;
      ok2dir[dir].wait();&lt;br /&gt;
   busy = true;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
pe esci(int dir)&lt;br /&gt;
   busy = false;&lt;br /&gt;
   ok2dir[(dir + 1) % 4].signal();&lt;br /&gt;
   if (!busy)&lt;br /&gt;
      ok2dir[(dir + 2) % 4].signal();&lt;br /&gt;
   if (!busy)&lt;br /&gt;
      ok2dir[(dir + 3) % 4].signal();&lt;br /&gt;
   if (!busy)&lt;br /&gt;
      ok2dir[(dir + 4) % 4].signal();  //dir&lt;br /&gt;
&lt;br /&gt;
//alternativa più compatta&lt;br /&gt;
pe esci(int dir)&lt;br /&gt;
   busy = false;&lt;br /&gt;
   for (i = 0; i &amp;lt; 4; i++)&lt;br /&gt;
   if (!busy)&lt;br /&gt;
      ok2dir[(dir + i + 1) % 4].signal();&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Soluzione proposta 2 ==== &lt;br /&gt;
Soluzione proposta da [https://t.me/LLibera LLibera] e corretta da  [https://so.v2.cs.unibo.it/wiki/index.php/User:Flecart Flecart]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
const int N_DIRECTION = 4;&lt;br /&gt;
&lt;br /&gt;
// assumo N = 0, E = 1, S = 2, W = 3, oppure shiftati ciclicamente, è equivalente&lt;br /&gt;
&lt;br /&gt;
monitor crossing {&lt;br /&gt;
	bool free;										//l'incrocio è libero?&lt;br /&gt;
	int num_waiting[N_DIRECTION];&lt;br /&gt;
	condition okToCross[N_DIRECTION];				//free == True&lt;br /&gt;
	&lt;br /&gt;
	crossing() {&lt;br /&gt;
		free = True;								//parto con l'incrocio libero&lt;br /&gt;
		for (int i = 0; i &amp;lt; N_DIRECTION; i++) {&lt;br /&gt;
			num_waiting[i] = 0;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	procedure entry enter(int direction) {&lt;br /&gt;
		if(!free) {									//se l'incrocio non è libero&lt;br /&gt;
			num_waiting[direction]++;&lt;br /&gt;
			okToCross[direction].wait();			//aspetto nella mia direzione&lt;br /&gt;
			num_waiting[direction]--;&lt;br /&gt;
		}&lt;br /&gt;
													//ora sono sicurə che sia libero&lt;br /&gt;
		free = False;								//quindi lo dichiaro occupato&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	procedure entry exit(int direction) {&lt;br /&gt;
													//non devo aspettare niente per liberare l'incrocio&lt;br /&gt;
		free = True;								//lo dichiaro libero&lt;br /&gt;
		&lt;br /&gt;
		for (int i = 0; i &amp;lt; N_DIRECTION; i++) {&lt;br /&gt;
			int curr_dir = (direction + i + 1) % N_DIRECTION;&lt;br /&gt;
			if (num_waiting[curr_dir] &amp;gt; 0) {&lt;br /&gt;
				okToCross[curr_dir].signal();&lt;br /&gt;
				break;	// l'onere di risvegliare gli altri è stato passato al nuovo processo risvegliato, quindi esco.&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.2 (da controllare) ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// server[] = array contenente il PID di tutti i server&lt;br /&gt;
&lt;br /&gt;
#define BROADCAST server[0]&lt;br /&gt;
&lt;br /&gt;
server[0]&lt;br /&gt;
{&lt;br /&gt;
    while(true)&lt;br /&gt;
    {&lt;br /&gt;
        &amp;lt;msg, sender&amp;gt; = arecv(*); // ricevo il messaggio&lt;br /&gt;
        if (sender == BROADCAST)&lt;br /&gt;
            print(msg); // se il messaggio l'ho ricevuto da me stesso allora lo stampo&lt;br /&gt;
        else&lt;br /&gt;
            asend(*, &amp;lt;msg, getpid()&amp;gt;); // se il messaggio l'ho ricevuto da un client o da un altro server lo inoltro a tutti i server (compreso me stesso)&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
server[x] // x = 1...N-1&lt;br /&gt;
{&lt;br /&gt;
    while(true)&lt;br /&gt;
    {&lt;br /&gt;
        &amp;lt;msg, sender&amp;gt; = arecv(*); // ricevo il messaggio&lt;br /&gt;
        if (sender == BROADCAST)&lt;br /&gt;
            print(msg); // se il messaggio l'ho ricevuto dal server[0] allora lo stampo&lt;br /&gt;
        else&lt;br /&gt;
            asend(BROADCAST, &amp;lt;msg, getpid()&amp;gt;) // se il messaggio l'ho ricevuto da un client lo inoltro al server[0]&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Soluzione proposta 2 ====&lt;br /&gt;
&lt;br /&gt;
Soluzione proposta da [https://so.v2.cs.unibo.it/wiki/index.php/User:Flecart Flecart]&lt;br /&gt;
Soluzione corretta da [https://so.v2.cs.unibo.it/wiki/index.php/User:Gio Flecart friend]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
process server_0 {&lt;br /&gt;
&lt;br /&gt;
        while (true) {&lt;br /&gt;
                &amp;lt;msg, sender&amp;gt; = arecv(ANY);&lt;br /&gt;
                for (int i = 1 ; i &amp;lt; N; i++) {&lt;br /&gt;
                        asend(&amp;lt;msg, 0&amp;gt;, server[i]);&lt;br /&gt;
                        while(true){&lt;br /&gt;
                          msg = arecv(server[i]); // così so che tutti abbiano stampato.&lt;br /&gt;
                          if(msg==ACK)&lt;br /&gt;
                            break&lt;br /&gt;
                          asend(msg,server[0]);&lt;br /&gt;
                        }&lt;br /&gt;
                }&lt;br /&gt;
                print(msg);&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
process server_[i=1 to N - 1] {&lt;br /&gt;
        while (true) {&lt;br /&gt;
                &amp;lt;msg, sender&amp;gt; = arecv(ANY);&lt;br /&gt;
                if (sender == 0) {&lt;br /&gt;
                        print(msg);&lt;br /&gt;
                        asend(ACK, server[0]);&lt;br /&gt;
                } else {&lt;br /&gt;
                        asend(&amp;lt;msg, i&amp;gt;, server[0]);&lt;br /&gt;
                }&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Esame 17/07/2017 ==&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2017.07.17.tot.pdf 2017.07.17.tot.pdf]&lt;br /&gt;
=== Esercizio c.1 ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
monitor conf {&lt;br /&gt;
        condition finished;&lt;br /&gt;
        condition ready2present[max];&lt;br /&gt;
        bool arrived[max] = false;&lt;br /&gt;
        bool giachiamato[max] = false;&lt;br /&gt;
&lt;br /&gt;
        entry chiama(chiamato){&lt;br /&gt;
        if(arrived[chiamato] == true)&lt;br /&gt;
                ready2present[chiamato].signal;&lt;br /&gt;
                finished.wait;&lt;br /&gt;
                return true;&lt;br /&gt;
        else&lt;br /&gt;
                giachiamato[chiamato]= true&lt;br /&gt;
                return false;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        entry arrivato(nome){&lt;br /&gt;
                if(giachiamato[nome] == true)&lt;br /&gt;
                        return  false;&lt;br /&gt;
&lt;br /&gt;
                arrived[nome] = true;&lt;br /&gt;
                ok2present[nome].wait;&lt;br /&gt;
                return true;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        entry finepresentazione(nome){&lt;br /&gt;
                finished.signal;&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.2 (da controllare) ===&lt;br /&gt;
controllata da [[User:LiberaL|LiberaL]] 14:26, 26 May 2023 (CEST) l'implementazione fornita gestisce solo il caso di arecv(ANY) e non arecv(mittente)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
si, è possibile: &lt;br /&gt;
&lt;br /&gt;
Implementare asend e arecv date bsend e brecv&lt;br /&gt;
&lt;br /&gt;
asend(pid_t dst, msg_type msg){&lt;br /&gt;
    bsend (&amp;lt;dst, msg&amp;gt;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
arecv(*){&lt;br /&gt;
  do {&lt;br /&gt;
    &amp;lt;dst, msg&amp;gt; = brecv(*);&lt;br /&gt;
  } while (dst != getpid())&lt;br /&gt;
  return msg;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
propongo ([[User:LiberaL|LiberaL]] 13:11, 27 May 2023 (CEST)) quindi questa implementazione con gestione arecv da mittente specificato (sempre da controllare)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
//il messaggio mandato è la tripla &amp;lt;destinatario, mittente, messaggio&amp;gt;&lt;br /&gt;
&lt;br /&gt;
asend(pid_t dst, msg_type msg){&lt;br /&gt;
    bsend (&amp;lt;dst, getpid(), msg&amp;gt;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Queue of &amp;lt;pid_t, msg_type&amp;gt; db; //nota: salvo qui solo se il messaggio è per me, quindi dest non mi serve&lt;br /&gt;
arecv(pid_t sender) {&lt;br /&gt;
&lt;br /&gt;
  //devo controllare se nella coda ho già ricevuto il messaggio da quel mittente, ovvero mentre aspettavo un messaggio da qualcun'altro&lt;br /&gt;
  //db.get(sender) cerca una tripla il cui mittente è sender&lt;br /&gt;
  //se trova il messaggio lo rimuove anche dal db.&lt;br /&gt;
  //db.get(ANY) ritorna (ed elimina da db) il primo che trova (FIFO), e if(db.isEmpty()) return NULL;&lt;br /&gt;
  if( ( &amp;lt;mit, msg&amp;gt; = db.get(sender) ) != NULL ) //se lo trova&lt;br /&gt;
    return msg;&lt;br /&gt;
&lt;br /&gt;
  bool message_for_me;&lt;br /&gt;
  do {&lt;br /&gt;
    &amp;lt;dst, mit, msg&amp;gt; = brecv(*);                 //ricevo&lt;br /&gt;
    message_for_me = (dst == getpid());         //il messaggio è per me?&lt;br /&gt;
    if( message_for_me ) {&lt;br /&gt;
      if ( mit == sender || sender == ANY )     //se devo ritornare il messaggio&lt;br /&gt;
        break;     //esci dal while&lt;br /&gt;
      else                                      //se devo salvarlo (sender specificato e messaggio per me)&lt;br /&gt;
        //devo mettere in db i messaggi di altri mittenti, ricevuti quando ne aspettavo uno da un mittente specificato&lt;br /&gt;
        db.add(&amp;lt;mit, msg&amp;gt;);&lt;br /&gt;
    }&lt;br /&gt;
  } while (!message_for_me)&lt;br /&gt;
  return msg;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Esame 19/06/2017 ==&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2017.06.19.tot.pdf 2017.06.19.tot.pdf]&lt;br /&gt;
=== Esercizio c.1 (da controllare)===&lt;br /&gt;
&lt;br /&gt;
* Mi sembra che ci sia un errore per il giodice, potrebbe succedere in un caso che il wait non si risvegli mai [[User:Flecart|Flecart]] ([[User talk:Flecart|talk]]) 15:38, 19 January 2023 (CET)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define NATLETI n&lt;br /&gt;
&lt;br /&gt;
condition ok2lancia[NATLETI];&lt;br /&gt;
condition ok2giudice;&lt;br /&gt;
&lt;br /&gt;
int counter[NATLETI];&lt;br /&gt;
int ultimo_tiro;&lt;br /&gt;
float registro[NATLETI][3];&lt;br /&gt;
&lt;br /&gt;
Procedure entry: boolean pronto(int i)&lt;br /&gt;
{&lt;br /&gt;
    if(!(i == 0 &amp;amp;&amp;amp; counter[i] == 0)) // se è il primo lancio non devo metterlo in wait&lt;br /&gt;
        ok2lancia[i].wait()&lt;br /&gt;
    if(counter[i] &amp;lt; 3)&lt;br /&gt;
        return true;&lt;br /&gt;
    else&lt;br /&gt;
        return false;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: void lanciato (int i)&lt;br /&gt;
{&lt;br /&gt;
    counter[i]++;&lt;br /&gt;
    ultimo_tiro = i;&lt;br /&gt;
    ok2giudice.signal();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: int lanciofatto()&lt;br /&gt;
{&lt;br /&gt;
    ok2giudice.wait()&lt;br /&gt;
    if(ultimo_tiro == NATLETI-1 &amp;amp;&amp;amp; counter[0] == 3)&lt;br /&gt;
        return -1;  // devo invalidare la condizione per uscire dal while, quindi se nessuno deve più lanciare ritorno -1&lt;br /&gt;
    else&lt;br /&gt;
        return ultimo_tiro;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: void registraechiama(int i, float m)&lt;br /&gt;
{&lt;br /&gt;
    registro[i][counter[i]-1] = m; // il secondo indice indica l'iesimo lancio -1 (perchè iniziamo a contare da zero)&lt;br /&gt;
    if(i == NATLETI-1) // se ha appena tirato l'ultimo atleta non posso dare il via a NATLETI (perchè non esiste), quindi faccio ricominciare il giro&lt;br /&gt;
        ok2lancia[0].signal();&lt;br /&gt;
    else&lt;br /&gt;
        ok2lancia[i+1].signal();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: int classifica()&lt;br /&gt;
{&lt;br /&gt;
    int best[NATLETI];&lt;br /&gt;
    for(int i = 0; i &amp;lt; NATLETI; i++)&lt;br /&gt;
    {&lt;br /&gt;
        for(int j = 0; j &amp;lt; 3; j++)&lt;br /&gt;
        {&lt;br /&gt;
            if(registro[i][j] &amp;gt; best[i])&lt;br /&gt;
                best[i] = registro[i][j];&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    best.sort_in_descending_order(); // supponiamo nel nostro pseudolinguaggio esista una funzione di ordinamento qualunque&lt;br /&gt;
    return best;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Esame 29/05/2017 ==&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2017.05.29.tot.pdf 2017.05.29.tot.pdf]&lt;br /&gt;
=== Esercizio c.1 ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
condition okpartita&lt;br /&gt;
condition ok2chiama&lt;br /&gt;
condition ok2punteggio&lt;br /&gt;
condition ok2run[2][MAX]&lt;br /&gt;
int numpronti&lt;br /&gt;
int punteggio[2]&lt;br /&gt;
boolean partita=false&lt;br /&gt;
boolean partitafinita=false&lt;br /&gt;
chiamati = []&lt;br /&gt;
contabandiera[2]&lt;br /&gt;
int winner&lt;br /&gt;
&lt;br /&gt;
entry nuovapartita():&lt;br /&gt;
{&lt;br /&gt;
    punteggio[A] = punteggio[B] = 0;&lt;br /&gt;
    numpronti = 0;&lt;br /&gt;
    partita=true;&lt;br /&gt;
    okpartita.signal()&lt;br /&gt;
    chiamati = [];&lt;br /&gt;
}&lt;br /&gt;
entry chiama(l):&lt;br /&gt;
{&lt;br /&gt;
    if (numpronti&amp;lt;2*MAX)&lt;br /&gt;
    {&lt;br /&gt;
        ok2chiama.wait();&lt;br /&gt;
    }&lt;br /&gt;
    chiamati = l;&lt;br /&gt;
    contabandiera[A] = contabandiera[B] = 0&lt;br /&gt;
    winner = -1;&lt;br /&gt;
    for (s in n)&lt;br /&gt;
    {&lt;br /&gt;
        ok2run[A][s].signal();&lt;br /&gt;
        ok2run[B][s].signal()&lt;br /&gt;
    }&lt;br /&gt;
    ok2punteggio.wait();&lt;br /&gt;
    punteggio[winner++]&lt;br /&gt;
    if (max(punteggio) == 10)&lt;br /&gt;
    {&lt;br /&gt;
        partitafinita = true;&lt;br /&gt;
        for (s in A,B)&lt;br /&gt;
        {&lt;br /&gt;
            for (n in range(MAX))&lt;br /&gt;
            {&lt;br /&gt;
                ok2run[s][n].signal();&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    return punteggio;&lt;br /&gt;
}&lt;br /&gt;
entry pronto(s, n):&lt;br /&gt;
{&lt;br /&gt;
    if (partitafinita) return 1;&lt;br /&gt;
    if (!partita)&lt;br /&gt;
    {&lt;br /&gt;
        okpartita.wait();&lt;br /&gt;
    }&lt;br /&gt;
    numpronti++;&lt;br /&gt;
    if (numpronti&amp;gt;=2*MAX)&lt;br /&gt;
    {&lt;br /&gt;
        ok2chiama.signal();&lt;br /&gt;
    }&lt;br /&gt;
    if (!(n in chiamati))&lt;br /&gt;
    {&lt;br /&gt;
        ok2run[s][n].wait();&lt;br /&gt;
    }&lt;br /&gt;
    numpronti--;&lt;br /&gt;
    return 0 if partita else 1;&lt;br /&gt;
}&lt;br /&gt;
allabandiera(s, n):&lt;br /&gt;
{&lt;br /&gt;
    contabandiera[s]++;&lt;br /&gt;
    if (winner == -1 &amp;amp;&amp;amp; contabandiera[s] == len(chiamati))&lt;br /&gt;
    {&lt;br /&gt;
        winner = s;&lt;br /&gt;
    }&lt;br /&gt;
    if (contabandiera[A] == len(chiamati) &amp;amp;&amp;amp; contabandiera[B] == len(chiamati))&lt;br /&gt;
    {&lt;br /&gt;
        ok2punteggio.signal();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
casi da discutere:    &lt;br /&gt;
se arrivano studenti a pronto prima che il prof dichiara nuovapartita succedono guai.&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>LiberaL</name></author>
	</entry>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=Prove_scritte_2017&amp;diff=3028</id>
		<title>Prove scritte 2017</title>
		<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php?title=Prove_scritte_2017&amp;diff=3028"/>
		<updated>2023-05-27T11:11:39Z</updated>

		<summary type="html">&lt;p&gt;LiberaL: /* Esercizio c.2 (da controllare) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Esame 11/09/2017 ==&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2017.09.11.tot.pdf 2017.09.11.tot.pdf]&lt;br /&gt;
=== Esercizio c.1 ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
monitor crossing&lt;br /&gt;
&lt;br /&gt;
ok2dir[4];     //NESW&lt;br /&gt;
bool busy = false;&lt;br /&gt;
&lt;br /&gt;
pe entra(int dir)&lt;br /&gt;
   if (busy)&lt;br /&gt;
      ok2dir[dir].wait();&lt;br /&gt;
   busy = true;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
pe esci(int dir)&lt;br /&gt;
   busy = false;&lt;br /&gt;
   ok2dir[(dir + 1) % 4].signal();&lt;br /&gt;
   if (!busy)&lt;br /&gt;
      ok2dir[(dir + 2) % 4].signal();&lt;br /&gt;
   if (!busy)&lt;br /&gt;
      ok2dir[(dir + 3) % 4].signal();&lt;br /&gt;
   if (!busy)&lt;br /&gt;
      ok2dir[(dir + 4) % 4].signal();  //dir&lt;br /&gt;
&lt;br /&gt;
//alternativa più compatta&lt;br /&gt;
pe esci(int dir)&lt;br /&gt;
   busy = false;&lt;br /&gt;
   for (i = 0; i &amp;lt; 4; i++)&lt;br /&gt;
   if (!busy)&lt;br /&gt;
      ok2dir[(dir + i + 1) % 4].signal();&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Soluzione proposta 2 ==== &lt;br /&gt;
Soluzione proposta da [https://t.me/LLibera LLibera] e corretta da  [https://so.v2.cs.unibo.it/wiki/index.php/User:Flecart Flecart]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
const int N_DIRECTION = 4;&lt;br /&gt;
&lt;br /&gt;
// assumo N = 0, E = 1, S = 2, W = 3, oppure shiftati ciclicamente, è equivalente&lt;br /&gt;
&lt;br /&gt;
monitor crossing {&lt;br /&gt;
	bool free;										//l'incrocio è libero?&lt;br /&gt;
	int num_waiting[N_DIRECTION];&lt;br /&gt;
	condition okToCross[N_DIRECTION];				//free == True&lt;br /&gt;
	&lt;br /&gt;
	crossing() {&lt;br /&gt;
		free = True;								//parto con l'incrocio libero&lt;br /&gt;
		for (int i = 0; i &amp;lt; N_DIRECTION; i++) {&lt;br /&gt;
			num_waiting[i] = 0;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	procedure entry enter(int direction) {&lt;br /&gt;
		if(!free) {									//se l'incrocio non è libero&lt;br /&gt;
			num_waiting[direction]++;&lt;br /&gt;
			okToCross[direction].wait();			//aspetto nella mia direzione&lt;br /&gt;
			num_waiting[direction]--;&lt;br /&gt;
		}&lt;br /&gt;
													//ora sono sicurə che sia libero&lt;br /&gt;
		free = False;								//quindi lo dichiaro occupato&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	procedure entry exit(int direction) {&lt;br /&gt;
													//non devo aspettare niente per liberare l'incrocio&lt;br /&gt;
		free = True;								//lo dichiaro libero&lt;br /&gt;
		&lt;br /&gt;
		for (int i = 0; i &amp;lt; N_DIRECTION; i++) {&lt;br /&gt;
			int curr_dir = (direction + i + 1) % N_DIRECTION;&lt;br /&gt;
			if (num_waiting[curr_dir] &amp;gt; 0) {&lt;br /&gt;
				okToCross[curr_dir].signal();&lt;br /&gt;
				break;	// l'onere di risvegliare gli altri è stato passato al nuovo processo risvegliato, quindi esco.&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.2 (da controllare) ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// server[] = array contenente il PID di tutti i server&lt;br /&gt;
&lt;br /&gt;
#define BROADCAST server[0]&lt;br /&gt;
&lt;br /&gt;
server[0]&lt;br /&gt;
{&lt;br /&gt;
    while(true)&lt;br /&gt;
    {&lt;br /&gt;
        &amp;lt;msg, sender&amp;gt; = arecv(*); // ricevo il messaggio&lt;br /&gt;
        if (sender == BROADCAST)&lt;br /&gt;
            print(msg); // se il messaggio l'ho ricevuto da me stesso allora lo stampo&lt;br /&gt;
        else&lt;br /&gt;
            asend(*, &amp;lt;msg, getpid()&amp;gt;); // se il messaggio l'ho ricevuto da un client o da un altro server lo inoltro a tutti i server (compreso me stesso)&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
server[x] // x = 1...N-1&lt;br /&gt;
{&lt;br /&gt;
    while(true)&lt;br /&gt;
    {&lt;br /&gt;
        &amp;lt;msg, sender&amp;gt; = arecv(*); // ricevo il messaggio&lt;br /&gt;
        if (sender == BROADCAST)&lt;br /&gt;
            print(msg); // se il messaggio l'ho ricevuto dal server[0] allora lo stampo&lt;br /&gt;
        else&lt;br /&gt;
            asend(BROADCAST, &amp;lt;msg, getpid()&amp;gt;) // se il messaggio l'ho ricevuto da un client lo inoltro al server[0]&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Soluzione proposta 2 ====&lt;br /&gt;
&lt;br /&gt;
Soluzione proposta da [https://so.v2.cs.unibo.it/wiki/index.php/User:Flecart Flecart]&lt;br /&gt;
Soluzione corretta da [https://so.v2.cs.unibo.it/wiki/index.php/User:Gio Flecart friend]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
process server_0 {&lt;br /&gt;
&lt;br /&gt;
        while (true) {&lt;br /&gt;
                &amp;lt;msg, sender&amp;gt; = arecv(ANY);&lt;br /&gt;
                for (int i = 1 ; i &amp;lt; N; i++) {&lt;br /&gt;
                        asend(&amp;lt;msg, 0&amp;gt;, server[i]);&lt;br /&gt;
                        while(true){&lt;br /&gt;
                          msg = arecv(server[i]); // così so che tutti abbiano stampato.&lt;br /&gt;
                          if(msg==ACK)&lt;br /&gt;
                            break&lt;br /&gt;
                          asend(msg,server[0]);&lt;br /&gt;
                        }&lt;br /&gt;
                }&lt;br /&gt;
                print(msg);&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
process server_[i=1 to N - 1] {&lt;br /&gt;
        while (true) {&lt;br /&gt;
                &amp;lt;msg, sender&amp;gt; = arecv(ANY);&lt;br /&gt;
                if (sender == 0) {&lt;br /&gt;
                        print(msg);&lt;br /&gt;
                        asend(ACK, server[0]);&lt;br /&gt;
                } else {&lt;br /&gt;
                        asend(&amp;lt;msg, i&amp;gt;, server[0]);&lt;br /&gt;
                }&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Esame 17/07/2017 ==&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2017.07.17.tot.pdf 2017.07.17.tot.pdf]&lt;br /&gt;
=== Esercizio c.1 ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
monitor conf {&lt;br /&gt;
        condition finished;&lt;br /&gt;
        condition ready2present[max];&lt;br /&gt;
        bool arrived[max] = false;&lt;br /&gt;
        bool giachiamato[max] = false;&lt;br /&gt;
&lt;br /&gt;
        entry chiama(chiamato){&lt;br /&gt;
        if(arrived[chiamato] == true)&lt;br /&gt;
                ready2present[chiamato].signal;&lt;br /&gt;
                finished.wait;&lt;br /&gt;
                return true;&lt;br /&gt;
        else&lt;br /&gt;
                giachiamato[chiamato]= true&lt;br /&gt;
                return false;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        entry arrivato(nome){&lt;br /&gt;
                if(giachiamato[nome] == true)&lt;br /&gt;
                        return  false;&lt;br /&gt;
&lt;br /&gt;
                arrived[nome] = true;&lt;br /&gt;
                ok2present[nome].wait;&lt;br /&gt;
                return true;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        entry finepresentazione(nome){&lt;br /&gt;
                finished.signal;&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.2 (da controllare) ===&lt;br /&gt;
controllata da [[User:LiberaL|LiberaL]] 14:26, 26 May 2023 (CEST) l'implementazione fornita gestisce solo il caso di arecv(ANY) e non arecv(mittente)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
si, è possibile: &lt;br /&gt;
&lt;br /&gt;
Implementare asend e arecv date bsend e brecv&lt;br /&gt;
&lt;br /&gt;
asend(pid_t dst, msg_type msg){&lt;br /&gt;
    bsend (&amp;lt;dst, msg&amp;gt;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
arecv(*){&lt;br /&gt;
  do {&lt;br /&gt;
    &amp;lt;dst, msg&amp;gt; = brecv(*);&lt;br /&gt;
  } while (dst != getpid())&lt;br /&gt;
  return msg;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
propongo ([[User:LiberaL|LiberaL]] 13:11, 27 May 2023 (CEST)) quindi questa implementazione con gestione arecv da mittente specificato (sempre da controllare)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
//il messaggio mandato è la tripla &amp;lt;destinatario, mittente, messaggio&amp;gt;&lt;br /&gt;
&lt;br /&gt;
asend(pid_t dst, msg_type msg){&lt;br /&gt;
    bsend (&amp;lt;dst, getpid(), msg&amp;gt;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Queue of &amp;lt;pid_t, msg_type&amp;gt; db; //nota: salvo qui solo se il messaggio è per me, quindi dest non mi serve&lt;br /&gt;
arecv(pid_t sender) {&lt;br /&gt;
&lt;br /&gt;
  //devo controllare se nella coda ho già ricevuto il messaggio da quel mittente, ovvero mentre aspettavo un messaggio da qualcun'altro&lt;br /&gt;
  //db.get(sender) cerca una tripla il cui mittente è sender&lt;br /&gt;
  //se trova il messaggio lo rimuove anche dal db.&lt;br /&gt;
  //db.get(ANY) ritorna (ed elimina da db) il primo che trova (FIFO), e if(db.isEmpty()) return NULL;&lt;br /&gt;
&lt;br /&gt;
  if( ( &amp;lt;mit, msg&amp;gt; = db.get(sender) ) != NULL ) //se lo trova&lt;br /&gt;
    return msg;&lt;br /&gt;
  bool message_for_me;&lt;br /&gt;
  do {&lt;br /&gt;
    &amp;lt;dst, mit, msg&amp;gt; = brecv(*);                 //ricevo&lt;br /&gt;
    message_for_me = (dst == getpid());         //il messaggio è per me?&lt;br /&gt;
    if( message_for_me ) {&lt;br /&gt;
      if ( mit == sender || sender == ANY )     //se devo ritornare il messaggio&lt;br /&gt;
        break;     //esci dal while&lt;br /&gt;
      else                                      //se devo salvarlo (sender specificato e messaggio per me)&lt;br /&gt;
        //devo mettere in db i messaggi di altri mittenti, ricevuti quando ne aspettavo uno da un mittente specificato&lt;br /&gt;
        db.add(&amp;lt;mit, msg&amp;gt;);&lt;br /&gt;
    }&lt;br /&gt;
  } while (!message_for_me)&lt;br /&gt;
  return msg;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Esame 19/06/2017 ==&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2017.06.19.tot.pdf 2017.06.19.tot.pdf]&lt;br /&gt;
=== Esercizio c.1 (da controllare)===&lt;br /&gt;
&lt;br /&gt;
* Mi sembra che ci sia un errore per il giodice, potrebbe succedere in un caso che il wait non si risvegli mai [[User:Flecart|Flecart]] ([[User talk:Flecart|talk]]) 15:38, 19 January 2023 (CET)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define NATLETI n&lt;br /&gt;
&lt;br /&gt;
condition ok2lancia[NATLETI];&lt;br /&gt;
condition ok2giudice;&lt;br /&gt;
&lt;br /&gt;
int counter[NATLETI];&lt;br /&gt;
int ultimo_tiro;&lt;br /&gt;
float registro[NATLETI][3];&lt;br /&gt;
&lt;br /&gt;
Procedure entry: boolean pronto(int i)&lt;br /&gt;
{&lt;br /&gt;
    if(!(i == 0 &amp;amp;&amp;amp; counter[i] == 0)) // se è il primo lancio non devo metterlo in wait&lt;br /&gt;
        ok2lancia[i].wait()&lt;br /&gt;
    if(counter[i] &amp;lt; 3)&lt;br /&gt;
        return true;&lt;br /&gt;
    else&lt;br /&gt;
        return false;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: void lanciato (int i)&lt;br /&gt;
{&lt;br /&gt;
    counter[i]++;&lt;br /&gt;
    ultimo_tiro = i;&lt;br /&gt;
    ok2giudice.signal();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: int lanciofatto()&lt;br /&gt;
{&lt;br /&gt;
    ok2giudice.wait()&lt;br /&gt;
    if(ultimo_tiro == NATLETI-1 &amp;amp;&amp;amp; counter[0] == 3)&lt;br /&gt;
        return -1;  // devo invalidare la condizione per uscire dal while, quindi se nessuno deve più lanciare ritorno -1&lt;br /&gt;
    else&lt;br /&gt;
        return ultimo_tiro;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: void registraechiama(int i, float m)&lt;br /&gt;
{&lt;br /&gt;
    registro[i][counter[i]-1] = m; // il secondo indice indica l'iesimo lancio -1 (perchè iniziamo a contare da zero)&lt;br /&gt;
    if(i == NATLETI-1) // se ha appena tirato l'ultimo atleta non posso dare il via a NATLETI (perchè non esiste), quindi faccio ricominciare il giro&lt;br /&gt;
        ok2lancia[0].signal();&lt;br /&gt;
    else&lt;br /&gt;
        ok2lancia[i+1].signal();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: int classifica()&lt;br /&gt;
{&lt;br /&gt;
    int best[NATLETI];&lt;br /&gt;
    for(int i = 0; i &amp;lt; NATLETI; i++)&lt;br /&gt;
    {&lt;br /&gt;
        for(int j = 0; j &amp;lt; 3; j++)&lt;br /&gt;
        {&lt;br /&gt;
            if(registro[i][j] &amp;gt; best[i])&lt;br /&gt;
                best[i] = registro[i][j];&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    best.sort_in_descending_order(); // supponiamo nel nostro pseudolinguaggio esista una funzione di ordinamento qualunque&lt;br /&gt;
    return best;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Esame 29/05/2017 ==&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2017.05.29.tot.pdf 2017.05.29.tot.pdf]&lt;br /&gt;
=== Esercizio c.1 ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
condition okpartita&lt;br /&gt;
condition ok2chiama&lt;br /&gt;
condition ok2punteggio&lt;br /&gt;
condition ok2run[2][MAX]&lt;br /&gt;
int numpronti&lt;br /&gt;
int punteggio[2]&lt;br /&gt;
boolean partita=false&lt;br /&gt;
boolean partitafinita=false&lt;br /&gt;
chiamati = []&lt;br /&gt;
contabandiera[2]&lt;br /&gt;
int winner&lt;br /&gt;
&lt;br /&gt;
entry nuovapartita():&lt;br /&gt;
{&lt;br /&gt;
    punteggio[A] = punteggio[B] = 0;&lt;br /&gt;
    numpronti = 0;&lt;br /&gt;
    partita=true;&lt;br /&gt;
    okpartita.signal()&lt;br /&gt;
    chiamati = [];&lt;br /&gt;
}&lt;br /&gt;
entry chiama(l):&lt;br /&gt;
{&lt;br /&gt;
    if (numpronti&amp;lt;2*MAX)&lt;br /&gt;
    {&lt;br /&gt;
        ok2chiama.wait();&lt;br /&gt;
    }&lt;br /&gt;
    chiamati = l;&lt;br /&gt;
    contabandiera[A] = contabandiera[B] = 0&lt;br /&gt;
    winner = -1;&lt;br /&gt;
    for (s in n)&lt;br /&gt;
    {&lt;br /&gt;
        ok2run[A][s].signal();&lt;br /&gt;
        ok2run[B][s].signal()&lt;br /&gt;
    }&lt;br /&gt;
    ok2punteggio.wait();&lt;br /&gt;
    punteggio[winner++]&lt;br /&gt;
    if (max(punteggio) == 10)&lt;br /&gt;
    {&lt;br /&gt;
        partitafinita = true;&lt;br /&gt;
        for (s in A,B)&lt;br /&gt;
        {&lt;br /&gt;
            for (n in range(MAX))&lt;br /&gt;
            {&lt;br /&gt;
                ok2run[s][n].signal();&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    return punteggio;&lt;br /&gt;
}&lt;br /&gt;
entry pronto(s, n):&lt;br /&gt;
{&lt;br /&gt;
    if (partitafinita) return 1;&lt;br /&gt;
    if (!partita)&lt;br /&gt;
    {&lt;br /&gt;
        okpartita.wait();&lt;br /&gt;
    }&lt;br /&gt;
    numpronti++;&lt;br /&gt;
    if (numpronti&amp;gt;=2*MAX)&lt;br /&gt;
    {&lt;br /&gt;
        ok2chiama.signal();&lt;br /&gt;
    }&lt;br /&gt;
    if (!(n in chiamati))&lt;br /&gt;
    {&lt;br /&gt;
        ok2run[s][n].wait();&lt;br /&gt;
    }&lt;br /&gt;
    numpronti--;&lt;br /&gt;
    return 0 if partita else 1;&lt;br /&gt;
}&lt;br /&gt;
allabandiera(s, n):&lt;br /&gt;
{&lt;br /&gt;
    contabandiera[s]++;&lt;br /&gt;
    if (winner == -1 &amp;amp;&amp;amp; contabandiera[s] == len(chiamati))&lt;br /&gt;
    {&lt;br /&gt;
        winner = s;&lt;br /&gt;
    }&lt;br /&gt;
    if (contabandiera[A] == len(chiamati) &amp;amp;&amp;amp; contabandiera[B] == len(chiamati))&lt;br /&gt;
    {&lt;br /&gt;
        ok2punteggio.signal();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
casi da discutere:    &lt;br /&gt;
se arrivano studenti a pronto prima che il prof dichiara nuovapartita succedono guai.&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>LiberaL</name></author>
	</entry>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=Prove_scritte_2017&amp;diff=3027</id>
		<title>Prove scritte 2017</title>
		<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php?title=Prove_scritte_2017&amp;diff=3027"/>
		<updated>2023-05-27T11:06:13Z</updated>

		<summary type="html">&lt;p&gt;LiberaL: /* Esercizio c.2 (da controllare) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Esame 11/09/2017 ==&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2017.09.11.tot.pdf 2017.09.11.tot.pdf]&lt;br /&gt;
=== Esercizio c.1 ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
monitor crossing&lt;br /&gt;
&lt;br /&gt;
ok2dir[4];     //NESW&lt;br /&gt;
bool busy = false;&lt;br /&gt;
&lt;br /&gt;
pe entra(int dir)&lt;br /&gt;
   if (busy)&lt;br /&gt;
      ok2dir[dir].wait();&lt;br /&gt;
   busy = true;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
pe esci(int dir)&lt;br /&gt;
   busy = false;&lt;br /&gt;
   ok2dir[(dir + 1) % 4].signal();&lt;br /&gt;
   if (!busy)&lt;br /&gt;
      ok2dir[(dir + 2) % 4].signal();&lt;br /&gt;
   if (!busy)&lt;br /&gt;
      ok2dir[(dir + 3) % 4].signal();&lt;br /&gt;
   if (!busy)&lt;br /&gt;
      ok2dir[(dir + 4) % 4].signal();  //dir&lt;br /&gt;
&lt;br /&gt;
//alternativa più compatta&lt;br /&gt;
pe esci(int dir)&lt;br /&gt;
   busy = false;&lt;br /&gt;
   for (i = 0; i &amp;lt; 4; i++)&lt;br /&gt;
   if (!busy)&lt;br /&gt;
      ok2dir[(dir + i + 1) % 4].signal();&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Soluzione proposta 2 ==== &lt;br /&gt;
Soluzione proposta da [https://t.me/LLibera LLibera] e corretta da  [https://so.v2.cs.unibo.it/wiki/index.php/User:Flecart Flecart]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
const int N_DIRECTION = 4;&lt;br /&gt;
&lt;br /&gt;
// assumo N = 0, E = 1, S = 2, W = 3, oppure shiftati ciclicamente, è equivalente&lt;br /&gt;
&lt;br /&gt;
monitor crossing {&lt;br /&gt;
	bool free;										//l'incrocio è libero?&lt;br /&gt;
	int num_waiting[N_DIRECTION];&lt;br /&gt;
	condition okToCross[N_DIRECTION];				//free == True&lt;br /&gt;
	&lt;br /&gt;
	crossing() {&lt;br /&gt;
		free = True;								//parto con l'incrocio libero&lt;br /&gt;
		for (int i = 0; i &amp;lt; N_DIRECTION; i++) {&lt;br /&gt;
			num_waiting[i] = 0;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	procedure entry enter(int direction) {&lt;br /&gt;
		if(!free) {									//se l'incrocio non è libero&lt;br /&gt;
			num_waiting[direction]++;&lt;br /&gt;
			okToCross[direction].wait();			//aspetto nella mia direzione&lt;br /&gt;
			num_waiting[direction]--;&lt;br /&gt;
		}&lt;br /&gt;
													//ora sono sicurə che sia libero&lt;br /&gt;
		free = False;								//quindi lo dichiaro occupato&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	procedure entry exit(int direction) {&lt;br /&gt;
													//non devo aspettare niente per liberare l'incrocio&lt;br /&gt;
		free = True;								//lo dichiaro libero&lt;br /&gt;
		&lt;br /&gt;
		for (int i = 0; i &amp;lt; N_DIRECTION; i++) {&lt;br /&gt;
			int curr_dir = (direction + i + 1) % N_DIRECTION;&lt;br /&gt;
			if (num_waiting[curr_dir] &amp;gt; 0) {&lt;br /&gt;
				okToCross[curr_dir].signal();&lt;br /&gt;
				break;	// l'onere di risvegliare gli altri è stato passato al nuovo processo risvegliato, quindi esco.&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.2 (da controllare) ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// server[] = array contenente il PID di tutti i server&lt;br /&gt;
&lt;br /&gt;
#define BROADCAST server[0]&lt;br /&gt;
&lt;br /&gt;
server[0]&lt;br /&gt;
{&lt;br /&gt;
    while(true)&lt;br /&gt;
    {&lt;br /&gt;
        &amp;lt;msg, sender&amp;gt; = arecv(*); // ricevo il messaggio&lt;br /&gt;
        if (sender == BROADCAST)&lt;br /&gt;
            print(msg); // se il messaggio l'ho ricevuto da me stesso allora lo stampo&lt;br /&gt;
        else&lt;br /&gt;
            asend(*, &amp;lt;msg, getpid()&amp;gt;); // se il messaggio l'ho ricevuto da un client o da un altro server lo inoltro a tutti i server (compreso me stesso)&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
server[x] // x = 1...N-1&lt;br /&gt;
{&lt;br /&gt;
    while(true)&lt;br /&gt;
    {&lt;br /&gt;
        &amp;lt;msg, sender&amp;gt; = arecv(*); // ricevo il messaggio&lt;br /&gt;
        if (sender == BROADCAST)&lt;br /&gt;
            print(msg); // se il messaggio l'ho ricevuto dal server[0] allora lo stampo&lt;br /&gt;
        else&lt;br /&gt;
            asend(BROADCAST, &amp;lt;msg, getpid()&amp;gt;) // se il messaggio l'ho ricevuto da un client lo inoltro al server[0]&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Soluzione proposta 2 ====&lt;br /&gt;
&lt;br /&gt;
Soluzione proposta da [https://so.v2.cs.unibo.it/wiki/index.php/User:Flecart Flecart]&lt;br /&gt;
Soluzione corretta da [https://so.v2.cs.unibo.it/wiki/index.php/User:Gio Flecart friend]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
process server_0 {&lt;br /&gt;
&lt;br /&gt;
        while (true) {&lt;br /&gt;
                &amp;lt;msg, sender&amp;gt; = arecv(ANY);&lt;br /&gt;
                for (int i = 1 ; i &amp;lt; N; i++) {&lt;br /&gt;
                        asend(&amp;lt;msg, 0&amp;gt;, server[i]);&lt;br /&gt;
                        while(true){&lt;br /&gt;
                          msg = arecv(server[i]); // così so che tutti abbiano stampato.&lt;br /&gt;
                          if(msg==ACK)&lt;br /&gt;
                            break&lt;br /&gt;
                          asend(msg,server[0]);&lt;br /&gt;
                        }&lt;br /&gt;
                }&lt;br /&gt;
                print(msg);&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
process server_[i=1 to N - 1] {&lt;br /&gt;
        while (true) {&lt;br /&gt;
                &amp;lt;msg, sender&amp;gt; = arecv(ANY);&lt;br /&gt;
                if (sender == 0) {&lt;br /&gt;
                        print(msg);&lt;br /&gt;
                        asend(ACK, server[0]);&lt;br /&gt;
                } else {&lt;br /&gt;
                        asend(&amp;lt;msg, i&amp;gt;, server[0]);&lt;br /&gt;
                }&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Esame 17/07/2017 ==&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2017.07.17.tot.pdf 2017.07.17.tot.pdf]&lt;br /&gt;
=== Esercizio c.1 ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
monitor conf {&lt;br /&gt;
        condition finished;&lt;br /&gt;
        condition ready2present[max];&lt;br /&gt;
        bool arrived[max] = false;&lt;br /&gt;
        bool giachiamato[max] = false;&lt;br /&gt;
&lt;br /&gt;
        entry chiama(chiamato){&lt;br /&gt;
        if(arrived[chiamato] == true)&lt;br /&gt;
                ready2present[chiamato].signal;&lt;br /&gt;
                finished.wait;&lt;br /&gt;
                return true;&lt;br /&gt;
        else&lt;br /&gt;
                giachiamato[chiamato]= true&lt;br /&gt;
                return false;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        entry arrivato(nome){&lt;br /&gt;
                if(giachiamato[nome] == true)&lt;br /&gt;
                        return  false;&lt;br /&gt;
&lt;br /&gt;
                arrived[nome] = true;&lt;br /&gt;
                ok2present[nome].wait;&lt;br /&gt;
                return true;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        entry finepresentazione(nome){&lt;br /&gt;
                finished.signal;&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.2 (da controllare) ===&lt;br /&gt;
controllata da [[User:LiberaL|LiberaL]] 14:26, 26 May 2023 (CEST) l'implementazione fornita gestisce solo il caso di arecv(ANY) e non arecv(mittente)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
si, è possibile: &lt;br /&gt;
&lt;br /&gt;
Implementare asend e arecv date bsend e brecv&lt;br /&gt;
&lt;br /&gt;
asend(pid_t dst, msg_type msg){&lt;br /&gt;
    bsend (&amp;lt;dst, msg&amp;gt;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
arecv(*){&lt;br /&gt;
  do {&lt;br /&gt;
    &amp;lt;dst, msg&amp;gt; = brecv(*);&lt;br /&gt;
  } while (dst != getpid())&lt;br /&gt;
  return msg;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
propongo (13:04, 27 May 2023 (CEST)) quindi questa implementazione con gestione arecv da mittente specificato (sempre da controllare)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
//il messaggio mandato è la tripla &amp;lt;destinatario, mittente, messaggio&amp;gt;&lt;br /&gt;
&lt;br /&gt;
asend(pid_t dst, msg_type msg){&lt;br /&gt;
    bsend (&amp;lt;dst, getpid(), msg&amp;gt;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Queue of &amp;lt;pid_t, msg_type&amp;gt; db; //nota: salvo qui solo se il messaggio è per me, quindi dest non mi serve&lt;br /&gt;
arecv(pid_t sender) {&lt;br /&gt;
&lt;br /&gt;
  //devo controllare se nella coda ho già ricevuto il messaggio da quel mittente, ovvero mentre aspettavo un messaggio da qualcun'altro&lt;br /&gt;
  //db.get(sender) cerca una tripla il cui mittente è sender&lt;br /&gt;
  //se trova il messaggio lo rimuove anche dal db.&lt;br /&gt;
  //db.get(ANY) ritorna (ed elimina da db) il primo che trova (FIFO), e if(db.isEmpty()) return NULL;&lt;br /&gt;
&lt;br /&gt;
  if( ( &amp;lt;mit, msg&amp;gt; = db.get(sender) ) != NULL ) //se lo trova&lt;br /&gt;
    return msg;&lt;br /&gt;
  bool message_for_me;&lt;br /&gt;
  do {&lt;br /&gt;
    &amp;lt;dst, mit, msg&amp;gt; = brecv(*);                 //ricevo&lt;br /&gt;
    message_for_me = (dst == getpid());         //il messaggio è per me?&lt;br /&gt;
    if( message_for_me ) {&lt;br /&gt;
      if ( mit == sender || sender == ANY )     //se devo ritornare il messaggio&lt;br /&gt;
        break;     //esci dal while&lt;br /&gt;
      else                                      //se devo salvarlo (sender specificato e messaggio per me)&lt;br /&gt;
        //devo mettere in db i messaggi di altri mittenti, ricevuti quando ne aspettavo uno da un mittente specificato&lt;br /&gt;
        db.add(&amp;lt;mit, msg&amp;gt;);&lt;br /&gt;
    }&lt;br /&gt;
  } while (!message_for_me)&lt;br /&gt;
  return msg;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Esame 19/06/2017 ==&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2017.06.19.tot.pdf 2017.06.19.tot.pdf]&lt;br /&gt;
=== Esercizio c.1 (da controllare)===&lt;br /&gt;
&lt;br /&gt;
* Mi sembra che ci sia un errore per il giodice, potrebbe succedere in un caso che il wait non si risvegli mai [[User:Flecart|Flecart]] ([[User talk:Flecart|talk]]) 15:38, 19 January 2023 (CET)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define NATLETI n&lt;br /&gt;
&lt;br /&gt;
condition ok2lancia[NATLETI];&lt;br /&gt;
condition ok2giudice;&lt;br /&gt;
&lt;br /&gt;
int counter[NATLETI];&lt;br /&gt;
int ultimo_tiro;&lt;br /&gt;
float registro[NATLETI][3];&lt;br /&gt;
&lt;br /&gt;
Procedure entry: boolean pronto(int i)&lt;br /&gt;
{&lt;br /&gt;
    if(!(i == 0 &amp;amp;&amp;amp; counter[i] == 0)) // se è il primo lancio non devo metterlo in wait&lt;br /&gt;
        ok2lancia[i].wait()&lt;br /&gt;
    if(counter[i] &amp;lt; 3)&lt;br /&gt;
        return true;&lt;br /&gt;
    else&lt;br /&gt;
        return false;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: void lanciato (int i)&lt;br /&gt;
{&lt;br /&gt;
    counter[i]++;&lt;br /&gt;
    ultimo_tiro = i;&lt;br /&gt;
    ok2giudice.signal();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: int lanciofatto()&lt;br /&gt;
{&lt;br /&gt;
    ok2giudice.wait()&lt;br /&gt;
    if(ultimo_tiro == NATLETI-1 &amp;amp;&amp;amp; counter[0] == 3)&lt;br /&gt;
        return -1;  // devo invalidare la condizione per uscire dal while, quindi se nessuno deve più lanciare ritorno -1&lt;br /&gt;
    else&lt;br /&gt;
        return ultimo_tiro;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: void registraechiama(int i, float m)&lt;br /&gt;
{&lt;br /&gt;
    registro[i][counter[i]-1] = m; // il secondo indice indica l'iesimo lancio -1 (perchè iniziamo a contare da zero)&lt;br /&gt;
    if(i == NATLETI-1) // se ha appena tirato l'ultimo atleta non posso dare il via a NATLETI (perchè non esiste), quindi faccio ricominciare il giro&lt;br /&gt;
        ok2lancia[0].signal();&lt;br /&gt;
    else&lt;br /&gt;
        ok2lancia[i+1].signal();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: int classifica()&lt;br /&gt;
{&lt;br /&gt;
    int best[NATLETI];&lt;br /&gt;
    for(int i = 0; i &amp;lt; NATLETI; i++)&lt;br /&gt;
    {&lt;br /&gt;
        for(int j = 0; j &amp;lt; 3; j++)&lt;br /&gt;
        {&lt;br /&gt;
            if(registro[i][j] &amp;gt; best[i])&lt;br /&gt;
                best[i] = registro[i][j];&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    best.sort_in_descending_order(); // supponiamo nel nostro pseudolinguaggio esista una funzione di ordinamento qualunque&lt;br /&gt;
    return best;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Esame 29/05/2017 ==&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2017.05.29.tot.pdf 2017.05.29.tot.pdf]&lt;br /&gt;
=== Esercizio c.1 ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
condition okpartita&lt;br /&gt;
condition ok2chiama&lt;br /&gt;
condition ok2punteggio&lt;br /&gt;
condition ok2run[2][MAX]&lt;br /&gt;
int numpronti&lt;br /&gt;
int punteggio[2]&lt;br /&gt;
boolean partita=false&lt;br /&gt;
boolean partitafinita=false&lt;br /&gt;
chiamati = []&lt;br /&gt;
contabandiera[2]&lt;br /&gt;
int winner&lt;br /&gt;
&lt;br /&gt;
entry nuovapartita():&lt;br /&gt;
{&lt;br /&gt;
    punteggio[A] = punteggio[B] = 0;&lt;br /&gt;
    numpronti = 0;&lt;br /&gt;
    partita=true;&lt;br /&gt;
    okpartita.signal()&lt;br /&gt;
    chiamati = [];&lt;br /&gt;
}&lt;br /&gt;
entry chiama(l):&lt;br /&gt;
{&lt;br /&gt;
    if (numpronti&amp;lt;2*MAX)&lt;br /&gt;
    {&lt;br /&gt;
        ok2chiama.wait();&lt;br /&gt;
    }&lt;br /&gt;
    chiamati = l;&lt;br /&gt;
    contabandiera[A] = contabandiera[B] = 0&lt;br /&gt;
    winner = -1;&lt;br /&gt;
    for (s in n)&lt;br /&gt;
    {&lt;br /&gt;
        ok2run[A][s].signal();&lt;br /&gt;
        ok2run[B][s].signal()&lt;br /&gt;
    }&lt;br /&gt;
    ok2punteggio.wait();&lt;br /&gt;
    punteggio[winner++]&lt;br /&gt;
    if (max(punteggio) == 10)&lt;br /&gt;
    {&lt;br /&gt;
        partitafinita = true;&lt;br /&gt;
        for (s in A,B)&lt;br /&gt;
        {&lt;br /&gt;
            for (n in range(MAX))&lt;br /&gt;
            {&lt;br /&gt;
                ok2run[s][n].signal();&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    return punteggio;&lt;br /&gt;
}&lt;br /&gt;
entry pronto(s, n):&lt;br /&gt;
{&lt;br /&gt;
    if (partitafinita) return 1;&lt;br /&gt;
    if (!partita)&lt;br /&gt;
    {&lt;br /&gt;
        okpartita.wait();&lt;br /&gt;
    }&lt;br /&gt;
    numpronti++;&lt;br /&gt;
    if (numpronti&amp;gt;=2*MAX)&lt;br /&gt;
    {&lt;br /&gt;
        ok2chiama.signal();&lt;br /&gt;
    }&lt;br /&gt;
    if (!(n in chiamati))&lt;br /&gt;
    {&lt;br /&gt;
        ok2run[s][n].wait();&lt;br /&gt;
    }&lt;br /&gt;
    numpronti--;&lt;br /&gt;
    return 0 if partita else 1;&lt;br /&gt;
}&lt;br /&gt;
allabandiera(s, n):&lt;br /&gt;
{&lt;br /&gt;
    contabandiera[s]++;&lt;br /&gt;
    if (winner == -1 &amp;amp;&amp;amp; contabandiera[s] == len(chiamati))&lt;br /&gt;
    {&lt;br /&gt;
        winner = s;&lt;br /&gt;
    }&lt;br /&gt;
    if (contabandiera[A] == len(chiamati) &amp;amp;&amp;amp; contabandiera[B] == len(chiamati))&lt;br /&gt;
    {&lt;br /&gt;
        ok2punteggio.signal();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
casi da discutere:    &lt;br /&gt;
se arrivano studenti a pronto prima che il prof dichiara nuovapartita succedono guai.&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>LiberaL</name></author>
	</entry>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=Prove_scritte_2017&amp;diff=3026</id>
		<title>Prove scritte 2017</title>
		<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php?title=Prove_scritte_2017&amp;diff=3026"/>
		<updated>2023-05-27T11:05:02Z</updated>

		<summary type="html">&lt;p&gt;LiberaL: /* Esercizio c.2 (da controllare) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Esame 11/09/2017 ==&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2017.09.11.tot.pdf 2017.09.11.tot.pdf]&lt;br /&gt;
=== Esercizio c.1 ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
monitor crossing&lt;br /&gt;
&lt;br /&gt;
ok2dir[4];     //NESW&lt;br /&gt;
bool busy = false;&lt;br /&gt;
&lt;br /&gt;
pe entra(int dir)&lt;br /&gt;
   if (busy)&lt;br /&gt;
      ok2dir[dir].wait();&lt;br /&gt;
   busy = true;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
pe esci(int dir)&lt;br /&gt;
   busy = false;&lt;br /&gt;
   ok2dir[(dir + 1) % 4].signal();&lt;br /&gt;
   if (!busy)&lt;br /&gt;
      ok2dir[(dir + 2) % 4].signal();&lt;br /&gt;
   if (!busy)&lt;br /&gt;
      ok2dir[(dir + 3) % 4].signal();&lt;br /&gt;
   if (!busy)&lt;br /&gt;
      ok2dir[(dir + 4) % 4].signal();  //dir&lt;br /&gt;
&lt;br /&gt;
//alternativa più compatta&lt;br /&gt;
pe esci(int dir)&lt;br /&gt;
   busy = false;&lt;br /&gt;
   for (i = 0; i &amp;lt; 4; i++)&lt;br /&gt;
   if (!busy)&lt;br /&gt;
      ok2dir[(dir + i + 1) % 4].signal();&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Soluzione proposta 2 ==== &lt;br /&gt;
Soluzione proposta da [https://t.me/LLibera LLibera] e corretta da  [https://so.v2.cs.unibo.it/wiki/index.php/User:Flecart Flecart]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
const int N_DIRECTION = 4;&lt;br /&gt;
&lt;br /&gt;
// assumo N = 0, E = 1, S = 2, W = 3, oppure shiftati ciclicamente, è equivalente&lt;br /&gt;
&lt;br /&gt;
monitor crossing {&lt;br /&gt;
	bool free;										//l'incrocio è libero?&lt;br /&gt;
	int num_waiting[N_DIRECTION];&lt;br /&gt;
	condition okToCross[N_DIRECTION];				//free == True&lt;br /&gt;
	&lt;br /&gt;
	crossing() {&lt;br /&gt;
		free = True;								//parto con l'incrocio libero&lt;br /&gt;
		for (int i = 0; i &amp;lt; N_DIRECTION; i++) {&lt;br /&gt;
			num_waiting[i] = 0;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	procedure entry enter(int direction) {&lt;br /&gt;
		if(!free) {									//se l'incrocio non è libero&lt;br /&gt;
			num_waiting[direction]++;&lt;br /&gt;
			okToCross[direction].wait();			//aspetto nella mia direzione&lt;br /&gt;
			num_waiting[direction]--;&lt;br /&gt;
		}&lt;br /&gt;
													//ora sono sicurə che sia libero&lt;br /&gt;
		free = False;								//quindi lo dichiaro occupato&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	procedure entry exit(int direction) {&lt;br /&gt;
													//non devo aspettare niente per liberare l'incrocio&lt;br /&gt;
		free = True;								//lo dichiaro libero&lt;br /&gt;
		&lt;br /&gt;
		for (int i = 0; i &amp;lt; N_DIRECTION; i++) {&lt;br /&gt;
			int curr_dir = (direction + i + 1) % N_DIRECTION;&lt;br /&gt;
			if (num_waiting[curr_dir] &amp;gt; 0) {&lt;br /&gt;
				okToCross[curr_dir].signal();&lt;br /&gt;
				break;	// l'onere di risvegliare gli altri è stato passato al nuovo processo risvegliato, quindi esco.&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.2 (da controllare) ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// server[] = array contenente il PID di tutti i server&lt;br /&gt;
&lt;br /&gt;
#define BROADCAST server[0]&lt;br /&gt;
&lt;br /&gt;
server[0]&lt;br /&gt;
{&lt;br /&gt;
    while(true)&lt;br /&gt;
    {&lt;br /&gt;
        &amp;lt;msg, sender&amp;gt; = arecv(*); // ricevo il messaggio&lt;br /&gt;
        if (sender == BROADCAST)&lt;br /&gt;
            print(msg); // se il messaggio l'ho ricevuto da me stesso allora lo stampo&lt;br /&gt;
        else&lt;br /&gt;
            asend(*, &amp;lt;msg, getpid()&amp;gt;); // se il messaggio l'ho ricevuto da un client o da un altro server lo inoltro a tutti i server (compreso me stesso)&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
server[x] // x = 1...N-1&lt;br /&gt;
{&lt;br /&gt;
    while(true)&lt;br /&gt;
    {&lt;br /&gt;
        &amp;lt;msg, sender&amp;gt; = arecv(*); // ricevo il messaggio&lt;br /&gt;
        if (sender == BROADCAST)&lt;br /&gt;
            print(msg); // se il messaggio l'ho ricevuto dal server[0] allora lo stampo&lt;br /&gt;
        else&lt;br /&gt;
            asend(BROADCAST, &amp;lt;msg, getpid()&amp;gt;) // se il messaggio l'ho ricevuto da un client lo inoltro al server[0]&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Soluzione proposta 2 ====&lt;br /&gt;
&lt;br /&gt;
Soluzione proposta da [https://so.v2.cs.unibo.it/wiki/index.php/User:Flecart Flecart]&lt;br /&gt;
Soluzione corretta da [https://so.v2.cs.unibo.it/wiki/index.php/User:Gio Flecart friend]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
process server_0 {&lt;br /&gt;
&lt;br /&gt;
        while (true) {&lt;br /&gt;
                &amp;lt;msg, sender&amp;gt; = arecv(ANY);&lt;br /&gt;
                for (int i = 1 ; i &amp;lt; N; i++) {&lt;br /&gt;
                        asend(&amp;lt;msg, 0&amp;gt;, server[i]);&lt;br /&gt;
                        while(true){&lt;br /&gt;
                          msg = arecv(server[i]); // così so che tutti abbiano stampato.&lt;br /&gt;
                          if(msg==ACK)&lt;br /&gt;
                            break&lt;br /&gt;
                          asend(msg,server[0]);&lt;br /&gt;
                        }&lt;br /&gt;
                }&lt;br /&gt;
                print(msg);&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
process server_[i=1 to N - 1] {&lt;br /&gt;
        while (true) {&lt;br /&gt;
                &amp;lt;msg, sender&amp;gt; = arecv(ANY);&lt;br /&gt;
                if (sender == 0) {&lt;br /&gt;
                        print(msg);&lt;br /&gt;
                        asend(ACK, server[0]);&lt;br /&gt;
                } else {&lt;br /&gt;
                        asend(&amp;lt;msg, i&amp;gt;, server[0]);&lt;br /&gt;
                }&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Esame 17/07/2017 ==&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2017.07.17.tot.pdf 2017.07.17.tot.pdf]&lt;br /&gt;
=== Esercizio c.1 ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
monitor conf {&lt;br /&gt;
        condition finished;&lt;br /&gt;
        condition ready2present[max];&lt;br /&gt;
        bool arrived[max] = false;&lt;br /&gt;
        bool giachiamato[max] = false;&lt;br /&gt;
&lt;br /&gt;
        entry chiama(chiamato){&lt;br /&gt;
        if(arrived[chiamato] == true)&lt;br /&gt;
                ready2present[chiamato].signal;&lt;br /&gt;
                finished.wait;&lt;br /&gt;
                return true;&lt;br /&gt;
        else&lt;br /&gt;
                giachiamato[chiamato]= true&lt;br /&gt;
                return false;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        entry arrivato(nome){&lt;br /&gt;
                if(giachiamato[nome] == true)&lt;br /&gt;
                        return  false;&lt;br /&gt;
&lt;br /&gt;
                arrived[nome] = true;&lt;br /&gt;
                ok2present[nome].wait;&lt;br /&gt;
                return true;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        entry finepresentazione(nome){&lt;br /&gt;
                finished.signal;&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.2 (da controllare) ===&lt;br /&gt;
controllata da [[User:LiberaL|LiberaL]] 14:26, 26 May 2023 (CEST) l'implementazione fornita gestisce solo il caso di arecv(ANY) e non arecv(mittente)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
si, è possibile: &lt;br /&gt;
&lt;br /&gt;
Implementare asend e arecv date bsend e brecv&lt;br /&gt;
&lt;br /&gt;
asend(pid_t dst, msg_type msg){&lt;br /&gt;
    bsend (&amp;lt;dst, msg&amp;gt;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
arecv(*){&lt;br /&gt;
  do {&lt;br /&gt;
    &amp;lt;dst, msg&amp;gt; = brecv(*);&lt;br /&gt;
  } while (dst != getpid())&lt;br /&gt;
  return msg;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
propongo (13:04, 27 May 2023 (CEST)) quindi questa implementazione con gestione arecv da mittente specificato (sempre da controllare)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
//il messaggio mandato è la tripla &amp;lt;destinatario, mittente, messaggio&amp;gt;&lt;br /&gt;
&lt;br /&gt;
asend(pid_t dst, msg_type msg){&lt;br /&gt;
    bsend (&amp;lt;dst, getpid(), msg&amp;gt;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Queue of &amp;lt;pid_t, msg_type&amp;gt; db; //nota: salvo qui solo se il messaggio è per me quindi dest non mi serve sarebbe sempre == getpid()&lt;br /&gt;
arecv(pid_t sender) {&lt;br /&gt;
&lt;br /&gt;
  //devo controllare se nella coda ho già ricevuto il messaggio da quel mittente, ovvero mentre aspettavo un messaggio da qualcun'altro&lt;br /&gt;
  //db.get(sender) cerca una tripla il cui mittente è sender&lt;br /&gt;
  //se trova il messaggio lo rimuove anche dal db.&lt;br /&gt;
  //db.get(ANY) ritorna (ed elimina da db) il primo che trova (FIFO), e if(db.isEmpty()) return NULL;&lt;br /&gt;
&lt;br /&gt;
  if( ( &amp;lt;mit, msg&amp;gt; = db.get(sender) ) != NULL ) //se lo trova&lt;br /&gt;
    return msg;&lt;br /&gt;
  bool message_for_me;&lt;br /&gt;
  do {&lt;br /&gt;
    &amp;lt;dst, mit, msg&amp;gt; = brecv(*);                 //ricevo&lt;br /&gt;
    message_for_me = (dst == getpid());         //il messaggio è per me?&lt;br /&gt;
    if( message_for_me ) {&lt;br /&gt;
      if ( mit == sender || sender == ANY )     //se devo ritornare il messaggio&lt;br /&gt;
        break;     //esci dal while&lt;br /&gt;
      else                                      //se devo salvarlo (sender specificato e messaggio per me)&lt;br /&gt;
        //devo mettere in db i messaggi di altri mittenti, ricevuti quando ne aspettavo uno da un mittente specificato&lt;br /&gt;
        db.add(&amp;lt;mit, msg&amp;gt;);&lt;br /&gt;
    }&lt;br /&gt;
  } while (!message_for_me)&lt;br /&gt;
  return msg;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Esame 19/06/2017 ==&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2017.06.19.tot.pdf 2017.06.19.tot.pdf]&lt;br /&gt;
=== Esercizio c.1 (da controllare)===&lt;br /&gt;
&lt;br /&gt;
* Mi sembra che ci sia un errore per il giodice, potrebbe succedere in un caso che il wait non si risvegli mai [[User:Flecart|Flecart]] ([[User talk:Flecart|talk]]) 15:38, 19 January 2023 (CET)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define NATLETI n&lt;br /&gt;
&lt;br /&gt;
condition ok2lancia[NATLETI];&lt;br /&gt;
condition ok2giudice;&lt;br /&gt;
&lt;br /&gt;
int counter[NATLETI];&lt;br /&gt;
int ultimo_tiro;&lt;br /&gt;
float registro[NATLETI][3];&lt;br /&gt;
&lt;br /&gt;
Procedure entry: boolean pronto(int i)&lt;br /&gt;
{&lt;br /&gt;
    if(!(i == 0 &amp;amp;&amp;amp; counter[i] == 0)) // se è il primo lancio non devo metterlo in wait&lt;br /&gt;
        ok2lancia[i].wait()&lt;br /&gt;
    if(counter[i] &amp;lt; 3)&lt;br /&gt;
        return true;&lt;br /&gt;
    else&lt;br /&gt;
        return false;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: void lanciato (int i)&lt;br /&gt;
{&lt;br /&gt;
    counter[i]++;&lt;br /&gt;
    ultimo_tiro = i;&lt;br /&gt;
    ok2giudice.signal();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: int lanciofatto()&lt;br /&gt;
{&lt;br /&gt;
    ok2giudice.wait()&lt;br /&gt;
    if(ultimo_tiro == NATLETI-1 &amp;amp;&amp;amp; counter[0] == 3)&lt;br /&gt;
        return -1;  // devo invalidare la condizione per uscire dal while, quindi se nessuno deve più lanciare ritorno -1&lt;br /&gt;
    else&lt;br /&gt;
        return ultimo_tiro;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: void registraechiama(int i, float m)&lt;br /&gt;
{&lt;br /&gt;
    registro[i][counter[i]-1] = m; // il secondo indice indica l'iesimo lancio -1 (perchè iniziamo a contare da zero)&lt;br /&gt;
    if(i == NATLETI-1) // se ha appena tirato l'ultimo atleta non posso dare il via a NATLETI (perchè non esiste), quindi faccio ricominciare il giro&lt;br /&gt;
        ok2lancia[0].signal();&lt;br /&gt;
    else&lt;br /&gt;
        ok2lancia[i+1].signal();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: int classifica()&lt;br /&gt;
{&lt;br /&gt;
    int best[NATLETI];&lt;br /&gt;
    for(int i = 0; i &amp;lt; NATLETI; i++)&lt;br /&gt;
    {&lt;br /&gt;
        for(int j = 0; j &amp;lt; 3; j++)&lt;br /&gt;
        {&lt;br /&gt;
            if(registro[i][j] &amp;gt; best[i])&lt;br /&gt;
                best[i] = registro[i][j];&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    best.sort_in_descending_order(); // supponiamo nel nostro pseudolinguaggio esista una funzione di ordinamento qualunque&lt;br /&gt;
    return best;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Esame 29/05/2017 ==&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2017.05.29.tot.pdf 2017.05.29.tot.pdf]&lt;br /&gt;
=== Esercizio c.1 ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
condition okpartita&lt;br /&gt;
condition ok2chiama&lt;br /&gt;
condition ok2punteggio&lt;br /&gt;
condition ok2run[2][MAX]&lt;br /&gt;
int numpronti&lt;br /&gt;
int punteggio[2]&lt;br /&gt;
boolean partita=false&lt;br /&gt;
boolean partitafinita=false&lt;br /&gt;
chiamati = []&lt;br /&gt;
contabandiera[2]&lt;br /&gt;
int winner&lt;br /&gt;
&lt;br /&gt;
entry nuovapartita():&lt;br /&gt;
{&lt;br /&gt;
    punteggio[A] = punteggio[B] = 0;&lt;br /&gt;
    numpronti = 0;&lt;br /&gt;
    partita=true;&lt;br /&gt;
    okpartita.signal()&lt;br /&gt;
    chiamati = [];&lt;br /&gt;
}&lt;br /&gt;
entry chiama(l):&lt;br /&gt;
{&lt;br /&gt;
    if (numpronti&amp;lt;2*MAX)&lt;br /&gt;
    {&lt;br /&gt;
        ok2chiama.wait();&lt;br /&gt;
    }&lt;br /&gt;
    chiamati = l;&lt;br /&gt;
    contabandiera[A] = contabandiera[B] = 0&lt;br /&gt;
    winner = -1;&lt;br /&gt;
    for (s in n)&lt;br /&gt;
    {&lt;br /&gt;
        ok2run[A][s].signal();&lt;br /&gt;
        ok2run[B][s].signal()&lt;br /&gt;
    }&lt;br /&gt;
    ok2punteggio.wait();&lt;br /&gt;
    punteggio[winner++]&lt;br /&gt;
    if (max(punteggio) == 10)&lt;br /&gt;
    {&lt;br /&gt;
        partitafinita = true;&lt;br /&gt;
        for (s in A,B)&lt;br /&gt;
        {&lt;br /&gt;
            for (n in range(MAX))&lt;br /&gt;
            {&lt;br /&gt;
                ok2run[s][n].signal();&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    return punteggio;&lt;br /&gt;
}&lt;br /&gt;
entry pronto(s, n):&lt;br /&gt;
{&lt;br /&gt;
    if (partitafinita) return 1;&lt;br /&gt;
    if (!partita)&lt;br /&gt;
    {&lt;br /&gt;
        okpartita.wait();&lt;br /&gt;
    }&lt;br /&gt;
    numpronti++;&lt;br /&gt;
    if (numpronti&amp;gt;=2*MAX)&lt;br /&gt;
    {&lt;br /&gt;
        ok2chiama.signal();&lt;br /&gt;
    }&lt;br /&gt;
    if (!(n in chiamati))&lt;br /&gt;
    {&lt;br /&gt;
        ok2run[s][n].wait();&lt;br /&gt;
    }&lt;br /&gt;
    numpronti--;&lt;br /&gt;
    return 0 if partita else 1;&lt;br /&gt;
}&lt;br /&gt;
allabandiera(s, n):&lt;br /&gt;
{&lt;br /&gt;
    contabandiera[s]++;&lt;br /&gt;
    if (winner == -1 &amp;amp;&amp;amp; contabandiera[s] == len(chiamati))&lt;br /&gt;
    {&lt;br /&gt;
        winner = s;&lt;br /&gt;
    }&lt;br /&gt;
    if (contabandiera[A] == len(chiamati) &amp;amp;&amp;amp; contabandiera[B] == len(chiamati))&lt;br /&gt;
    {&lt;br /&gt;
        ok2punteggio.signal();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
casi da discutere:    &lt;br /&gt;
se arrivano studenti a pronto prima che il prof dichiara nuovapartita succedono guai.&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>LiberaL</name></author>
	</entry>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=Prove_scritte_2017&amp;diff=3025</id>
		<title>Prove scritte 2017</title>
		<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php?title=Prove_scritte_2017&amp;diff=3025"/>
		<updated>2023-05-27T11:04:06Z</updated>

		<summary type="html">&lt;p&gt;LiberaL: /* Esercizio c.2 (da controllare) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Esame 11/09/2017 ==&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2017.09.11.tot.pdf 2017.09.11.tot.pdf]&lt;br /&gt;
=== Esercizio c.1 ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
monitor crossing&lt;br /&gt;
&lt;br /&gt;
ok2dir[4];     //NESW&lt;br /&gt;
bool busy = false;&lt;br /&gt;
&lt;br /&gt;
pe entra(int dir)&lt;br /&gt;
   if (busy)&lt;br /&gt;
      ok2dir[dir].wait();&lt;br /&gt;
   busy = true;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
pe esci(int dir)&lt;br /&gt;
   busy = false;&lt;br /&gt;
   ok2dir[(dir + 1) % 4].signal();&lt;br /&gt;
   if (!busy)&lt;br /&gt;
      ok2dir[(dir + 2) % 4].signal();&lt;br /&gt;
   if (!busy)&lt;br /&gt;
      ok2dir[(dir + 3) % 4].signal();&lt;br /&gt;
   if (!busy)&lt;br /&gt;
      ok2dir[(dir + 4) % 4].signal();  //dir&lt;br /&gt;
&lt;br /&gt;
//alternativa più compatta&lt;br /&gt;
pe esci(int dir)&lt;br /&gt;
   busy = false;&lt;br /&gt;
   for (i = 0; i &amp;lt; 4; i++)&lt;br /&gt;
   if (!busy)&lt;br /&gt;
      ok2dir[(dir + i + 1) % 4].signal();&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Soluzione proposta 2 ==== &lt;br /&gt;
Soluzione proposta da [https://t.me/LLibera LLibera] e corretta da  [https://so.v2.cs.unibo.it/wiki/index.php/User:Flecart Flecart]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
const int N_DIRECTION = 4;&lt;br /&gt;
&lt;br /&gt;
// assumo N = 0, E = 1, S = 2, W = 3, oppure shiftati ciclicamente, è equivalente&lt;br /&gt;
&lt;br /&gt;
monitor crossing {&lt;br /&gt;
	bool free;										//l'incrocio è libero?&lt;br /&gt;
	int num_waiting[N_DIRECTION];&lt;br /&gt;
	condition okToCross[N_DIRECTION];				//free == True&lt;br /&gt;
	&lt;br /&gt;
	crossing() {&lt;br /&gt;
		free = True;								//parto con l'incrocio libero&lt;br /&gt;
		for (int i = 0; i &amp;lt; N_DIRECTION; i++) {&lt;br /&gt;
			num_waiting[i] = 0;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	procedure entry enter(int direction) {&lt;br /&gt;
		if(!free) {									//se l'incrocio non è libero&lt;br /&gt;
			num_waiting[direction]++;&lt;br /&gt;
			okToCross[direction].wait();			//aspetto nella mia direzione&lt;br /&gt;
			num_waiting[direction]--;&lt;br /&gt;
		}&lt;br /&gt;
													//ora sono sicurə che sia libero&lt;br /&gt;
		free = False;								//quindi lo dichiaro occupato&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	procedure entry exit(int direction) {&lt;br /&gt;
													//non devo aspettare niente per liberare l'incrocio&lt;br /&gt;
		free = True;								//lo dichiaro libero&lt;br /&gt;
		&lt;br /&gt;
		for (int i = 0; i &amp;lt; N_DIRECTION; i++) {&lt;br /&gt;
			int curr_dir = (direction + i + 1) % N_DIRECTION;&lt;br /&gt;
			if (num_waiting[curr_dir] &amp;gt; 0) {&lt;br /&gt;
				okToCross[curr_dir].signal();&lt;br /&gt;
				break;	// l'onere di risvegliare gli altri è stato passato al nuovo processo risvegliato, quindi esco.&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.2 (da controllare) ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// server[] = array contenente il PID di tutti i server&lt;br /&gt;
&lt;br /&gt;
#define BROADCAST server[0]&lt;br /&gt;
&lt;br /&gt;
server[0]&lt;br /&gt;
{&lt;br /&gt;
    while(true)&lt;br /&gt;
    {&lt;br /&gt;
        &amp;lt;msg, sender&amp;gt; = arecv(*); // ricevo il messaggio&lt;br /&gt;
        if (sender == BROADCAST)&lt;br /&gt;
            print(msg); // se il messaggio l'ho ricevuto da me stesso allora lo stampo&lt;br /&gt;
        else&lt;br /&gt;
            asend(*, &amp;lt;msg, getpid()&amp;gt;); // se il messaggio l'ho ricevuto da un client o da un altro server lo inoltro a tutti i server (compreso me stesso)&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
server[x] // x = 1...N-1&lt;br /&gt;
{&lt;br /&gt;
    while(true)&lt;br /&gt;
    {&lt;br /&gt;
        &amp;lt;msg, sender&amp;gt; = arecv(*); // ricevo il messaggio&lt;br /&gt;
        if (sender == BROADCAST)&lt;br /&gt;
            print(msg); // se il messaggio l'ho ricevuto dal server[0] allora lo stampo&lt;br /&gt;
        else&lt;br /&gt;
            asend(BROADCAST, &amp;lt;msg, getpid()&amp;gt;) // se il messaggio l'ho ricevuto da un client lo inoltro al server[0]&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Soluzione proposta 2 ====&lt;br /&gt;
&lt;br /&gt;
Soluzione proposta da [https://so.v2.cs.unibo.it/wiki/index.php/User:Flecart Flecart]&lt;br /&gt;
Soluzione corretta da [https://so.v2.cs.unibo.it/wiki/index.php/User:Gio Flecart friend]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
process server_0 {&lt;br /&gt;
&lt;br /&gt;
        while (true) {&lt;br /&gt;
                &amp;lt;msg, sender&amp;gt; = arecv(ANY);&lt;br /&gt;
                for (int i = 1 ; i &amp;lt; N; i++) {&lt;br /&gt;
                        asend(&amp;lt;msg, 0&amp;gt;, server[i]);&lt;br /&gt;
                        while(true){&lt;br /&gt;
                          msg = arecv(server[i]); // così so che tutti abbiano stampato.&lt;br /&gt;
                          if(msg==ACK)&lt;br /&gt;
                            break&lt;br /&gt;
                          asend(msg,server[0]);&lt;br /&gt;
                        }&lt;br /&gt;
                }&lt;br /&gt;
                print(msg);&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
process server_[i=1 to N - 1] {&lt;br /&gt;
        while (true) {&lt;br /&gt;
                &amp;lt;msg, sender&amp;gt; = arecv(ANY);&lt;br /&gt;
                if (sender == 0) {&lt;br /&gt;
                        print(msg);&lt;br /&gt;
                        asend(ACK, server[0]);&lt;br /&gt;
                } else {&lt;br /&gt;
                        asend(&amp;lt;msg, i&amp;gt;, server[0]);&lt;br /&gt;
                }&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Esame 17/07/2017 ==&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2017.07.17.tot.pdf 2017.07.17.tot.pdf]&lt;br /&gt;
=== Esercizio c.1 ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
monitor conf {&lt;br /&gt;
        condition finished;&lt;br /&gt;
        condition ready2present[max];&lt;br /&gt;
        bool arrived[max] = false;&lt;br /&gt;
        bool giachiamato[max] = false;&lt;br /&gt;
&lt;br /&gt;
        entry chiama(chiamato){&lt;br /&gt;
        if(arrived[chiamato] == true)&lt;br /&gt;
                ready2present[chiamato].signal;&lt;br /&gt;
                finished.wait;&lt;br /&gt;
                return true;&lt;br /&gt;
        else&lt;br /&gt;
                giachiamato[chiamato]= true&lt;br /&gt;
                return false;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        entry arrivato(nome){&lt;br /&gt;
                if(giachiamato[nome] == true)&lt;br /&gt;
                        return  false;&lt;br /&gt;
&lt;br /&gt;
                arrived[nome] = true;&lt;br /&gt;
                ok2present[nome].wait;&lt;br /&gt;
                return true;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        entry finepresentazione(nome){&lt;br /&gt;
                finished.signal;&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.2 (da controllare) ===&lt;br /&gt;
controllata da [[User:LiberaL|LiberaL]] 14:26, 26 May 2023 (CEST) l'implementazione fornita gestisce solo il caso di arecv(ANY) e non arecv(mittente)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
si, è possibile: &lt;br /&gt;
&lt;br /&gt;
Implementare asend e arecv date bsend e brecv&lt;br /&gt;
&lt;br /&gt;
asend(pid_t dst, msg_type msg){&lt;br /&gt;
    bsend (&amp;lt;dst, msg&amp;gt;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
arecv(*){&lt;br /&gt;
  do {&lt;br /&gt;
    &amp;lt;dst, msg&amp;gt; = brecv(*);&lt;br /&gt;
  } while (dst != getpid())&lt;br /&gt;
  return msg;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
propongo (13:04, 27 May 2023 (CEST)) quindi questa implementazione con gestione arecv da mittente specificato (sempre da controllare)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
//il messaggio mandato è la tripla &amp;lt;destinatario, mittente, messaggio&amp;gt;&lt;br /&gt;
&lt;br /&gt;
asend(pid_t dst, msg_type msg){&lt;br /&gt;
    bsend (&amp;lt;dst, getpid(), msg&amp;gt;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Queue of &amp;lt;pid_t, msg_type&amp;gt; db; //nota: salvo qui solo se il messaggio è per me quindi dest non mi serve sarebbe sempre == getpid()&lt;br /&gt;
arecv(pid_t sender) {&lt;br /&gt;
&lt;br /&gt;
  //devo controllare se nella coda ho già ricevuto il messaggio da quel mittente, ovvero mentre aspettavo un messaggio da qualcun'altro&lt;br /&gt;
  //db.get(sender) cerca una tripla il cui mittente è sender&lt;br /&gt;
  //se trova il messaggio lo rimuove anche dal db.&lt;br /&gt;
  //db.get(ANY) ritorna (ed elimina da db) il primo che trova (FIFO), e if(db.isEmpty()) return NULL;&lt;br /&gt;
&lt;br /&gt;
  if( ( &amp;lt;mit, msg&amp;gt; = db.get(sender) ) != NULL ) //se lo trova&lt;br /&gt;
    return msg;&lt;br /&gt;
  bool message_for_me;&lt;br /&gt;
  do {&lt;br /&gt;
    &amp;lt;dst, mit, msg&amp;gt; = brecv(*);                 //ricevo&lt;br /&gt;
    message_for_me = (dst == getpid());    //il messaggio è per me?&lt;br /&gt;
    if( message_for_me ) {&lt;br /&gt;
      if ( mit == sender || sender == ANY )     //se devo ritornare il messaggio&lt;br /&gt;
        break;     //esci dal while&lt;br /&gt;
      else                                      //se devo salvarlo (sender specificato e messaggio per me)&lt;br /&gt;
        //devo mettere in db i messaggi di altri mittenti, ricevuti quando ne aspettavo uno da un mittente specificato&lt;br /&gt;
        db.add(&amp;lt;mit, msg&amp;gt;);&lt;br /&gt;
    }&lt;br /&gt;
  } while (!message_for_me)&lt;br /&gt;
  return msg;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Esame 19/06/2017 ==&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2017.06.19.tot.pdf 2017.06.19.tot.pdf]&lt;br /&gt;
=== Esercizio c.1 (da controllare)===&lt;br /&gt;
&lt;br /&gt;
* Mi sembra che ci sia un errore per il giodice, potrebbe succedere in un caso che il wait non si risvegli mai [[User:Flecart|Flecart]] ([[User talk:Flecart|talk]]) 15:38, 19 January 2023 (CET)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define NATLETI n&lt;br /&gt;
&lt;br /&gt;
condition ok2lancia[NATLETI];&lt;br /&gt;
condition ok2giudice;&lt;br /&gt;
&lt;br /&gt;
int counter[NATLETI];&lt;br /&gt;
int ultimo_tiro;&lt;br /&gt;
float registro[NATLETI][3];&lt;br /&gt;
&lt;br /&gt;
Procedure entry: boolean pronto(int i)&lt;br /&gt;
{&lt;br /&gt;
    if(!(i == 0 &amp;amp;&amp;amp; counter[i] == 0)) // se è il primo lancio non devo metterlo in wait&lt;br /&gt;
        ok2lancia[i].wait()&lt;br /&gt;
    if(counter[i] &amp;lt; 3)&lt;br /&gt;
        return true;&lt;br /&gt;
    else&lt;br /&gt;
        return false;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: void lanciato (int i)&lt;br /&gt;
{&lt;br /&gt;
    counter[i]++;&lt;br /&gt;
    ultimo_tiro = i;&lt;br /&gt;
    ok2giudice.signal();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: int lanciofatto()&lt;br /&gt;
{&lt;br /&gt;
    ok2giudice.wait()&lt;br /&gt;
    if(ultimo_tiro == NATLETI-1 &amp;amp;&amp;amp; counter[0] == 3)&lt;br /&gt;
        return -1;  // devo invalidare la condizione per uscire dal while, quindi se nessuno deve più lanciare ritorno -1&lt;br /&gt;
    else&lt;br /&gt;
        return ultimo_tiro;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: void registraechiama(int i, float m)&lt;br /&gt;
{&lt;br /&gt;
    registro[i][counter[i]-1] = m; // il secondo indice indica l'iesimo lancio -1 (perchè iniziamo a contare da zero)&lt;br /&gt;
    if(i == NATLETI-1) // se ha appena tirato l'ultimo atleta non posso dare il via a NATLETI (perchè non esiste), quindi faccio ricominciare il giro&lt;br /&gt;
        ok2lancia[0].signal();&lt;br /&gt;
    else&lt;br /&gt;
        ok2lancia[i+1].signal();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: int classifica()&lt;br /&gt;
{&lt;br /&gt;
    int best[NATLETI];&lt;br /&gt;
    for(int i = 0; i &amp;lt; NATLETI; i++)&lt;br /&gt;
    {&lt;br /&gt;
        for(int j = 0; j &amp;lt; 3; j++)&lt;br /&gt;
        {&lt;br /&gt;
            if(registro[i][j] &amp;gt; best[i])&lt;br /&gt;
                best[i] = registro[i][j];&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    best.sort_in_descending_order(); // supponiamo nel nostro pseudolinguaggio esista una funzione di ordinamento qualunque&lt;br /&gt;
    return best;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Esame 29/05/2017 ==&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2017.05.29.tot.pdf 2017.05.29.tot.pdf]&lt;br /&gt;
=== Esercizio c.1 ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
condition okpartita&lt;br /&gt;
condition ok2chiama&lt;br /&gt;
condition ok2punteggio&lt;br /&gt;
condition ok2run[2][MAX]&lt;br /&gt;
int numpronti&lt;br /&gt;
int punteggio[2]&lt;br /&gt;
boolean partita=false&lt;br /&gt;
boolean partitafinita=false&lt;br /&gt;
chiamati = []&lt;br /&gt;
contabandiera[2]&lt;br /&gt;
int winner&lt;br /&gt;
&lt;br /&gt;
entry nuovapartita():&lt;br /&gt;
{&lt;br /&gt;
    punteggio[A] = punteggio[B] = 0;&lt;br /&gt;
    numpronti = 0;&lt;br /&gt;
    partita=true;&lt;br /&gt;
    okpartita.signal()&lt;br /&gt;
    chiamati = [];&lt;br /&gt;
}&lt;br /&gt;
entry chiama(l):&lt;br /&gt;
{&lt;br /&gt;
    if (numpronti&amp;lt;2*MAX)&lt;br /&gt;
    {&lt;br /&gt;
        ok2chiama.wait();&lt;br /&gt;
    }&lt;br /&gt;
    chiamati = l;&lt;br /&gt;
    contabandiera[A] = contabandiera[B] = 0&lt;br /&gt;
    winner = -1;&lt;br /&gt;
    for (s in n)&lt;br /&gt;
    {&lt;br /&gt;
        ok2run[A][s].signal();&lt;br /&gt;
        ok2run[B][s].signal()&lt;br /&gt;
    }&lt;br /&gt;
    ok2punteggio.wait();&lt;br /&gt;
    punteggio[winner++]&lt;br /&gt;
    if (max(punteggio) == 10)&lt;br /&gt;
    {&lt;br /&gt;
        partitafinita = true;&lt;br /&gt;
        for (s in A,B)&lt;br /&gt;
        {&lt;br /&gt;
            for (n in range(MAX))&lt;br /&gt;
            {&lt;br /&gt;
                ok2run[s][n].signal();&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    return punteggio;&lt;br /&gt;
}&lt;br /&gt;
entry pronto(s, n):&lt;br /&gt;
{&lt;br /&gt;
    if (partitafinita) return 1;&lt;br /&gt;
    if (!partita)&lt;br /&gt;
    {&lt;br /&gt;
        okpartita.wait();&lt;br /&gt;
    }&lt;br /&gt;
    numpronti++;&lt;br /&gt;
    if (numpronti&amp;gt;=2*MAX)&lt;br /&gt;
    {&lt;br /&gt;
        ok2chiama.signal();&lt;br /&gt;
    }&lt;br /&gt;
    if (!(n in chiamati))&lt;br /&gt;
    {&lt;br /&gt;
        ok2run[s][n].wait();&lt;br /&gt;
    }&lt;br /&gt;
    numpronti--;&lt;br /&gt;
    return 0 if partita else 1;&lt;br /&gt;
}&lt;br /&gt;
allabandiera(s, n):&lt;br /&gt;
{&lt;br /&gt;
    contabandiera[s]++;&lt;br /&gt;
    if (winner == -1 &amp;amp;&amp;amp; contabandiera[s] == len(chiamati))&lt;br /&gt;
    {&lt;br /&gt;
        winner = s;&lt;br /&gt;
    }&lt;br /&gt;
    if (contabandiera[A] == len(chiamati) &amp;amp;&amp;amp; contabandiera[B] == len(chiamati))&lt;br /&gt;
    {&lt;br /&gt;
        ok2punteggio.signal();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
casi da discutere:    &lt;br /&gt;
se arrivano studenti a pronto prima che il prof dichiara nuovapartita succedono guai.&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>LiberaL</name></author>
	</entry>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=User:LiberaL&amp;diff=3024</id>
		<title>User:LiberaL</title>
		<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php?title=User:LiberaL&amp;diff=3024"/>
		<updated>2023-05-26T12:52:59Z</updated>

		<summary type="html">&lt;p&gt;LiberaL: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Se vuoi contattarmi sono presente su Telegram con tag [https://t.me/LLibera @LLibera]&lt;br /&gt;
&lt;br /&gt;
Sono Libera Longo, studentessa Laurea Triennale informatica qui a Bologna :D&lt;/div&gt;</summary>
		<author><name>LiberaL</name></author>
	</entry>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=User:LiberaL&amp;diff=3023</id>
		<title>User:LiberaL</title>
		<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php?title=User:LiberaL&amp;diff=3023"/>
		<updated>2023-05-26T12:52:28Z</updated>

		<summary type="html">&lt;p&gt;LiberaL: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Se vuoi contattarmi sono presente su Telegram con tag [https://t.me/LLibera @LLibera]&lt;br /&gt;
&lt;br /&gt;
Sono Libera Longo, studentessa Laurea Triennale informatica qui a Bologna :D&lt;br /&gt;
&lt;br /&gt;
(se vedi una pagina firmata con [ https://t.me/llibera LiberaL ] o [ https://t.me/llibera LLibera ] sono sempre io... che non so come firmarmi...)&lt;/div&gt;</summary>
		<author><name>LiberaL</name></author>
	</entry>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=User:LiberaL&amp;diff=3022</id>
		<title>User:LiberaL</title>
		<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php?title=User:LiberaL&amp;diff=3022"/>
		<updated>2023-05-26T12:46:09Z</updated>

		<summary type="html">&lt;p&gt;LiberaL: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Se vuoi contattarmi sono presente su Telegram con tag [https://t.me/LLibera @LLibera]&lt;br /&gt;
&lt;br /&gt;
Sono Libera Longo, studentessa Laurea Triennale informatica qui a Bologna :D&lt;/div&gt;</summary>
		<author><name>LiberaL</name></author>
	</entry>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=User:LiberaL&amp;diff=3021</id>
		<title>User:LiberaL</title>
		<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php?title=User:LiberaL&amp;diff=3021"/>
		<updated>2023-05-26T12:45:50Z</updated>

		<summary type="html">&lt;p&gt;LiberaL: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Se vuoi contattarmi sono presente su Telegram con tag [https://t.me/LLibera @LLibera]&lt;br /&gt;
&lt;br /&gt;
Sono Libera Longo, studentessa Laurea Triennale informatica qui a Bologna :D anno scolastico 2022/2023&lt;/div&gt;</summary>
		<author><name>LiberaL</name></author>
	</entry>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=User:LiberaL&amp;diff=3020</id>
		<title>User:LiberaL</title>
		<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php?title=User:LiberaL&amp;diff=3020"/>
		<updated>2023-05-26T12:45:37Z</updated>

		<summary type="html">&lt;p&gt;LiberaL: Created page with &amp;quot;Se vuoi contattarmi sono presente su Telegram con tag [https://t.me/LLibera @LLibera] Sono Libera Longo, studentessa Laurea Triennale informatica qui a Bologna :D anno scolast...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Se vuoi contattarmi sono presente su Telegram con tag [https://t.me/LLibera @LLibera]&lt;br /&gt;
Sono Libera Longo, studentessa Laurea Triennale informatica qui a Bologna :D anno scolastico 2022/2023&lt;/div&gt;</summary>
		<author><name>LiberaL</name></author>
	</entry>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=Prove_scritte_2017&amp;diff=3019</id>
		<title>Prove scritte 2017</title>
		<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php?title=Prove_scritte_2017&amp;diff=3019"/>
		<updated>2023-05-26T12:37:50Z</updated>

		<summary type="html">&lt;p&gt;LiberaL: /* Esercizio c.2 (da controllare) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Esame 11/09/2017 ==&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2017.09.11.tot.pdf 2017.09.11.tot.pdf]&lt;br /&gt;
=== Esercizio c.1 ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
monitor crossing&lt;br /&gt;
&lt;br /&gt;
ok2dir[4];     //NESW&lt;br /&gt;
bool busy = false;&lt;br /&gt;
&lt;br /&gt;
pe entra(int dir)&lt;br /&gt;
   if (busy)&lt;br /&gt;
      ok2dir[dir].wait();&lt;br /&gt;
   busy = true;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
pe esci(int dir)&lt;br /&gt;
   busy = false;&lt;br /&gt;
   ok2dir[(dir + 1) % 4].signal();&lt;br /&gt;
   if (!busy)&lt;br /&gt;
      ok2dir[(dir + 2) % 4].signal();&lt;br /&gt;
   if (!busy)&lt;br /&gt;
      ok2dir[(dir + 3) % 4].signal();&lt;br /&gt;
   if (!busy)&lt;br /&gt;
      ok2dir[(dir + 4) % 4].signal();  //dir&lt;br /&gt;
&lt;br /&gt;
//alternativa più compatta&lt;br /&gt;
pe esci(int dir)&lt;br /&gt;
   busy = false;&lt;br /&gt;
   for (i = 0; i &amp;lt; 4; i++)&lt;br /&gt;
   if (!busy)&lt;br /&gt;
      ok2dir[(dir + i + 1) % 4].signal();&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Soluzione proposta 2 ==== &lt;br /&gt;
Soluzione proposta da [https://t.me/LLibera LLibera] e corretta da  [https://so.v2.cs.unibo.it/wiki/index.php/User:Flecart Flecart]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
const int N_DIRECTION = 4;&lt;br /&gt;
&lt;br /&gt;
// assumo N = 0, E = 1, S = 2, W = 3, oppure shiftati ciclicamente, è equivalente&lt;br /&gt;
&lt;br /&gt;
monitor crossing {&lt;br /&gt;
	bool free;										//l'incrocio è libero?&lt;br /&gt;
	int num_waiting[N_DIRECTION];&lt;br /&gt;
	condition okToCross[N_DIRECTION];				//free == True&lt;br /&gt;
	&lt;br /&gt;
	crossing() {&lt;br /&gt;
		free = True;								//parto con l'incrocio libero&lt;br /&gt;
		for (int i = 0; i &amp;lt; N_DIRECTION; i++) {&lt;br /&gt;
			num_waiting[i] = 0;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	procedure entry enter(int direction) {&lt;br /&gt;
		if(!free) {									//se l'incrocio non è libero&lt;br /&gt;
			num_waiting[direction]++;&lt;br /&gt;
			okToCross[direction].wait();			//aspetto nella mia direzione&lt;br /&gt;
			num_waiting[direction]--;&lt;br /&gt;
		}&lt;br /&gt;
													//ora sono sicurə che sia libero&lt;br /&gt;
		free = False;								//quindi lo dichiaro occupato&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	procedure entry exit(int direction) {&lt;br /&gt;
													//non devo aspettare niente per liberare l'incrocio&lt;br /&gt;
		free = True;								//lo dichiaro libero&lt;br /&gt;
		&lt;br /&gt;
		for (int i = 0; i &amp;lt; N_DIRECTION; i++) {&lt;br /&gt;
			int curr_dir = (direction + i + 1) % N_DIRECTION;&lt;br /&gt;
			if (num_waiting[curr_dir] &amp;gt; 0) {&lt;br /&gt;
				okToCross[curr_dir].signal();&lt;br /&gt;
				break;	// l'onere di risvegliare gli altri è stato passato al nuovo processo risvegliato, quindi esco.&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.2 (da controllare) ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// server[] = array contenente il PID di tutti i server&lt;br /&gt;
&lt;br /&gt;
#define BROADCAST server[0]&lt;br /&gt;
&lt;br /&gt;
server[0]&lt;br /&gt;
{&lt;br /&gt;
    while(true)&lt;br /&gt;
    {&lt;br /&gt;
        &amp;lt;msg, sender&amp;gt; = arecv(*); // ricevo il messaggio&lt;br /&gt;
        if (sender == BROADCAST)&lt;br /&gt;
            print(msg); // se il messaggio l'ho ricevuto da me stesso allora lo stampo&lt;br /&gt;
        else&lt;br /&gt;
            asend(*, &amp;lt;msg, getpid()&amp;gt;); // se il messaggio l'ho ricevuto da un client o da un altro server lo inoltro a tutti i server (compreso me stesso)&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
server[x] // x = 1...N-1&lt;br /&gt;
{&lt;br /&gt;
    while(true)&lt;br /&gt;
    {&lt;br /&gt;
        &amp;lt;msg, sender&amp;gt; = arecv(*); // ricevo il messaggio&lt;br /&gt;
        if (sender == BROADCAST)&lt;br /&gt;
            print(msg); // se il messaggio l'ho ricevuto dal server[0] allora lo stampo&lt;br /&gt;
        else&lt;br /&gt;
            asend(BROADCAST, &amp;lt;msg, getpid()&amp;gt;) // se il messaggio l'ho ricevuto da un client lo inoltro al server[0]&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Soluzione proposta 2 ====&lt;br /&gt;
&lt;br /&gt;
Soluzione proposta da [https://so.v2.cs.unibo.it/wiki/index.php/User:Flecart Flecart]&lt;br /&gt;
Soluzione corretta da [https://so.v2.cs.unibo.it/wiki/index.php/User:Gio Flecart friend]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
process server_0 {&lt;br /&gt;
&lt;br /&gt;
        while (true) {&lt;br /&gt;
                &amp;lt;msg, sender&amp;gt; = arecv(ANY);&lt;br /&gt;
                for (int i = 1 ; i &amp;lt; N; i++) {&lt;br /&gt;
                        asend(&amp;lt;msg, 0&amp;gt;, server[i]);&lt;br /&gt;
                        while(true){&lt;br /&gt;
                          msg = arecv(server[i]); // così so che tutti abbiano stampato.&lt;br /&gt;
                          if(msg==ACK)&lt;br /&gt;
                            break&lt;br /&gt;
                          asend(msg,server[0]);&lt;br /&gt;
                        }&lt;br /&gt;
                }&lt;br /&gt;
                print(msg);&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
process server_[i=1 to N - 1] {&lt;br /&gt;
        while (true) {&lt;br /&gt;
                &amp;lt;msg, sender&amp;gt; = arecv(ANY);&lt;br /&gt;
                if (sender == 0) {&lt;br /&gt;
                        print(msg);&lt;br /&gt;
                        asend(ACK, server[0]);&lt;br /&gt;
                } else {&lt;br /&gt;
                        asend(&amp;lt;msg, i&amp;gt;, server[0]);&lt;br /&gt;
                }&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Esame 17/07/2017 ==&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2017.07.17.tot.pdf 2017.07.17.tot.pdf]&lt;br /&gt;
=== Esercizio c.1 ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
monitor conf {&lt;br /&gt;
        condition finished;&lt;br /&gt;
        condition ready2present[max];&lt;br /&gt;
        bool arrived[max] = false;&lt;br /&gt;
        bool giachiamato[max] = false;&lt;br /&gt;
&lt;br /&gt;
        entry chiama(chiamato){&lt;br /&gt;
        if(arrived[chiamato] == true)&lt;br /&gt;
                ready2present[chiamato].signal;&lt;br /&gt;
                finished.wait;&lt;br /&gt;
                return true;&lt;br /&gt;
        else&lt;br /&gt;
                giachiamato[chiamato]= true&lt;br /&gt;
                return false;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        entry arrivato(nome){&lt;br /&gt;
                if(giachiamato[nome] == true)&lt;br /&gt;
                        return  false;&lt;br /&gt;
&lt;br /&gt;
                arrived[nome] = true;&lt;br /&gt;
                ok2present[nome].wait;&lt;br /&gt;
                return true;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        entry finepresentazione(nome){&lt;br /&gt;
                finished.signal;&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.2 (da controllare) ===&lt;br /&gt;
controllata da [https://t.me/LLibera LLibera] 14:26, 26 May 2023 (CEST) l'implementazione fornita gestisce solo il caso di arecv(ANY) e non arecv(mittente)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
si, è possibile: &lt;br /&gt;
&lt;br /&gt;
Implementare asend e arecv date bsend e brecv&lt;br /&gt;
&lt;br /&gt;
asend(pid_t dst, msg_type msg){&lt;br /&gt;
    bsend (&amp;lt;dst, msg&amp;gt;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
arecv(*){&lt;br /&gt;
  do {&lt;br /&gt;
    &amp;lt;dst, msg&amp;gt; = brecv(*);&lt;br /&gt;
  } while (dst != getpid())&lt;br /&gt;
  return msg;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
propongo (LLibera) quindi questa implementazione con gestione arecv da mittente specificato (sempre da controllare)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
//il messaggio mandato è la tripla &amp;lt;destinatario, mittente, messaggio&amp;gt;&lt;br /&gt;
&lt;br /&gt;
asend(pid_t dst, msg_type msg){&lt;br /&gt;
    bsend (&amp;lt;dst, getpid(), msg&amp;gt;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Queue of &amp;lt;pid_t, pid_t, msg_type&amp;gt; db;&lt;br /&gt;
arecv(pid_t sender) {&lt;br /&gt;
&lt;br /&gt;
  //devo controllare se nella coda ho già ricevuto il messaggio da quel mittente, ovvero mentre aspettavo un messaggio da qualcun'altro&lt;br /&gt;
  //db.get(sender) cerca una tripla il cui mittente è sender&lt;br /&gt;
  //se trova il messaggio lo rimuove anche dal db.&lt;br /&gt;
  //db.get(ANY) ritorna (ed elimina da db) il primo che trova (FIFO), e if(db.isEmpty()) return NULL;&lt;br /&gt;
&lt;br /&gt;
  if( ( &amp;lt;dst, mit, msg&amp;gt; = db.get(sender) ) != NULL ) //se lo trova&lt;br /&gt;
    return msg;&lt;br /&gt;
  do {&lt;br /&gt;
    &amp;lt;dst, mit, msg&amp;gt; = brecv(*);                 //ricevo&lt;br /&gt;
    bool message_for_me = (dst == getpid());    //il messaggio è per me?&lt;br /&gt;
    if( message_for_me ) {&lt;br /&gt;
      if ( mit == sender || sender == ANY )     //se devo ritornare il messaggio&lt;br /&gt;
        break;     //esci dal while&lt;br /&gt;
      else                                      //se devo salvarlo (sender specificato e messaggio per me)&lt;br /&gt;
        //devo mettere in db i messaggi di altri mittenti, ricevuti quando ne aspettavo uno da un mittente specificato&lt;br /&gt;
        db.add(&amp;lt;dst, mit, msg&amp;gt;);&lt;br /&gt;
    }&lt;br /&gt;
  } while (!message_for_me)&lt;br /&gt;
  return msg;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Esame 19/06/2017 ==&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2017.06.19.tot.pdf 2017.06.19.tot.pdf]&lt;br /&gt;
=== Esercizio c.1 (da controllare)===&lt;br /&gt;
&lt;br /&gt;
* Mi sembra che ci sia un errore per il giodice, potrebbe succedere in un caso che il wait non si risvegli mai [[User:Flecart|Flecart]] ([[User talk:Flecart|talk]]) 15:38, 19 January 2023 (CET)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define NATLETI n&lt;br /&gt;
&lt;br /&gt;
condition ok2lancia[NATLETI];&lt;br /&gt;
condition ok2giudice;&lt;br /&gt;
&lt;br /&gt;
int counter[NATLETI];&lt;br /&gt;
int ultimo_tiro;&lt;br /&gt;
float registro[NATLETI][3];&lt;br /&gt;
&lt;br /&gt;
Procedure entry: boolean pronto(int i)&lt;br /&gt;
{&lt;br /&gt;
    if(!(i == 0 &amp;amp;&amp;amp; counter[i] == 0)) // se è il primo lancio non devo metterlo in wait&lt;br /&gt;
        ok2lancia[i].wait()&lt;br /&gt;
    if(counter[i] &amp;lt; 3)&lt;br /&gt;
        return true;&lt;br /&gt;
    else&lt;br /&gt;
        return false;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: void lanciato (int i)&lt;br /&gt;
{&lt;br /&gt;
    counter[i]++;&lt;br /&gt;
    ultimo_tiro = i;&lt;br /&gt;
    ok2giudice.signal();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: int lanciofatto()&lt;br /&gt;
{&lt;br /&gt;
    ok2giudice.wait()&lt;br /&gt;
    if(ultimo_tiro == NATLETI-1 &amp;amp;&amp;amp; counter[0] == 3)&lt;br /&gt;
        return -1;  // devo invalidare la condizione per uscire dal while, quindi se nessuno deve più lanciare ritorno -1&lt;br /&gt;
    else&lt;br /&gt;
        return ultimo_tiro;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: void registraechiama(int i, float m)&lt;br /&gt;
{&lt;br /&gt;
    registro[i][counter[i]-1] = m; // il secondo indice indica l'iesimo lancio -1 (perchè iniziamo a contare da zero)&lt;br /&gt;
    if(i == NATLETI-1) // se ha appena tirato l'ultimo atleta non posso dare il via a NATLETI (perchè non esiste), quindi faccio ricominciare il giro&lt;br /&gt;
        ok2lancia[0].signal();&lt;br /&gt;
    else&lt;br /&gt;
        ok2lancia[i+1].signal();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: int classifica()&lt;br /&gt;
{&lt;br /&gt;
    int best[NATLETI];&lt;br /&gt;
    for(int i = 0; i &amp;lt; NATLETI; i++)&lt;br /&gt;
    {&lt;br /&gt;
        for(int j = 0; j &amp;lt; 3; j++)&lt;br /&gt;
        {&lt;br /&gt;
            if(registro[i][j] &amp;gt; best[i])&lt;br /&gt;
                best[i] = registro[i][j];&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    best.sort_in_descending_order(); // supponiamo nel nostro pseudolinguaggio esista una funzione di ordinamento qualunque&lt;br /&gt;
    return best;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Esame 29/05/2017 ==&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2017.05.29.tot.pdf 2017.05.29.tot.pdf]&lt;br /&gt;
=== Esercizio c.1 ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
condition okpartita&lt;br /&gt;
condition ok2chiama&lt;br /&gt;
condition ok2punteggio&lt;br /&gt;
condition ok2run[2][MAX]&lt;br /&gt;
int numpronti&lt;br /&gt;
int punteggio[2]&lt;br /&gt;
boolean partita=false&lt;br /&gt;
boolean partitafinita=false&lt;br /&gt;
chiamati = []&lt;br /&gt;
contabandiera[2]&lt;br /&gt;
int winner&lt;br /&gt;
&lt;br /&gt;
entry nuovapartita():&lt;br /&gt;
{&lt;br /&gt;
    punteggio[A] = punteggio[B] = 0;&lt;br /&gt;
    numpronti = 0;&lt;br /&gt;
    partita=true;&lt;br /&gt;
    okpartita.signal()&lt;br /&gt;
    chiamati = [];&lt;br /&gt;
}&lt;br /&gt;
entry chiama(l):&lt;br /&gt;
{&lt;br /&gt;
    if (numpronti&amp;lt;2*MAX)&lt;br /&gt;
    {&lt;br /&gt;
        ok2chiama.wait();&lt;br /&gt;
    }&lt;br /&gt;
    chiamati = l;&lt;br /&gt;
    contabandiera[A] = contabandiera[B] = 0&lt;br /&gt;
    winner = -1;&lt;br /&gt;
    for (s in n)&lt;br /&gt;
    {&lt;br /&gt;
        ok2run[A][s].signal();&lt;br /&gt;
        ok2run[B][s].signal()&lt;br /&gt;
    }&lt;br /&gt;
    ok2punteggio.wait();&lt;br /&gt;
    punteggio[winner++]&lt;br /&gt;
    if (max(punteggio) == 10)&lt;br /&gt;
    {&lt;br /&gt;
        partitafinita = true;&lt;br /&gt;
        for (s in A,B)&lt;br /&gt;
        {&lt;br /&gt;
            for (n in range(MAX))&lt;br /&gt;
            {&lt;br /&gt;
                ok2run[s][n].signal();&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    return punteggio;&lt;br /&gt;
}&lt;br /&gt;
entry pronto(s, n):&lt;br /&gt;
{&lt;br /&gt;
    if (partitafinita) return 1;&lt;br /&gt;
    if (!partita)&lt;br /&gt;
    {&lt;br /&gt;
        okpartita.wait();&lt;br /&gt;
    }&lt;br /&gt;
    numpronti++;&lt;br /&gt;
    if (numpronti&amp;gt;=2*MAX)&lt;br /&gt;
    {&lt;br /&gt;
        ok2chiama.signal();&lt;br /&gt;
    }&lt;br /&gt;
    if (!(n in chiamati))&lt;br /&gt;
    {&lt;br /&gt;
        ok2run[s][n].wait();&lt;br /&gt;
    }&lt;br /&gt;
    numpronti--;&lt;br /&gt;
    return 0 if partita else 1;&lt;br /&gt;
}&lt;br /&gt;
allabandiera(s, n):&lt;br /&gt;
{&lt;br /&gt;
    contabandiera[s]++;&lt;br /&gt;
    if (winner == -1 &amp;amp;&amp;amp; contabandiera[s] == len(chiamati))&lt;br /&gt;
    {&lt;br /&gt;
        winner = s;&lt;br /&gt;
    }&lt;br /&gt;
    if (contabandiera[A] == len(chiamati) &amp;amp;&amp;amp; contabandiera[B] == len(chiamati))&lt;br /&gt;
    {&lt;br /&gt;
        ok2punteggio.signal();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
casi da discutere:    &lt;br /&gt;
se arrivano studenti a pronto prima che il prof dichiara nuovapartita succedono guai.&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>LiberaL</name></author>
	</entry>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=Prove_scritte_2017&amp;diff=3018</id>
		<title>Prove scritte 2017</title>
		<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php?title=Prove_scritte_2017&amp;diff=3018"/>
		<updated>2023-05-26T12:26:45Z</updated>

		<summary type="html">&lt;p&gt;LiberaL: /* Esercizio c.2 (da controllare) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Esame 11/09/2017 ==&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2017.09.11.tot.pdf 2017.09.11.tot.pdf]&lt;br /&gt;
=== Esercizio c.1 ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
monitor crossing&lt;br /&gt;
&lt;br /&gt;
ok2dir[4];     //NESW&lt;br /&gt;
bool busy = false;&lt;br /&gt;
&lt;br /&gt;
pe entra(int dir)&lt;br /&gt;
   if (busy)&lt;br /&gt;
      ok2dir[dir].wait();&lt;br /&gt;
   busy = true;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
pe esci(int dir)&lt;br /&gt;
   busy = false;&lt;br /&gt;
   ok2dir[(dir + 1) % 4].signal();&lt;br /&gt;
   if (!busy)&lt;br /&gt;
      ok2dir[(dir + 2) % 4].signal();&lt;br /&gt;
   if (!busy)&lt;br /&gt;
      ok2dir[(dir + 3) % 4].signal();&lt;br /&gt;
   if (!busy)&lt;br /&gt;
      ok2dir[(dir + 4) % 4].signal();  //dir&lt;br /&gt;
&lt;br /&gt;
//alternativa più compatta&lt;br /&gt;
pe esci(int dir)&lt;br /&gt;
   busy = false;&lt;br /&gt;
   for (i = 0; i &amp;lt; 4; i++)&lt;br /&gt;
   if (!busy)&lt;br /&gt;
      ok2dir[(dir + i + 1) % 4].signal();&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Soluzione proposta 2 ==== &lt;br /&gt;
Soluzione proposta da [https://t.me/LLibera LLibera] e corretta da  [https://so.v2.cs.unibo.it/wiki/index.php/User:Flecart Flecart]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
const int N_DIRECTION = 4;&lt;br /&gt;
&lt;br /&gt;
// assumo N = 0, E = 1, S = 2, W = 3, oppure shiftati ciclicamente, è equivalente&lt;br /&gt;
&lt;br /&gt;
monitor crossing {&lt;br /&gt;
	bool free;										//l'incrocio è libero?&lt;br /&gt;
	int num_waiting[N_DIRECTION];&lt;br /&gt;
	condition okToCross[N_DIRECTION];				//free == True&lt;br /&gt;
	&lt;br /&gt;
	crossing() {&lt;br /&gt;
		free = True;								//parto con l'incrocio libero&lt;br /&gt;
		for (int i = 0; i &amp;lt; N_DIRECTION; i++) {&lt;br /&gt;
			num_waiting[i] = 0;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	procedure entry enter(int direction) {&lt;br /&gt;
		if(!free) {									//se l'incrocio non è libero&lt;br /&gt;
			num_waiting[direction]++;&lt;br /&gt;
			okToCross[direction].wait();			//aspetto nella mia direzione&lt;br /&gt;
			num_waiting[direction]--;&lt;br /&gt;
		}&lt;br /&gt;
													//ora sono sicurə che sia libero&lt;br /&gt;
		free = False;								//quindi lo dichiaro occupato&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	procedure entry exit(int direction) {&lt;br /&gt;
													//non devo aspettare niente per liberare l'incrocio&lt;br /&gt;
		free = True;								//lo dichiaro libero&lt;br /&gt;
		&lt;br /&gt;
		for (int i = 0; i &amp;lt; N_DIRECTION; i++) {&lt;br /&gt;
			int curr_dir = (direction + i + 1) % N_DIRECTION;&lt;br /&gt;
			if (num_waiting[curr_dir] &amp;gt; 0) {&lt;br /&gt;
				okToCross[curr_dir].signal();&lt;br /&gt;
				break;	// l'onere di risvegliare gli altri è stato passato al nuovo processo risvegliato, quindi esco.&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.2 (da controllare) ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// server[] = array contenente il PID di tutti i server&lt;br /&gt;
&lt;br /&gt;
#define BROADCAST server[0]&lt;br /&gt;
&lt;br /&gt;
server[0]&lt;br /&gt;
{&lt;br /&gt;
    while(true)&lt;br /&gt;
    {&lt;br /&gt;
        &amp;lt;msg, sender&amp;gt; = arecv(*); // ricevo il messaggio&lt;br /&gt;
        if (sender == BROADCAST)&lt;br /&gt;
            print(msg); // se il messaggio l'ho ricevuto da me stesso allora lo stampo&lt;br /&gt;
        else&lt;br /&gt;
            asend(*, &amp;lt;msg, getpid()&amp;gt;); // se il messaggio l'ho ricevuto da un client o da un altro server lo inoltro a tutti i server (compreso me stesso)&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
server[x] // x = 1...N-1&lt;br /&gt;
{&lt;br /&gt;
    while(true)&lt;br /&gt;
    {&lt;br /&gt;
        &amp;lt;msg, sender&amp;gt; = arecv(*); // ricevo il messaggio&lt;br /&gt;
        if (sender == BROADCAST)&lt;br /&gt;
            print(msg); // se il messaggio l'ho ricevuto dal server[0] allora lo stampo&lt;br /&gt;
        else&lt;br /&gt;
            asend(BROADCAST, &amp;lt;msg, getpid()&amp;gt;) // se il messaggio l'ho ricevuto da un client lo inoltro al server[0]&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Soluzione proposta 2 ====&lt;br /&gt;
&lt;br /&gt;
Soluzione proposta da [https://so.v2.cs.unibo.it/wiki/index.php/User:Flecart Flecart]&lt;br /&gt;
Soluzione corretta da [https://so.v2.cs.unibo.it/wiki/index.php/User:Gio Flecart friend]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
process server_0 {&lt;br /&gt;
&lt;br /&gt;
        while (true) {&lt;br /&gt;
                &amp;lt;msg, sender&amp;gt; = arecv(ANY);&lt;br /&gt;
                for (int i = 1 ; i &amp;lt; N; i++) {&lt;br /&gt;
                        asend(&amp;lt;msg, 0&amp;gt;, server[i]);&lt;br /&gt;
                        while(true){&lt;br /&gt;
                          msg = arecv(server[i]); // così so che tutti abbiano stampato.&lt;br /&gt;
                          if(msg==ACK)&lt;br /&gt;
                            break&lt;br /&gt;
                          asend(msg,server[0]);&lt;br /&gt;
                        }&lt;br /&gt;
                }&lt;br /&gt;
                print(msg);&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
process server_[i=1 to N - 1] {&lt;br /&gt;
        while (true) {&lt;br /&gt;
                &amp;lt;msg, sender&amp;gt; = arecv(ANY);&lt;br /&gt;
                if (sender == 0) {&lt;br /&gt;
                        print(msg);&lt;br /&gt;
                        asend(ACK, server[0]);&lt;br /&gt;
                } else {&lt;br /&gt;
                        asend(&amp;lt;msg, i&amp;gt;, server[0]);&lt;br /&gt;
                }&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Esame 17/07/2017 ==&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2017.07.17.tot.pdf 2017.07.17.tot.pdf]&lt;br /&gt;
=== Esercizio c.1 ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
monitor conf {&lt;br /&gt;
        condition finished;&lt;br /&gt;
        condition ready2present[max];&lt;br /&gt;
        bool arrived[max] = false;&lt;br /&gt;
        bool giachiamato[max] = false;&lt;br /&gt;
&lt;br /&gt;
        entry chiama(chiamato){&lt;br /&gt;
        if(arrived[chiamato] == true)&lt;br /&gt;
                ready2present[chiamato].signal;&lt;br /&gt;
                finished.wait;&lt;br /&gt;
                return true;&lt;br /&gt;
        else&lt;br /&gt;
                giachiamato[chiamato]= true&lt;br /&gt;
                return false;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        entry arrivato(nome){&lt;br /&gt;
                if(giachiamato[nome] == true)&lt;br /&gt;
                        return  false;&lt;br /&gt;
&lt;br /&gt;
                arrived[nome] = true;&lt;br /&gt;
                ok2present[nome].wait;&lt;br /&gt;
                return true;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        entry finepresentazione(nome){&lt;br /&gt;
                finished.signal;&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.2 (da controllare) ===&lt;br /&gt;
controllata da [https://t.me/LLibera LLibera] https://t.me/LLibera 14:26, 26 May 2023 (CEST) l'implementazione fornita gestisce solo il caso di arecv(ANY) e non arecv(mittente)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
si, è possibile: &lt;br /&gt;
&lt;br /&gt;
Implementare asend e arecv date bsend e brecv&lt;br /&gt;
&lt;br /&gt;
asend(pid_t dst, msg_type msg){&lt;br /&gt;
    bsend (&amp;lt;dst, msg&amp;gt;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
arecv(*){&lt;br /&gt;
  do {&lt;br /&gt;
    &amp;lt;dst, msg&amp;gt; = brecv(*);&lt;br /&gt;
  } while (dst != getpid())&lt;br /&gt;
  return msg;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
propongo (LLibera) quindi questa implementazione con gestione arecv da mittente specificato (sempre da controllare)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
//il messaggio mandato è la tripla &amp;lt;destinatario, mittente, messaggio&amp;gt;&lt;br /&gt;
&lt;br /&gt;
asend(pid_t dst, msg_type msg){&lt;br /&gt;
    bsend (&amp;lt;dst, getpid(), msg&amp;gt;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Queue of &amp;lt;pid_t, pid_t, msg_type&amp;gt; db;&lt;br /&gt;
arecv(pid_t sender) {&lt;br /&gt;
&lt;br /&gt;
  //devo controllare se nella coda ho già ricevuto il messaggio da quel mittente, ovvero mentre aspettavo un messaggio da qualcun'altro&lt;br /&gt;
  //db.get(sender) cerca una tripla il cui mittente è sender&lt;br /&gt;
  //se trova il messaggio lo rimuove anche dal db.&lt;br /&gt;
  //db.get(ANY) ritorna (ed elimina da db) il primo che trova (FIFO), e if(db.isEmpty()) return NULL;&lt;br /&gt;
&lt;br /&gt;
  if( ( &amp;lt;dst, mit, msg&amp;gt; = db.get(sender) ) != NULL ) //se lo trova&lt;br /&gt;
    return msg;&lt;br /&gt;
  do {&lt;br /&gt;
    &amp;lt;dst, mit, msg&amp;gt; = brecv(*);                 //ricevo&lt;br /&gt;
    bool message_for_me = (dst == getpid());    //il messaggio è per me?&lt;br /&gt;
    if( message_for_me ) {&lt;br /&gt;
      if ( mit == sender || sender == ANY )     //se devo ritornare il messaggio&lt;br /&gt;
        break;     //esci dal while&lt;br /&gt;
      else                                      //se devo salvarlo (sender specificato e messaggio per me)&lt;br /&gt;
        //devo mettere in db i messaggi di altri mittenti, ricevuti quando ne aspettavo uno da un mittente specificato&lt;br /&gt;
        db.add(&amp;lt;dst, mit, msg&amp;gt;);&lt;br /&gt;
    }&lt;br /&gt;
  } while (!message_for_me)&lt;br /&gt;
  return msg;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Esame 19/06/2017 ==&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2017.06.19.tot.pdf 2017.06.19.tot.pdf]&lt;br /&gt;
=== Esercizio c.1 (da controllare)===&lt;br /&gt;
&lt;br /&gt;
* Mi sembra che ci sia un errore per il giodice, potrebbe succedere in un caso che il wait non si risvegli mai [[User:Flecart|Flecart]] ([[User talk:Flecart|talk]]) 15:38, 19 January 2023 (CET)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define NATLETI n&lt;br /&gt;
&lt;br /&gt;
condition ok2lancia[NATLETI];&lt;br /&gt;
condition ok2giudice;&lt;br /&gt;
&lt;br /&gt;
int counter[NATLETI];&lt;br /&gt;
int ultimo_tiro;&lt;br /&gt;
float registro[NATLETI][3];&lt;br /&gt;
&lt;br /&gt;
Procedure entry: boolean pronto(int i)&lt;br /&gt;
{&lt;br /&gt;
    if(!(i == 0 &amp;amp;&amp;amp; counter[i] == 0)) // se è il primo lancio non devo metterlo in wait&lt;br /&gt;
        ok2lancia[i].wait()&lt;br /&gt;
    if(counter[i] &amp;lt; 3)&lt;br /&gt;
        return true;&lt;br /&gt;
    else&lt;br /&gt;
        return false;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: void lanciato (int i)&lt;br /&gt;
{&lt;br /&gt;
    counter[i]++;&lt;br /&gt;
    ultimo_tiro = i;&lt;br /&gt;
    ok2giudice.signal();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: int lanciofatto()&lt;br /&gt;
{&lt;br /&gt;
    ok2giudice.wait()&lt;br /&gt;
    if(ultimo_tiro == NATLETI-1 &amp;amp;&amp;amp; counter[0] == 3)&lt;br /&gt;
        return -1;  // devo invalidare la condizione per uscire dal while, quindi se nessuno deve più lanciare ritorno -1&lt;br /&gt;
    else&lt;br /&gt;
        return ultimo_tiro;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: void registraechiama(int i, float m)&lt;br /&gt;
{&lt;br /&gt;
    registro[i][counter[i]-1] = m; // il secondo indice indica l'iesimo lancio -1 (perchè iniziamo a contare da zero)&lt;br /&gt;
    if(i == NATLETI-1) // se ha appena tirato l'ultimo atleta non posso dare il via a NATLETI (perchè non esiste), quindi faccio ricominciare il giro&lt;br /&gt;
        ok2lancia[0].signal();&lt;br /&gt;
    else&lt;br /&gt;
        ok2lancia[i+1].signal();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: int classifica()&lt;br /&gt;
{&lt;br /&gt;
    int best[NATLETI];&lt;br /&gt;
    for(int i = 0; i &amp;lt; NATLETI; i++)&lt;br /&gt;
    {&lt;br /&gt;
        for(int j = 0; j &amp;lt; 3; j++)&lt;br /&gt;
        {&lt;br /&gt;
            if(registro[i][j] &amp;gt; best[i])&lt;br /&gt;
                best[i] = registro[i][j];&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    best.sort_in_descending_order(); // supponiamo nel nostro pseudolinguaggio esista una funzione di ordinamento qualunque&lt;br /&gt;
    return best;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Esame 29/05/2017 ==&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2017.05.29.tot.pdf 2017.05.29.tot.pdf]&lt;br /&gt;
=== Esercizio c.1 ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
condition okpartita&lt;br /&gt;
condition ok2chiama&lt;br /&gt;
condition ok2punteggio&lt;br /&gt;
condition ok2run[2][MAX]&lt;br /&gt;
int numpronti&lt;br /&gt;
int punteggio[2]&lt;br /&gt;
boolean partita=false&lt;br /&gt;
boolean partitafinita=false&lt;br /&gt;
chiamati = []&lt;br /&gt;
contabandiera[2]&lt;br /&gt;
int winner&lt;br /&gt;
&lt;br /&gt;
entry nuovapartita():&lt;br /&gt;
{&lt;br /&gt;
    punteggio[A] = punteggio[B] = 0;&lt;br /&gt;
    numpronti = 0;&lt;br /&gt;
    partita=true;&lt;br /&gt;
    okpartita.signal()&lt;br /&gt;
    chiamati = [];&lt;br /&gt;
}&lt;br /&gt;
entry chiama(l):&lt;br /&gt;
{&lt;br /&gt;
    if (numpronti&amp;lt;2*MAX)&lt;br /&gt;
    {&lt;br /&gt;
        ok2chiama.wait();&lt;br /&gt;
    }&lt;br /&gt;
    chiamati = l;&lt;br /&gt;
    contabandiera[A] = contabandiera[B] = 0&lt;br /&gt;
    winner = -1;&lt;br /&gt;
    for (s in n)&lt;br /&gt;
    {&lt;br /&gt;
        ok2run[A][s].signal();&lt;br /&gt;
        ok2run[B][s].signal()&lt;br /&gt;
    }&lt;br /&gt;
    ok2punteggio.wait();&lt;br /&gt;
    punteggio[winner++]&lt;br /&gt;
    if (max(punteggio) == 10)&lt;br /&gt;
    {&lt;br /&gt;
        partitafinita = true;&lt;br /&gt;
        for (s in A,B)&lt;br /&gt;
        {&lt;br /&gt;
            for (n in range(MAX))&lt;br /&gt;
            {&lt;br /&gt;
                ok2run[s][n].signal();&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    return punteggio;&lt;br /&gt;
}&lt;br /&gt;
entry pronto(s, n):&lt;br /&gt;
{&lt;br /&gt;
    if (partitafinita) return 1;&lt;br /&gt;
    if (!partita)&lt;br /&gt;
    {&lt;br /&gt;
        okpartita.wait();&lt;br /&gt;
    }&lt;br /&gt;
    numpronti++;&lt;br /&gt;
    if (numpronti&amp;gt;=2*MAX)&lt;br /&gt;
    {&lt;br /&gt;
        ok2chiama.signal();&lt;br /&gt;
    }&lt;br /&gt;
    if (!(n in chiamati))&lt;br /&gt;
    {&lt;br /&gt;
        ok2run[s][n].wait();&lt;br /&gt;
    }&lt;br /&gt;
    numpronti--;&lt;br /&gt;
    return 0 if partita else 1;&lt;br /&gt;
}&lt;br /&gt;
allabandiera(s, n):&lt;br /&gt;
{&lt;br /&gt;
    contabandiera[s]++;&lt;br /&gt;
    if (winner == -1 &amp;amp;&amp;amp; contabandiera[s] == len(chiamati))&lt;br /&gt;
    {&lt;br /&gt;
        winner = s;&lt;br /&gt;
    }&lt;br /&gt;
    if (contabandiera[A] == len(chiamati) &amp;amp;&amp;amp; contabandiera[B] == len(chiamati))&lt;br /&gt;
    {&lt;br /&gt;
        ok2punteggio.signal();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
casi da discutere:    &lt;br /&gt;
se arrivano studenti a pronto prima che il prof dichiara nuovapartita succedono guai.&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>LiberaL</name></author>
	</entry>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=Prove_scritte_2017&amp;diff=3017</id>
		<title>Prove scritte 2017</title>
		<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php?title=Prove_scritte_2017&amp;diff=3017"/>
		<updated>2023-05-26T12:19:25Z</updated>

		<summary type="html">&lt;p&gt;LiberaL: /* Esercizio c.2 (da controllare) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Esame 11/09/2017 ==&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2017.09.11.tot.pdf 2017.09.11.tot.pdf]&lt;br /&gt;
=== Esercizio c.1 ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
monitor crossing&lt;br /&gt;
&lt;br /&gt;
ok2dir[4];     //NESW&lt;br /&gt;
bool busy = false;&lt;br /&gt;
&lt;br /&gt;
pe entra(int dir)&lt;br /&gt;
   if (busy)&lt;br /&gt;
      ok2dir[dir].wait();&lt;br /&gt;
   busy = true;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
pe esci(int dir)&lt;br /&gt;
   busy = false;&lt;br /&gt;
   ok2dir[(dir + 1) % 4].signal();&lt;br /&gt;
   if (!busy)&lt;br /&gt;
      ok2dir[(dir + 2) % 4].signal();&lt;br /&gt;
   if (!busy)&lt;br /&gt;
      ok2dir[(dir + 3) % 4].signal();&lt;br /&gt;
   if (!busy)&lt;br /&gt;
      ok2dir[(dir + 4) % 4].signal();  //dir&lt;br /&gt;
&lt;br /&gt;
//alternativa più compatta&lt;br /&gt;
pe esci(int dir)&lt;br /&gt;
   busy = false;&lt;br /&gt;
   for (i = 0; i &amp;lt; 4; i++)&lt;br /&gt;
   if (!busy)&lt;br /&gt;
      ok2dir[(dir + i + 1) % 4].signal();&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Soluzione proposta 2 ==== &lt;br /&gt;
Soluzione proposta da [https://t.me/LLibera LLibera] e corretta da  [https://so.v2.cs.unibo.it/wiki/index.php/User:Flecart Flecart]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
const int N_DIRECTION = 4;&lt;br /&gt;
&lt;br /&gt;
// assumo N = 0, E = 1, S = 2, W = 3, oppure shiftati ciclicamente, è equivalente&lt;br /&gt;
&lt;br /&gt;
monitor crossing {&lt;br /&gt;
	bool free;										//l'incrocio è libero?&lt;br /&gt;
	int num_waiting[N_DIRECTION];&lt;br /&gt;
	condition okToCross[N_DIRECTION];				//free == True&lt;br /&gt;
	&lt;br /&gt;
	crossing() {&lt;br /&gt;
		free = True;								//parto con l'incrocio libero&lt;br /&gt;
		for (int i = 0; i &amp;lt; N_DIRECTION; i++) {&lt;br /&gt;
			num_waiting[i] = 0;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	procedure entry enter(int direction) {&lt;br /&gt;
		if(!free) {									//se l'incrocio non è libero&lt;br /&gt;
			num_waiting[direction]++;&lt;br /&gt;
			okToCross[direction].wait();			//aspetto nella mia direzione&lt;br /&gt;
			num_waiting[direction]--;&lt;br /&gt;
		}&lt;br /&gt;
													//ora sono sicurə che sia libero&lt;br /&gt;
		free = False;								//quindi lo dichiaro occupato&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	procedure entry exit(int direction) {&lt;br /&gt;
													//non devo aspettare niente per liberare l'incrocio&lt;br /&gt;
		free = True;								//lo dichiaro libero&lt;br /&gt;
		&lt;br /&gt;
		for (int i = 0; i &amp;lt; N_DIRECTION; i++) {&lt;br /&gt;
			int curr_dir = (direction + i + 1) % N_DIRECTION;&lt;br /&gt;
			if (num_waiting[curr_dir] &amp;gt; 0) {&lt;br /&gt;
				okToCross[curr_dir].signal();&lt;br /&gt;
				break;	// l'onere di risvegliare gli altri è stato passato al nuovo processo risvegliato, quindi esco.&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.2 (da controllare) ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// server[] = array contenente il PID di tutti i server&lt;br /&gt;
&lt;br /&gt;
#define BROADCAST server[0]&lt;br /&gt;
&lt;br /&gt;
server[0]&lt;br /&gt;
{&lt;br /&gt;
    while(true)&lt;br /&gt;
    {&lt;br /&gt;
        &amp;lt;msg, sender&amp;gt; = arecv(*); // ricevo il messaggio&lt;br /&gt;
        if (sender == BROADCAST)&lt;br /&gt;
            print(msg); // se il messaggio l'ho ricevuto da me stesso allora lo stampo&lt;br /&gt;
        else&lt;br /&gt;
            asend(*, &amp;lt;msg, getpid()&amp;gt;); // se il messaggio l'ho ricevuto da un client o da un altro server lo inoltro a tutti i server (compreso me stesso)&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
server[x] // x = 1...N-1&lt;br /&gt;
{&lt;br /&gt;
    while(true)&lt;br /&gt;
    {&lt;br /&gt;
        &amp;lt;msg, sender&amp;gt; = arecv(*); // ricevo il messaggio&lt;br /&gt;
        if (sender == BROADCAST)&lt;br /&gt;
            print(msg); // se il messaggio l'ho ricevuto dal server[0] allora lo stampo&lt;br /&gt;
        else&lt;br /&gt;
            asend(BROADCAST, &amp;lt;msg, getpid()&amp;gt;) // se il messaggio l'ho ricevuto da un client lo inoltro al server[0]&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Soluzione proposta 2 ====&lt;br /&gt;
&lt;br /&gt;
Soluzione proposta da [https://so.v2.cs.unibo.it/wiki/index.php/User:Flecart Flecart]&lt;br /&gt;
Soluzione corretta da [https://so.v2.cs.unibo.it/wiki/index.php/User:Gio Flecart friend]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
process server_0 {&lt;br /&gt;
&lt;br /&gt;
        while (true) {&lt;br /&gt;
                &amp;lt;msg, sender&amp;gt; = arecv(ANY);&lt;br /&gt;
                for (int i = 1 ; i &amp;lt; N; i++) {&lt;br /&gt;
                        asend(&amp;lt;msg, 0&amp;gt;, server[i]);&lt;br /&gt;
                        while(true){&lt;br /&gt;
                          msg = arecv(server[i]); // così so che tutti abbiano stampato.&lt;br /&gt;
                          if(msg==ACK)&lt;br /&gt;
                            break&lt;br /&gt;
                          asend(msg,server[0]);&lt;br /&gt;
                        }&lt;br /&gt;
                }&lt;br /&gt;
                print(msg);&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
process server_[i=1 to N - 1] {&lt;br /&gt;
        while (true) {&lt;br /&gt;
                &amp;lt;msg, sender&amp;gt; = arecv(ANY);&lt;br /&gt;
                if (sender == 0) {&lt;br /&gt;
                        print(msg);&lt;br /&gt;
                        asend(ACK, server[0]);&lt;br /&gt;
                } else {&lt;br /&gt;
                        asend(&amp;lt;msg, i&amp;gt;, server[0]);&lt;br /&gt;
                }&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Esame 17/07/2017 ==&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2017.07.17.tot.pdf 2017.07.17.tot.pdf]&lt;br /&gt;
=== Esercizio c.1 ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
monitor conf {&lt;br /&gt;
        condition finished;&lt;br /&gt;
        condition ready2present[max];&lt;br /&gt;
        bool arrived[max] = false;&lt;br /&gt;
        bool giachiamato[max] = false;&lt;br /&gt;
&lt;br /&gt;
        entry chiama(chiamato){&lt;br /&gt;
        if(arrived[chiamato] == true)&lt;br /&gt;
                ready2present[chiamato].signal;&lt;br /&gt;
                finished.wait;&lt;br /&gt;
                return true;&lt;br /&gt;
        else&lt;br /&gt;
                giachiamato[chiamato]= true&lt;br /&gt;
                return false;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        entry arrivato(nome){&lt;br /&gt;
                if(giachiamato[nome] == true)&lt;br /&gt;
                        return  false;&lt;br /&gt;
&lt;br /&gt;
                arrived[nome] = true;&lt;br /&gt;
                ok2present[nome].wait;&lt;br /&gt;
                return true;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        entry finepresentazione(nome){&lt;br /&gt;
                finished.signal;&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.2 (da controllare) ===&lt;br /&gt;
controllata da [https://t.me/LLibera LLibera] 13:41, 26 May 2023 (CEST) l'implementazione fornita gestisce solo il caso di arecv(ANY) e non arecv(mittente)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
si, è possibile: &lt;br /&gt;
&lt;br /&gt;
Implementare asend e arecv date bsend e brecv&lt;br /&gt;
&lt;br /&gt;
asend(pid_t dst, msg_type msg){&lt;br /&gt;
    bsend (&amp;lt;dst, msg&amp;gt;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
arecv(*){&lt;br /&gt;
  do {&lt;br /&gt;
    &amp;lt;dst, msg&amp;gt; = brecv(*);&lt;br /&gt;
  } while (dst != getpid())&lt;br /&gt;
  return msg;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
propongo (LLibera) quindi questa implementazione con gestione arecv da mittente specificato (sempre da controllare)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
//il messaggio mandato è la tripla &amp;lt;destinatario, mittente, messaggio&amp;gt;&lt;br /&gt;
&lt;br /&gt;
asend(pid_t dst, msg_type msg){&lt;br /&gt;
    bsend (&amp;lt;dst, getpid(), msg&amp;gt;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Queue of &amp;lt;pid_t, pid_t, msg_type&amp;gt; db;&lt;br /&gt;
arecv(pid_t sender) {&lt;br /&gt;
&lt;br /&gt;
  //devo controllare se nella coda ho già ricevuto il messaggio da quel mittente precedentemente, mentre aspettavo un messaggio da qualcun'altro&lt;br /&gt;
  //db.get(sender) cerca una tripla il cui mittente è sender&lt;br /&gt;
  //se trova il messaggio lo rimuove anche dal db.&lt;br /&gt;
  //se sender è ANY db.get(sender) ritorna (ed elimina da db) il primo che trova (FIFO), e if(db.isEmpty()) return NULL;&lt;br /&gt;
&lt;br /&gt;
  if( ( &amp;lt;dst, mit, msg&amp;gt; = db.get(sender) ) != NULL ) //se lo trova&lt;br /&gt;
    return msg;&lt;br /&gt;
  do {&lt;br /&gt;
    &amp;lt;dst, mit, msg&amp;gt; = brecv(*);                 //ricevo&lt;br /&gt;
    bool message_for_me = (dst == getpid());    //il messaggio è per me?&lt;br /&gt;
    if( message_for_me ) {&lt;br /&gt;
      if ( mit == sender || sender == ANY )     //se devo ritornare il messaggio&lt;br /&gt;
        break;     //esci dal while&lt;br /&gt;
      else                                      //se devo salvarlo (sender specificato e messaggio per me)&lt;br /&gt;
        //devo mettere in db i messaggi di altri mittenti, ricevuti quando ne aspettavo uno da un mittente specificato&lt;br /&gt;
        db.add(&amp;lt;dst, mit, msg&amp;gt;);&lt;br /&gt;
    }&lt;br /&gt;
  } while (!message_for_me)&lt;br /&gt;
  return msg;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Esame 19/06/2017 ==&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2017.06.19.tot.pdf 2017.06.19.tot.pdf]&lt;br /&gt;
=== Esercizio c.1 (da controllare)===&lt;br /&gt;
&lt;br /&gt;
* Mi sembra che ci sia un errore per il giodice, potrebbe succedere in un caso che il wait non si risvegli mai [[User:Flecart|Flecart]] ([[User talk:Flecart|talk]]) 15:38, 19 January 2023 (CET)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define NATLETI n&lt;br /&gt;
&lt;br /&gt;
condition ok2lancia[NATLETI];&lt;br /&gt;
condition ok2giudice;&lt;br /&gt;
&lt;br /&gt;
int counter[NATLETI];&lt;br /&gt;
int ultimo_tiro;&lt;br /&gt;
float registro[NATLETI][3];&lt;br /&gt;
&lt;br /&gt;
Procedure entry: boolean pronto(int i)&lt;br /&gt;
{&lt;br /&gt;
    if(!(i == 0 &amp;amp;&amp;amp; counter[i] == 0)) // se è il primo lancio non devo metterlo in wait&lt;br /&gt;
        ok2lancia[i].wait()&lt;br /&gt;
    if(counter[i] &amp;lt; 3)&lt;br /&gt;
        return true;&lt;br /&gt;
    else&lt;br /&gt;
        return false;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: void lanciato (int i)&lt;br /&gt;
{&lt;br /&gt;
    counter[i]++;&lt;br /&gt;
    ultimo_tiro = i;&lt;br /&gt;
    ok2giudice.signal();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: int lanciofatto()&lt;br /&gt;
{&lt;br /&gt;
    ok2giudice.wait()&lt;br /&gt;
    if(ultimo_tiro == NATLETI-1 &amp;amp;&amp;amp; counter[0] == 3)&lt;br /&gt;
        return -1;  // devo invalidare la condizione per uscire dal while, quindi se nessuno deve più lanciare ritorno -1&lt;br /&gt;
    else&lt;br /&gt;
        return ultimo_tiro;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: void registraechiama(int i, float m)&lt;br /&gt;
{&lt;br /&gt;
    registro[i][counter[i]-1] = m; // il secondo indice indica l'iesimo lancio -1 (perchè iniziamo a contare da zero)&lt;br /&gt;
    if(i == NATLETI-1) // se ha appena tirato l'ultimo atleta non posso dare il via a NATLETI (perchè non esiste), quindi faccio ricominciare il giro&lt;br /&gt;
        ok2lancia[0].signal();&lt;br /&gt;
    else&lt;br /&gt;
        ok2lancia[i+1].signal();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: int classifica()&lt;br /&gt;
{&lt;br /&gt;
    int best[NATLETI];&lt;br /&gt;
    for(int i = 0; i &amp;lt; NATLETI; i++)&lt;br /&gt;
    {&lt;br /&gt;
        for(int j = 0; j &amp;lt; 3; j++)&lt;br /&gt;
        {&lt;br /&gt;
            if(registro[i][j] &amp;gt; best[i])&lt;br /&gt;
                best[i] = registro[i][j];&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    best.sort_in_descending_order(); // supponiamo nel nostro pseudolinguaggio esista una funzione di ordinamento qualunque&lt;br /&gt;
    return best;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Esame 29/05/2017 ==&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2017.05.29.tot.pdf 2017.05.29.tot.pdf]&lt;br /&gt;
=== Esercizio c.1 ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
condition okpartita&lt;br /&gt;
condition ok2chiama&lt;br /&gt;
condition ok2punteggio&lt;br /&gt;
condition ok2run[2][MAX]&lt;br /&gt;
int numpronti&lt;br /&gt;
int punteggio[2]&lt;br /&gt;
boolean partita=false&lt;br /&gt;
boolean partitafinita=false&lt;br /&gt;
chiamati = []&lt;br /&gt;
contabandiera[2]&lt;br /&gt;
int winner&lt;br /&gt;
&lt;br /&gt;
entry nuovapartita():&lt;br /&gt;
{&lt;br /&gt;
    punteggio[A] = punteggio[B] = 0;&lt;br /&gt;
    numpronti = 0;&lt;br /&gt;
    partita=true;&lt;br /&gt;
    okpartita.signal()&lt;br /&gt;
    chiamati = [];&lt;br /&gt;
}&lt;br /&gt;
entry chiama(l):&lt;br /&gt;
{&lt;br /&gt;
    if (numpronti&amp;lt;2*MAX)&lt;br /&gt;
    {&lt;br /&gt;
        ok2chiama.wait();&lt;br /&gt;
    }&lt;br /&gt;
    chiamati = l;&lt;br /&gt;
    contabandiera[A] = contabandiera[B] = 0&lt;br /&gt;
    winner = -1;&lt;br /&gt;
    for (s in n)&lt;br /&gt;
    {&lt;br /&gt;
        ok2run[A][s].signal();&lt;br /&gt;
        ok2run[B][s].signal()&lt;br /&gt;
    }&lt;br /&gt;
    ok2punteggio.wait();&lt;br /&gt;
    punteggio[winner++]&lt;br /&gt;
    if (max(punteggio) == 10)&lt;br /&gt;
    {&lt;br /&gt;
        partitafinita = true;&lt;br /&gt;
        for (s in A,B)&lt;br /&gt;
        {&lt;br /&gt;
            for (n in range(MAX))&lt;br /&gt;
            {&lt;br /&gt;
                ok2run[s][n].signal();&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    return punteggio;&lt;br /&gt;
}&lt;br /&gt;
entry pronto(s, n):&lt;br /&gt;
{&lt;br /&gt;
    if (partitafinita) return 1;&lt;br /&gt;
    if (!partita)&lt;br /&gt;
    {&lt;br /&gt;
        okpartita.wait();&lt;br /&gt;
    }&lt;br /&gt;
    numpronti++;&lt;br /&gt;
    if (numpronti&amp;gt;=2*MAX)&lt;br /&gt;
    {&lt;br /&gt;
        ok2chiama.signal();&lt;br /&gt;
    }&lt;br /&gt;
    if (!(n in chiamati))&lt;br /&gt;
    {&lt;br /&gt;
        ok2run[s][n].wait();&lt;br /&gt;
    }&lt;br /&gt;
    numpronti--;&lt;br /&gt;
    return 0 if partita else 1;&lt;br /&gt;
}&lt;br /&gt;
allabandiera(s, n):&lt;br /&gt;
{&lt;br /&gt;
    contabandiera[s]++;&lt;br /&gt;
    if (winner == -1 &amp;amp;&amp;amp; contabandiera[s] == len(chiamati))&lt;br /&gt;
    {&lt;br /&gt;
        winner = s;&lt;br /&gt;
    }&lt;br /&gt;
    if (contabandiera[A] == len(chiamati) &amp;amp;&amp;amp; contabandiera[B] == len(chiamati))&lt;br /&gt;
    {&lt;br /&gt;
        ok2punteggio.signal();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
casi da discutere:    &lt;br /&gt;
se arrivano studenti a pronto prima che il prof dichiara nuovapartita succedono guai.&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>LiberaL</name></author>
	</entry>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=Prove_scritte_2017&amp;diff=3016</id>
		<title>Prove scritte 2017</title>
		<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php?title=Prove_scritte_2017&amp;diff=3016"/>
		<updated>2023-05-26T12:18:04Z</updated>

		<summary type="html">&lt;p&gt;LiberaL: /* Esercizio c.2 (da controllare) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Esame 11/09/2017 ==&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2017.09.11.tot.pdf 2017.09.11.tot.pdf]&lt;br /&gt;
=== Esercizio c.1 ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
monitor crossing&lt;br /&gt;
&lt;br /&gt;
ok2dir[4];     //NESW&lt;br /&gt;
bool busy = false;&lt;br /&gt;
&lt;br /&gt;
pe entra(int dir)&lt;br /&gt;
   if (busy)&lt;br /&gt;
      ok2dir[dir].wait();&lt;br /&gt;
   busy = true;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
pe esci(int dir)&lt;br /&gt;
   busy = false;&lt;br /&gt;
   ok2dir[(dir + 1) % 4].signal();&lt;br /&gt;
   if (!busy)&lt;br /&gt;
      ok2dir[(dir + 2) % 4].signal();&lt;br /&gt;
   if (!busy)&lt;br /&gt;
      ok2dir[(dir + 3) % 4].signal();&lt;br /&gt;
   if (!busy)&lt;br /&gt;
      ok2dir[(dir + 4) % 4].signal();  //dir&lt;br /&gt;
&lt;br /&gt;
//alternativa più compatta&lt;br /&gt;
pe esci(int dir)&lt;br /&gt;
   busy = false;&lt;br /&gt;
   for (i = 0; i &amp;lt; 4; i++)&lt;br /&gt;
   if (!busy)&lt;br /&gt;
      ok2dir[(dir + i + 1) % 4].signal();&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Soluzione proposta 2 ==== &lt;br /&gt;
Soluzione proposta da [https://t.me/LLibera LLibera] e corretta da  [https://so.v2.cs.unibo.it/wiki/index.php/User:Flecart Flecart]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
const int N_DIRECTION = 4;&lt;br /&gt;
&lt;br /&gt;
// assumo N = 0, E = 1, S = 2, W = 3, oppure shiftati ciclicamente, è equivalente&lt;br /&gt;
&lt;br /&gt;
monitor crossing {&lt;br /&gt;
	bool free;										//l'incrocio è libero?&lt;br /&gt;
	int num_waiting[N_DIRECTION];&lt;br /&gt;
	condition okToCross[N_DIRECTION];				//free == True&lt;br /&gt;
	&lt;br /&gt;
	crossing() {&lt;br /&gt;
		free = True;								//parto con l'incrocio libero&lt;br /&gt;
		for (int i = 0; i &amp;lt; N_DIRECTION; i++) {&lt;br /&gt;
			num_waiting[i] = 0;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	procedure entry enter(int direction) {&lt;br /&gt;
		if(!free) {									//se l'incrocio non è libero&lt;br /&gt;
			num_waiting[direction]++;&lt;br /&gt;
			okToCross[direction].wait();			//aspetto nella mia direzione&lt;br /&gt;
			num_waiting[direction]--;&lt;br /&gt;
		}&lt;br /&gt;
													//ora sono sicurə che sia libero&lt;br /&gt;
		free = False;								//quindi lo dichiaro occupato&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	procedure entry exit(int direction) {&lt;br /&gt;
													//non devo aspettare niente per liberare l'incrocio&lt;br /&gt;
		free = True;								//lo dichiaro libero&lt;br /&gt;
		&lt;br /&gt;
		for (int i = 0; i &amp;lt; N_DIRECTION; i++) {&lt;br /&gt;
			int curr_dir = (direction + i + 1) % N_DIRECTION;&lt;br /&gt;
			if (num_waiting[curr_dir] &amp;gt; 0) {&lt;br /&gt;
				okToCross[curr_dir].signal();&lt;br /&gt;
				break;	// l'onere di risvegliare gli altri è stato passato al nuovo processo risvegliato, quindi esco.&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.2 (da controllare) ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// server[] = array contenente il PID di tutti i server&lt;br /&gt;
&lt;br /&gt;
#define BROADCAST server[0]&lt;br /&gt;
&lt;br /&gt;
server[0]&lt;br /&gt;
{&lt;br /&gt;
    while(true)&lt;br /&gt;
    {&lt;br /&gt;
        &amp;lt;msg, sender&amp;gt; = arecv(*); // ricevo il messaggio&lt;br /&gt;
        if (sender == BROADCAST)&lt;br /&gt;
            print(msg); // se il messaggio l'ho ricevuto da me stesso allora lo stampo&lt;br /&gt;
        else&lt;br /&gt;
            asend(*, &amp;lt;msg, getpid()&amp;gt;); // se il messaggio l'ho ricevuto da un client o da un altro server lo inoltro a tutti i server (compreso me stesso)&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
server[x] // x = 1...N-1&lt;br /&gt;
{&lt;br /&gt;
    while(true)&lt;br /&gt;
    {&lt;br /&gt;
        &amp;lt;msg, sender&amp;gt; = arecv(*); // ricevo il messaggio&lt;br /&gt;
        if (sender == BROADCAST)&lt;br /&gt;
            print(msg); // se il messaggio l'ho ricevuto dal server[0] allora lo stampo&lt;br /&gt;
        else&lt;br /&gt;
            asend(BROADCAST, &amp;lt;msg, getpid()&amp;gt;) // se il messaggio l'ho ricevuto da un client lo inoltro al server[0]&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Soluzione proposta 2 ====&lt;br /&gt;
&lt;br /&gt;
Soluzione proposta da [https://so.v2.cs.unibo.it/wiki/index.php/User:Flecart Flecart]&lt;br /&gt;
Soluzione corretta da [https://so.v2.cs.unibo.it/wiki/index.php/User:Gio Flecart friend]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
process server_0 {&lt;br /&gt;
&lt;br /&gt;
        while (true) {&lt;br /&gt;
                &amp;lt;msg, sender&amp;gt; = arecv(ANY);&lt;br /&gt;
                for (int i = 1 ; i &amp;lt; N; i++) {&lt;br /&gt;
                        asend(&amp;lt;msg, 0&amp;gt;, server[i]);&lt;br /&gt;
                        while(true){&lt;br /&gt;
                          msg = arecv(server[i]); // così so che tutti abbiano stampato.&lt;br /&gt;
                          if(msg==ACK)&lt;br /&gt;
                            break&lt;br /&gt;
                          asend(msg,server[0]);&lt;br /&gt;
                        }&lt;br /&gt;
                }&lt;br /&gt;
                print(msg);&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
process server_[i=1 to N - 1] {&lt;br /&gt;
        while (true) {&lt;br /&gt;
                &amp;lt;msg, sender&amp;gt; = arecv(ANY);&lt;br /&gt;
                if (sender == 0) {&lt;br /&gt;
                        print(msg);&lt;br /&gt;
                        asend(ACK, server[0]);&lt;br /&gt;
                } else {&lt;br /&gt;
                        asend(&amp;lt;msg, i&amp;gt;, server[0]);&lt;br /&gt;
                }&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Esame 17/07/2017 ==&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2017.07.17.tot.pdf 2017.07.17.tot.pdf]&lt;br /&gt;
=== Esercizio c.1 ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
monitor conf {&lt;br /&gt;
        condition finished;&lt;br /&gt;
        condition ready2present[max];&lt;br /&gt;
        bool arrived[max] = false;&lt;br /&gt;
        bool giachiamato[max] = false;&lt;br /&gt;
&lt;br /&gt;
        entry chiama(chiamato){&lt;br /&gt;
        if(arrived[chiamato] == true)&lt;br /&gt;
                ready2present[chiamato].signal;&lt;br /&gt;
                finished.wait;&lt;br /&gt;
                return true;&lt;br /&gt;
        else&lt;br /&gt;
                giachiamato[chiamato]= true&lt;br /&gt;
                return false;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        entry arrivato(nome){&lt;br /&gt;
                if(giachiamato[nome] == true)&lt;br /&gt;
                        return  false;&lt;br /&gt;
&lt;br /&gt;
                arrived[nome] = true;&lt;br /&gt;
                ok2present[nome].wait;&lt;br /&gt;
                return true;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        entry finepresentazione(nome){&lt;br /&gt;
                finished.signal;&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.2 (da controllare) ===&lt;br /&gt;
controllata da [https://t.me/LLibera LLibera] 13:41, 26 May 2023 (CEST) l'implementazione fornita gestisce solo il caso di arecv(ANY) e non arecv(mittente)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
si, è possibile: &lt;br /&gt;
&lt;br /&gt;
Implementare asend e arecv date bsend e brecv&lt;br /&gt;
&lt;br /&gt;
asend(pid_t dst, msg_type msg){&lt;br /&gt;
    bsend (&amp;lt;dst, msg&amp;gt;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
arecv(*){&lt;br /&gt;
  do {&lt;br /&gt;
    &amp;lt;dst, msg&amp;gt; = brecv(*);&lt;br /&gt;
  } while (dst != getpid())&lt;br /&gt;
  return msg;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
propongo (LLibera) quindi questa implementazione con gestione arecv da mittente specificato (sempre da controllare)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
//il messaggio mandato è la tripla &amp;lt;destinatario, mittente, messaggio&amp;gt;&lt;br /&gt;
&lt;br /&gt;
asend(pid_t dst, msg_type msg){&lt;br /&gt;
    bsend (&amp;lt;dst, getpid(), msg&amp;gt;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Queue of &amp;lt;pid_t, pid_t, msg_type&amp;gt; db;&lt;br /&gt;
arecv(pid_t sender) {&lt;br /&gt;
&lt;br /&gt;
  //devo controllare se nella coda ho già ricevuto il messaggio da quel mittente precedentemente, mentre aspettavo un messaggio da qualcun'altro&lt;br /&gt;
  //db.get(sender) cerca una tripla il cui mittente è sender&lt;br /&gt;
  //se trova il messaggio lo rimuove anche dal db.&lt;br /&gt;
  //se sender è ANY db.get(sender) ritorna (ed elimina da db) il primo che trova (FIFO), e if(db.isEmpty()) return NULL;&lt;br /&gt;
&lt;br /&gt;
  if( ( &amp;lt;dst, mit, msg&amp;gt; = db.get(sender) ) != NULL ) //se non lo trova&lt;br /&gt;
    return msg;&lt;br /&gt;
  do {&lt;br /&gt;
    &amp;lt;dst, mit, msg&amp;gt; = brecv(*);                 //ricevo&lt;br /&gt;
    bool message_for_me = (dst == getpid());    //il messaggio è per me?&lt;br /&gt;
    if( message_for_me ) {&lt;br /&gt;
      if ( mit == sender || sender == ANY )     //se devo ritornare il messaggio&lt;br /&gt;
        break;                                  //esci dal while&lt;br /&gt;
      else                                      //se devo salvarlo (sender specificato e messaggio per me)&lt;br /&gt;
        //devo mettere in db i messaggi di altri mittenti, ricevuti quando ne aspettavo uno da un mittente specificato&lt;br /&gt;
        db.add(&amp;lt;dst, mit, msg&amp;gt;);&lt;br /&gt;
    }&lt;br /&gt;
  } while (!message_for_me)&lt;br /&gt;
  return msg;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Esame 19/06/2017 ==&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2017.06.19.tot.pdf 2017.06.19.tot.pdf]&lt;br /&gt;
=== Esercizio c.1 (da controllare)===&lt;br /&gt;
&lt;br /&gt;
* Mi sembra che ci sia un errore per il giodice, potrebbe succedere in un caso che il wait non si risvegli mai [[User:Flecart|Flecart]] ([[User talk:Flecart|talk]]) 15:38, 19 January 2023 (CET)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define NATLETI n&lt;br /&gt;
&lt;br /&gt;
condition ok2lancia[NATLETI];&lt;br /&gt;
condition ok2giudice;&lt;br /&gt;
&lt;br /&gt;
int counter[NATLETI];&lt;br /&gt;
int ultimo_tiro;&lt;br /&gt;
float registro[NATLETI][3];&lt;br /&gt;
&lt;br /&gt;
Procedure entry: boolean pronto(int i)&lt;br /&gt;
{&lt;br /&gt;
    if(!(i == 0 &amp;amp;&amp;amp; counter[i] == 0)) // se è il primo lancio non devo metterlo in wait&lt;br /&gt;
        ok2lancia[i].wait()&lt;br /&gt;
    if(counter[i] &amp;lt; 3)&lt;br /&gt;
        return true;&lt;br /&gt;
    else&lt;br /&gt;
        return false;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: void lanciato (int i)&lt;br /&gt;
{&lt;br /&gt;
    counter[i]++;&lt;br /&gt;
    ultimo_tiro = i;&lt;br /&gt;
    ok2giudice.signal();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: int lanciofatto()&lt;br /&gt;
{&lt;br /&gt;
    ok2giudice.wait()&lt;br /&gt;
    if(ultimo_tiro == NATLETI-1 &amp;amp;&amp;amp; counter[0] == 3)&lt;br /&gt;
        return -1;  // devo invalidare la condizione per uscire dal while, quindi se nessuno deve più lanciare ritorno -1&lt;br /&gt;
    else&lt;br /&gt;
        return ultimo_tiro;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: void registraechiama(int i, float m)&lt;br /&gt;
{&lt;br /&gt;
    registro[i][counter[i]-1] = m; // il secondo indice indica l'iesimo lancio -1 (perchè iniziamo a contare da zero)&lt;br /&gt;
    if(i == NATLETI-1) // se ha appena tirato l'ultimo atleta non posso dare il via a NATLETI (perchè non esiste), quindi faccio ricominciare il giro&lt;br /&gt;
        ok2lancia[0].signal();&lt;br /&gt;
    else&lt;br /&gt;
        ok2lancia[i+1].signal();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: int classifica()&lt;br /&gt;
{&lt;br /&gt;
    int best[NATLETI];&lt;br /&gt;
    for(int i = 0; i &amp;lt; NATLETI; i++)&lt;br /&gt;
    {&lt;br /&gt;
        for(int j = 0; j &amp;lt; 3; j++)&lt;br /&gt;
        {&lt;br /&gt;
            if(registro[i][j] &amp;gt; best[i])&lt;br /&gt;
                best[i] = registro[i][j];&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    best.sort_in_descending_order(); // supponiamo nel nostro pseudolinguaggio esista una funzione di ordinamento qualunque&lt;br /&gt;
    return best;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Esame 29/05/2017 ==&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2017.05.29.tot.pdf 2017.05.29.tot.pdf]&lt;br /&gt;
=== Esercizio c.1 ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
condition okpartita&lt;br /&gt;
condition ok2chiama&lt;br /&gt;
condition ok2punteggio&lt;br /&gt;
condition ok2run[2][MAX]&lt;br /&gt;
int numpronti&lt;br /&gt;
int punteggio[2]&lt;br /&gt;
boolean partita=false&lt;br /&gt;
boolean partitafinita=false&lt;br /&gt;
chiamati = []&lt;br /&gt;
contabandiera[2]&lt;br /&gt;
int winner&lt;br /&gt;
&lt;br /&gt;
entry nuovapartita():&lt;br /&gt;
{&lt;br /&gt;
    punteggio[A] = punteggio[B] = 0;&lt;br /&gt;
    numpronti = 0;&lt;br /&gt;
    partita=true;&lt;br /&gt;
    okpartita.signal()&lt;br /&gt;
    chiamati = [];&lt;br /&gt;
}&lt;br /&gt;
entry chiama(l):&lt;br /&gt;
{&lt;br /&gt;
    if (numpronti&amp;lt;2*MAX)&lt;br /&gt;
    {&lt;br /&gt;
        ok2chiama.wait();&lt;br /&gt;
    }&lt;br /&gt;
    chiamati = l;&lt;br /&gt;
    contabandiera[A] = contabandiera[B] = 0&lt;br /&gt;
    winner = -1;&lt;br /&gt;
    for (s in n)&lt;br /&gt;
    {&lt;br /&gt;
        ok2run[A][s].signal();&lt;br /&gt;
        ok2run[B][s].signal()&lt;br /&gt;
    }&lt;br /&gt;
    ok2punteggio.wait();&lt;br /&gt;
    punteggio[winner++]&lt;br /&gt;
    if (max(punteggio) == 10)&lt;br /&gt;
    {&lt;br /&gt;
        partitafinita = true;&lt;br /&gt;
        for (s in A,B)&lt;br /&gt;
        {&lt;br /&gt;
            for (n in range(MAX))&lt;br /&gt;
            {&lt;br /&gt;
                ok2run[s][n].signal();&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    return punteggio;&lt;br /&gt;
}&lt;br /&gt;
entry pronto(s, n):&lt;br /&gt;
{&lt;br /&gt;
    if (partitafinita) return 1;&lt;br /&gt;
    if (!partita)&lt;br /&gt;
    {&lt;br /&gt;
        okpartita.wait();&lt;br /&gt;
    }&lt;br /&gt;
    numpronti++;&lt;br /&gt;
    if (numpronti&amp;gt;=2*MAX)&lt;br /&gt;
    {&lt;br /&gt;
        ok2chiama.signal();&lt;br /&gt;
    }&lt;br /&gt;
    if (!(n in chiamati))&lt;br /&gt;
    {&lt;br /&gt;
        ok2run[s][n].wait();&lt;br /&gt;
    }&lt;br /&gt;
    numpronti--;&lt;br /&gt;
    return 0 if partita else 1;&lt;br /&gt;
}&lt;br /&gt;
allabandiera(s, n):&lt;br /&gt;
{&lt;br /&gt;
    contabandiera[s]++;&lt;br /&gt;
    if (winner == -1 &amp;amp;&amp;amp; contabandiera[s] == len(chiamati))&lt;br /&gt;
    {&lt;br /&gt;
        winner = s;&lt;br /&gt;
    }&lt;br /&gt;
    if (contabandiera[A] == len(chiamati) &amp;amp;&amp;amp; contabandiera[B] == len(chiamati))&lt;br /&gt;
    {&lt;br /&gt;
        ok2punteggio.signal();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
casi da discutere:    &lt;br /&gt;
se arrivano studenti a pronto prima che il prof dichiara nuovapartita succedono guai.&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>LiberaL</name></author>
	</entry>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=Prove_scritte_2017&amp;diff=3015</id>
		<title>Prove scritte 2017</title>
		<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php?title=Prove_scritte_2017&amp;diff=3015"/>
		<updated>2023-05-26T12:09:53Z</updated>

		<summary type="html">&lt;p&gt;LiberaL: /* Esercizio c.2 (da controllare) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Esame 11/09/2017 ==&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2017.09.11.tot.pdf 2017.09.11.tot.pdf]&lt;br /&gt;
=== Esercizio c.1 ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
monitor crossing&lt;br /&gt;
&lt;br /&gt;
ok2dir[4];     //NESW&lt;br /&gt;
bool busy = false;&lt;br /&gt;
&lt;br /&gt;
pe entra(int dir)&lt;br /&gt;
   if (busy)&lt;br /&gt;
      ok2dir[dir].wait();&lt;br /&gt;
   busy = true;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
pe esci(int dir)&lt;br /&gt;
   busy = false;&lt;br /&gt;
   ok2dir[(dir + 1) % 4].signal();&lt;br /&gt;
   if (!busy)&lt;br /&gt;
      ok2dir[(dir + 2) % 4].signal();&lt;br /&gt;
   if (!busy)&lt;br /&gt;
      ok2dir[(dir + 3) % 4].signal();&lt;br /&gt;
   if (!busy)&lt;br /&gt;
      ok2dir[(dir + 4) % 4].signal();  //dir&lt;br /&gt;
&lt;br /&gt;
//alternativa più compatta&lt;br /&gt;
pe esci(int dir)&lt;br /&gt;
   busy = false;&lt;br /&gt;
   for (i = 0; i &amp;lt; 4; i++)&lt;br /&gt;
   if (!busy)&lt;br /&gt;
      ok2dir[(dir + i + 1) % 4].signal();&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Soluzione proposta 2 ==== &lt;br /&gt;
Soluzione proposta da [https://t.me/LLibera LLibera] e corretta da  [https://so.v2.cs.unibo.it/wiki/index.php/User:Flecart Flecart]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
const int N_DIRECTION = 4;&lt;br /&gt;
&lt;br /&gt;
// assumo N = 0, E = 1, S = 2, W = 3, oppure shiftati ciclicamente, è equivalente&lt;br /&gt;
&lt;br /&gt;
monitor crossing {&lt;br /&gt;
	bool free;										//l'incrocio è libero?&lt;br /&gt;
	int num_waiting[N_DIRECTION];&lt;br /&gt;
	condition okToCross[N_DIRECTION];				//free == True&lt;br /&gt;
	&lt;br /&gt;
	crossing() {&lt;br /&gt;
		free = True;								//parto con l'incrocio libero&lt;br /&gt;
		for (int i = 0; i &amp;lt; N_DIRECTION; i++) {&lt;br /&gt;
			num_waiting[i] = 0;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	procedure entry enter(int direction) {&lt;br /&gt;
		if(!free) {									//se l'incrocio non è libero&lt;br /&gt;
			num_waiting[direction]++;&lt;br /&gt;
			okToCross[direction].wait();			//aspetto nella mia direzione&lt;br /&gt;
			num_waiting[direction]--;&lt;br /&gt;
		}&lt;br /&gt;
													//ora sono sicurə che sia libero&lt;br /&gt;
		free = False;								//quindi lo dichiaro occupato&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	procedure entry exit(int direction) {&lt;br /&gt;
													//non devo aspettare niente per liberare l'incrocio&lt;br /&gt;
		free = True;								//lo dichiaro libero&lt;br /&gt;
		&lt;br /&gt;
		for (int i = 0; i &amp;lt; N_DIRECTION; i++) {&lt;br /&gt;
			int curr_dir = (direction + i + 1) % N_DIRECTION;&lt;br /&gt;
			if (num_waiting[curr_dir] &amp;gt; 0) {&lt;br /&gt;
				okToCross[curr_dir].signal();&lt;br /&gt;
				break;	// l'onere di risvegliare gli altri è stato passato al nuovo processo risvegliato, quindi esco.&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.2 (da controllare) ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// server[] = array contenente il PID di tutti i server&lt;br /&gt;
&lt;br /&gt;
#define BROADCAST server[0]&lt;br /&gt;
&lt;br /&gt;
server[0]&lt;br /&gt;
{&lt;br /&gt;
    while(true)&lt;br /&gt;
    {&lt;br /&gt;
        &amp;lt;msg, sender&amp;gt; = arecv(*); // ricevo il messaggio&lt;br /&gt;
        if (sender == BROADCAST)&lt;br /&gt;
            print(msg); // se il messaggio l'ho ricevuto da me stesso allora lo stampo&lt;br /&gt;
        else&lt;br /&gt;
            asend(*, &amp;lt;msg, getpid()&amp;gt;); // se il messaggio l'ho ricevuto da un client o da un altro server lo inoltro a tutti i server (compreso me stesso)&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
server[x] // x = 1...N-1&lt;br /&gt;
{&lt;br /&gt;
    while(true)&lt;br /&gt;
    {&lt;br /&gt;
        &amp;lt;msg, sender&amp;gt; = arecv(*); // ricevo il messaggio&lt;br /&gt;
        if (sender == BROADCAST)&lt;br /&gt;
            print(msg); // se il messaggio l'ho ricevuto dal server[0] allora lo stampo&lt;br /&gt;
        else&lt;br /&gt;
            asend(BROADCAST, &amp;lt;msg, getpid()&amp;gt;) // se il messaggio l'ho ricevuto da un client lo inoltro al server[0]&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Soluzione proposta 2 ====&lt;br /&gt;
&lt;br /&gt;
Soluzione proposta da [https://so.v2.cs.unibo.it/wiki/index.php/User:Flecart Flecart]&lt;br /&gt;
Soluzione corretta da [https://so.v2.cs.unibo.it/wiki/index.php/User:Gio Flecart friend]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
process server_0 {&lt;br /&gt;
&lt;br /&gt;
        while (true) {&lt;br /&gt;
                &amp;lt;msg, sender&amp;gt; = arecv(ANY);&lt;br /&gt;
                for (int i = 1 ; i &amp;lt; N; i++) {&lt;br /&gt;
                        asend(&amp;lt;msg, 0&amp;gt;, server[i]);&lt;br /&gt;
                        while(true){&lt;br /&gt;
                          msg = arecv(server[i]); // così so che tutti abbiano stampato.&lt;br /&gt;
                          if(msg==ACK)&lt;br /&gt;
                            break&lt;br /&gt;
                          asend(msg,server[0]);&lt;br /&gt;
                        }&lt;br /&gt;
                }&lt;br /&gt;
                print(msg);&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
process server_[i=1 to N - 1] {&lt;br /&gt;
        while (true) {&lt;br /&gt;
                &amp;lt;msg, sender&amp;gt; = arecv(ANY);&lt;br /&gt;
                if (sender == 0) {&lt;br /&gt;
                        print(msg);&lt;br /&gt;
                        asend(ACK, server[0]);&lt;br /&gt;
                } else {&lt;br /&gt;
                        asend(&amp;lt;msg, i&amp;gt;, server[0]);&lt;br /&gt;
                }&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Esame 17/07/2017 ==&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2017.07.17.tot.pdf 2017.07.17.tot.pdf]&lt;br /&gt;
=== Esercizio c.1 ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
monitor conf {&lt;br /&gt;
        condition finished;&lt;br /&gt;
        condition ready2present[max];&lt;br /&gt;
        bool arrived[max] = false;&lt;br /&gt;
        bool giachiamato[max] = false;&lt;br /&gt;
&lt;br /&gt;
        entry chiama(chiamato){&lt;br /&gt;
        if(arrived[chiamato] == true)&lt;br /&gt;
                ready2present[chiamato].signal;&lt;br /&gt;
                finished.wait;&lt;br /&gt;
                return true;&lt;br /&gt;
        else&lt;br /&gt;
                giachiamato[chiamato]= true&lt;br /&gt;
                return false;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        entry arrivato(nome){&lt;br /&gt;
                if(giachiamato[nome] == true)&lt;br /&gt;
                        return  false;&lt;br /&gt;
&lt;br /&gt;
                arrived[nome] = true;&lt;br /&gt;
                ok2present[nome].wait;&lt;br /&gt;
                return true;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        entry finepresentazione(nome){&lt;br /&gt;
                finished.signal;&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.2 (da controllare) ===&lt;br /&gt;
controllata da [https://t.me/LLibera LLibera] 13:41, 26 May 2023 (CEST) l'implementazione fornita gestisce solo il caso di arecv(ANY) e non arecv(mittente)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
si, è possibile: &lt;br /&gt;
&lt;br /&gt;
Implementare asend e arecv date bsend e brecv&lt;br /&gt;
&lt;br /&gt;
asend(pid_t dst, msg_type msg){&lt;br /&gt;
    bsend (&amp;lt;dst, msg&amp;gt;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
arecv(*){&lt;br /&gt;
  do {&lt;br /&gt;
    &amp;lt;dst, msg&amp;gt; = brecv(*);&lt;br /&gt;
  } while (dst != getpid())&lt;br /&gt;
  return msg;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
propongo (LLibera) quindi questa implementazione con gestione arecv da mittente specificato (sempre da controllare)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
//il messaggio mandato è la tripla &amp;lt;destinatario, mittente, messaggio&amp;gt;&lt;br /&gt;
&lt;br /&gt;
asend(pid_t dst, msg_type msg){&lt;br /&gt;
    bsend (&amp;lt;dst, getpid(), msg&amp;gt;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Queue of &amp;lt;pid_t, pid_t, msg_type&amp;gt; db;&lt;br /&gt;
arecv(pid_t sender) {&lt;br /&gt;
&lt;br /&gt;
  //devo controllare se nella coda ho già ricevuto il messaggio da quel mittente precedentemente, mentre aspettavo un messaggio da qualcun'altro&lt;br /&gt;
  //db.get(sender) cerca una tripla il cui mittente è sender&lt;br /&gt;
  //se trova il messaggio lo rimuove anche dal db.&lt;br /&gt;
  //se sender è ANY db.get(sender) ritorna (ed elimina da db) il primo che trova (FIFO), e if(db.isEmpty()) return NULL;&lt;br /&gt;
&lt;br /&gt;
  if( ( &amp;lt;dst, mit, msg&amp;gt; = db.get(sender) ) != NULL ) //se non lo trova&lt;br /&gt;
    return msg;&lt;br /&gt;
  do {&lt;br /&gt;
    &amp;lt;dst, mit, msg&amp;gt; = brecv(*);                 //ricevo&lt;br /&gt;
    bool message_for_me = (dst == getpid());    //il messaggio è per me?&lt;br /&gt;
    if( message_for_me &amp;amp;&amp;amp; ( mit == sender || sender == ANY ) )     //se devo ritornare il messaggio&lt;br /&gt;
      break;                                    //esci dal while&lt;br /&gt;
    if( sender != ANY &amp;amp;&amp;amp; message_for_me ) {     //se devo salvarlo (sender specificato e messaggio per me)&lt;br /&gt;
      //devo mettere in db i messaggi di altri mittenti, ricevuti quando ne aspettavo uno da un mittente specificato&lt;br /&gt;
      db.add(&amp;lt;dst, mit, msg&amp;gt;);&lt;br /&gt;
    }&lt;br /&gt;
  } while (!message_for_me)&lt;br /&gt;
  return msg;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Esame 19/06/2017 ==&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2017.06.19.tot.pdf 2017.06.19.tot.pdf]&lt;br /&gt;
=== Esercizio c.1 (da controllare)===&lt;br /&gt;
&lt;br /&gt;
* Mi sembra che ci sia un errore per il giodice, potrebbe succedere in un caso che il wait non si risvegli mai [[User:Flecart|Flecart]] ([[User talk:Flecart|talk]]) 15:38, 19 January 2023 (CET)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define NATLETI n&lt;br /&gt;
&lt;br /&gt;
condition ok2lancia[NATLETI];&lt;br /&gt;
condition ok2giudice;&lt;br /&gt;
&lt;br /&gt;
int counter[NATLETI];&lt;br /&gt;
int ultimo_tiro;&lt;br /&gt;
float registro[NATLETI][3];&lt;br /&gt;
&lt;br /&gt;
Procedure entry: boolean pronto(int i)&lt;br /&gt;
{&lt;br /&gt;
    if(!(i == 0 &amp;amp;&amp;amp; counter[i] == 0)) // se è il primo lancio non devo metterlo in wait&lt;br /&gt;
        ok2lancia[i].wait()&lt;br /&gt;
    if(counter[i] &amp;lt; 3)&lt;br /&gt;
        return true;&lt;br /&gt;
    else&lt;br /&gt;
        return false;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: void lanciato (int i)&lt;br /&gt;
{&lt;br /&gt;
    counter[i]++;&lt;br /&gt;
    ultimo_tiro = i;&lt;br /&gt;
    ok2giudice.signal();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: int lanciofatto()&lt;br /&gt;
{&lt;br /&gt;
    ok2giudice.wait()&lt;br /&gt;
    if(ultimo_tiro == NATLETI-1 &amp;amp;&amp;amp; counter[0] == 3)&lt;br /&gt;
        return -1;  // devo invalidare la condizione per uscire dal while, quindi se nessuno deve più lanciare ritorno -1&lt;br /&gt;
    else&lt;br /&gt;
        return ultimo_tiro;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: void registraechiama(int i, float m)&lt;br /&gt;
{&lt;br /&gt;
    registro[i][counter[i]-1] = m; // il secondo indice indica l'iesimo lancio -1 (perchè iniziamo a contare da zero)&lt;br /&gt;
    if(i == NATLETI-1) // se ha appena tirato l'ultimo atleta non posso dare il via a NATLETI (perchè non esiste), quindi faccio ricominciare il giro&lt;br /&gt;
        ok2lancia[0].signal();&lt;br /&gt;
    else&lt;br /&gt;
        ok2lancia[i+1].signal();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: int classifica()&lt;br /&gt;
{&lt;br /&gt;
    int best[NATLETI];&lt;br /&gt;
    for(int i = 0; i &amp;lt; NATLETI; i++)&lt;br /&gt;
    {&lt;br /&gt;
        for(int j = 0; j &amp;lt; 3; j++)&lt;br /&gt;
        {&lt;br /&gt;
            if(registro[i][j] &amp;gt; best[i])&lt;br /&gt;
                best[i] = registro[i][j];&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    best.sort_in_descending_order(); // supponiamo nel nostro pseudolinguaggio esista una funzione di ordinamento qualunque&lt;br /&gt;
    return best;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Esame 29/05/2017 ==&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2017.05.29.tot.pdf 2017.05.29.tot.pdf]&lt;br /&gt;
=== Esercizio c.1 ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
condition okpartita&lt;br /&gt;
condition ok2chiama&lt;br /&gt;
condition ok2punteggio&lt;br /&gt;
condition ok2run[2][MAX]&lt;br /&gt;
int numpronti&lt;br /&gt;
int punteggio[2]&lt;br /&gt;
boolean partita=false&lt;br /&gt;
boolean partitafinita=false&lt;br /&gt;
chiamati = []&lt;br /&gt;
contabandiera[2]&lt;br /&gt;
int winner&lt;br /&gt;
&lt;br /&gt;
entry nuovapartita():&lt;br /&gt;
{&lt;br /&gt;
    punteggio[A] = punteggio[B] = 0;&lt;br /&gt;
    numpronti = 0;&lt;br /&gt;
    partita=true;&lt;br /&gt;
    okpartita.signal()&lt;br /&gt;
    chiamati = [];&lt;br /&gt;
}&lt;br /&gt;
entry chiama(l):&lt;br /&gt;
{&lt;br /&gt;
    if (numpronti&amp;lt;2*MAX)&lt;br /&gt;
    {&lt;br /&gt;
        ok2chiama.wait();&lt;br /&gt;
    }&lt;br /&gt;
    chiamati = l;&lt;br /&gt;
    contabandiera[A] = contabandiera[B] = 0&lt;br /&gt;
    winner = -1;&lt;br /&gt;
    for (s in n)&lt;br /&gt;
    {&lt;br /&gt;
        ok2run[A][s].signal();&lt;br /&gt;
        ok2run[B][s].signal()&lt;br /&gt;
    }&lt;br /&gt;
    ok2punteggio.wait();&lt;br /&gt;
    punteggio[winner++]&lt;br /&gt;
    if (max(punteggio) == 10)&lt;br /&gt;
    {&lt;br /&gt;
        partitafinita = true;&lt;br /&gt;
        for (s in A,B)&lt;br /&gt;
        {&lt;br /&gt;
            for (n in range(MAX))&lt;br /&gt;
            {&lt;br /&gt;
                ok2run[s][n].signal();&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    return punteggio;&lt;br /&gt;
}&lt;br /&gt;
entry pronto(s, n):&lt;br /&gt;
{&lt;br /&gt;
    if (partitafinita) return 1;&lt;br /&gt;
    if (!partita)&lt;br /&gt;
    {&lt;br /&gt;
        okpartita.wait();&lt;br /&gt;
    }&lt;br /&gt;
    numpronti++;&lt;br /&gt;
    if (numpronti&amp;gt;=2*MAX)&lt;br /&gt;
    {&lt;br /&gt;
        ok2chiama.signal();&lt;br /&gt;
    }&lt;br /&gt;
    if (!(n in chiamati))&lt;br /&gt;
    {&lt;br /&gt;
        ok2run[s][n].wait();&lt;br /&gt;
    }&lt;br /&gt;
    numpronti--;&lt;br /&gt;
    return 0 if partita else 1;&lt;br /&gt;
}&lt;br /&gt;
allabandiera(s, n):&lt;br /&gt;
{&lt;br /&gt;
    contabandiera[s]++;&lt;br /&gt;
    if (winner == -1 &amp;amp;&amp;amp; contabandiera[s] == len(chiamati))&lt;br /&gt;
    {&lt;br /&gt;
        winner = s;&lt;br /&gt;
    }&lt;br /&gt;
    if (contabandiera[A] == len(chiamati) &amp;amp;&amp;amp; contabandiera[B] == len(chiamati))&lt;br /&gt;
    {&lt;br /&gt;
        ok2punteggio.signal();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
casi da discutere:    &lt;br /&gt;
se arrivano studenti a pronto prima che il prof dichiara nuovapartita succedono guai.&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>LiberaL</name></author>
	</entry>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=Prove_scritte_2017&amp;diff=3014</id>
		<title>Prove scritte 2017</title>
		<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php?title=Prove_scritte_2017&amp;diff=3014"/>
		<updated>2023-05-26T12:07:54Z</updated>

		<summary type="html">&lt;p&gt;LiberaL: /* Esercizio c.2 (da controllare) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Esame 11/09/2017 ==&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2017.09.11.tot.pdf 2017.09.11.tot.pdf]&lt;br /&gt;
=== Esercizio c.1 ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
monitor crossing&lt;br /&gt;
&lt;br /&gt;
ok2dir[4];     //NESW&lt;br /&gt;
bool busy = false;&lt;br /&gt;
&lt;br /&gt;
pe entra(int dir)&lt;br /&gt;
   if (busy)&lt;br /&gt;
      ok2dir[dir].wait();&lt;br /&gt;
   busy = true;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
pe esci(int dir)&lt;br /&gt;
   busy = false;&lt;br /&gt;
   ok2dir[(dir + 1) % 4].signal();&lt;br /&gt;
   if (!busy)&lt;br /&gt;
      ok2dir[(dir + 2) % 4].signal();&lt;br /&gt;
   if (!busy)&lt;br /&gt;
      ok2dir[(dir + 3) % 4].signal();&lt;br /&gt;
   if (!busy)&lt;br /&gt;
      ok2dir[(dir + 4) % 4].signal();  //dir&lt;br /&gt;
&lt;br /&gt;
//alternativa più compatta&lt;br /&gt;
pe esci(int dir)&lt;br /&gt;
   busy = false;&lt;br /&gt;
   for (i = 0; i &amp;lt; 4; i++)&lt;br /&gt;
   if (!busy)&lt;br /&gt;
      ok2dir[(dir + i + 1) % 4].signal();&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Soluzione proposta 2 ==== &lt;br /&gt;
Soluzione proposta da [https://t.me/LLibera LLibera] e corretta da  [https://so.v2.cs.unibo.it/wiki/index.php/User:Flecart Flecart]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
const int N_DIRECTION = 4;&lt;br /&gt;
&lt;br /&gt;
// assumo N = 0, E = 1, S = 2, W = 3, oppure shiftati ciclicamente, è equivalente&lt;br /&gt;
&lt;br /&gt;
monitor crossing {&lt;br /&gt;
	bool free;										//l'incrocio è libero?&lt;br /&gt;
	int num_waiting[N_DIRECTION];&lt;br /&gt;
	condition okToCross[N_DIRECTION];				//free == True&lt;br /&gt;
	&lt;br /&gt;
	crossing() {&lt;br /&gt;
		free = True;								//parto con l'incrocio libero&lt;br /&gt;
		for (int i = 0; i &amp;lt; N_DIRECTION; i++) {&lt;br /&gt;
			num_waiting[i] = 0;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	procedure entry enter(int direction) {&lt;br /&gt;
		if(!free) {									//se l'incrocio non è libero&lt;br /&gt;
			num_waiting[direction]++;&lt;br /&gt;
			okToCross[direction].wait();			//aspetto nella mia direzione&lt;br /&gt;
			num_waiting[direction]--;&lt;br /&gt;
		}&lt;br /&gt;
													//ora sono sicurə che sia libero&lt;br /&gt;
		free = False;								//quindi lo dichiaro occupato&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	procedure entry exit(int direction) {&lt;br /&gt;
													//non devo aspettare niente per liberare l'incrocio&lt;br /&gt;
		free = True;								//lo dichiaro libero&lt;br /&gt;
		&lt;br /&gt;
		for (int i = 0; i &amp;lt; N_DIRECTION; i++) {&lt;br /&gt;
			int curr_dir = (direction + i + 1) % N_DIRECTION;&lt;br /&gt;
			if (num_waiting[curr_dir] &amp;gt; 0) {&lt;br /&gt;
				okToCross[curr_dir].signal();&lt;br /&gt;
				break;	// l'onere di risvegliare gli altri è stato passato al nuovo processo risvegliato, quindi esco.&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.2 (da controllare) ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// server[] = array contenente il PID di tutti i server&lt;br /&gt;
&lt;br /&gt;
#define BROADCAST server[0]&lt;br /&gt;
&lt;br /&gt;
server[0]&lt;br /&gt;
{&lt;br /&gt;
    while(true)&lt;br /&gt;
    {&lt;br /&gt;
        &amp;lt;msg, sender&amp;gt; = arecv(*); // ricevo il messaggio&lt;br /&gt;
        if (sender == BROADCAST)&lt;br /&gt;
            print(msg); // se il messaggio l'ho ricevuto da me stesso allora lo stampo&lt;br /&gt;
        else&lt;br /&gt;
            asend(*, &amp;lt;msg, getpid()&amp;gt;); // se il messaggio l'ho ricevuto da un client o da un altro server lo inoltro a tutti i server (compreso me stesso)&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
server[x] // x = 1...N-1&lt;br /&gt;
{&lt;br /&gt;
    while(true)&lt;br /&gt;
    {&lt;br /&gt;
        &amp;lt;msg, sender&amp;gt; = arecv(*); // ricevo il messaggio&lt;br /&gt;
        if (sender == BROADCAST)&lt;br /&gt;
            print(msg); // se il messaggio l'ho ricevuto dal server[0] allora lo stampo&lt;br /&gt;
        else&lt;br /&gt;
            asend(BROADCAST, &amp;lt;msg, getpid()&amp;gt;) // se il messaggio l'ho ricevuto da un client lo inoltro al server[0]&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Soluzione proposta 2 ====&lt;br /&gt;
&lt;br /&gt;
Soluzione proposta da [https://so.v2.cs.unibo.it/wiki/index.php/User:Flecart Flecart]&lt;br /&gt;
Soluzione corretta da [https://so.v2.cs.unibo.it/wiki/index.php/User:Gio Flecart friend]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
process server_0 {&lt;br /&gt;
&lt;br /&gt;
        while (true) {&lt;br /&gt;
                &amp;lt;msg, sender&amp;gt; = arecv(ANY);&lt;br /&gt;
                for (int i = 1 ; i &amp;lt; N; i++) {&lt;br /&gt;
                        asend(&amp;lt;msg, 0&amp;gt;, server[i]);&lt;br /&gt;
                        while(true){&lt;br /&gt;
                          msg = arecv(server[i]); // così so che tutti abbiano stampato.&lt;br /&gt;
                          if(msg==ACK)&lt;br /&gt;
                            break&lt;br /&gt;
                          asend(msg,server[0]);&lt;br /&gt;
                        }&lt;br /&gt;
                }&lt;br /&gt;
                print(msg);&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
process server_[i=1 to N - 1] {&lt;br /&gt;
        while (true) {&lt;br /&gt;
                &amp;lt;msg, sender&amp;gt; = arecv(ANY);&lt;br /&gt;
                if (sender == 0) {&lt;br /&gt;
                        print(msg);&lt;br /&gt;
                        asend(ACK, server[0]);&lt;br /&gt;
                } else {&lt;br /&gt;
                        asend(&amp;lt;msg, i&amp;gt;, server[0]);&lt;br /&gt;
                }&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Esame 17/07/2017 ==&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2017.07.17.tot.pdf 2017.07.17.tot.pdf]&lt;br /&gt;
=== Esercizio c.1 ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
monitor conf {&lt;br /&gt;
        condition finished;&lt;br /&gt;
        condition ready2present[max];&lt;br /&gt;
        bool arrived[max] = false;&lt;br /&gt;
        bool giachiamato[max] = false;&lt;br /&gt;
&lt;br /&gt;
        entry chiama(chiamato){&lt;br /&gt;
        if(arrived[chiamato] == true)&lt;br /&gt;
                ready2present[chiamato].signal;&lt;br /&gt;
                finished.wait;&lt;br /&gt;
                return true;&lt;br /&gt;
        else&lt;br /&gt;
                giachiamato[chiamato]= true&lt;br /&gt;
                return false;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        entry arrivato(nome){&lt;br /&gt;
                if(giachiamato[nome] == true)&lt;br /&gt;
                        return  false;&lt;br /&gt;
&lt;br /&gt;
                arrived[nome] = true;&lt;br /&gt;
                ok2present[nome].wait;&lt;br /&gt;
                return true;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        entry finepresentazione(nome){&lt;br /&gt;
                finished.signal;&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.2 (da controllare) ===&lt;br /&gt;
controllata da [https://t.me/LLibera LLibera] 13:41, 26 May 2023 (CEST) l'implementazione fornita gestisce solo il caso di arecv(ANY) e non arecv(mittente)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
si, è possibile: &lt;br /&gt;
&lt;br /&gt;
Implementare asend e arecv date bsend e brecv&lt;br /&gt;
&lt;br /&gt;
asend(pid_t dst, msg_type msg){&lt;br /&gt;
    bsend (&amp;lt;dst, msg&amp;gt;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
arecv(*){&lt;br /&gt;
  do {&lt;br /&gt;
    &amp;lt;dst, msg&amp;gt; = brecv(*);&lt;br /&gt;
  } while (dst != getpid())&lt;br /&gt;
  return msg;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
propongo (LLibera) quindi questa implementazione con gestione arecv da mittente specificato (sempre da controllare)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
//il messaggio mandato è la tripla &amp;lt;destinatario, mittente, messaggio&amp;gt;&lt;br /&gt;
&lt;br /&gt;
asend(pid_t dst, msg_type msg){&lt;br /&gt;
    bsend (&amp;lt;dst, getpid(), msg&amp;gt;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Queue of &amp;lt;pid_t, pid_t, msg_type&amp;gt; db;&lt;br /&gt;
arecv(pid_t sender) {&lt;br /&gt;
&lt;br /&gt;
  //devo controllare se nella coda ho già ricevuto il messaggio da quel mittente precedentemente, mentre aspettavo un messaggio da qualcun'altro&lt;br /&gt;
  //db.get(sender) cerca una tripla il cui mittente è sender&lt;br /&gt;
  //se trova il messaggio lo rimuove anche dal db.&lt;br /&gt;
  //se sender è ANY db.get(sender) ritorna (ed elimina da db) il primo che trova (FIFO), e if(db.isEmpty()) return NULL;&lt;br /&gt;
&lt;br /&gt;
  if( ( &amp;lt;dst, mit, msg&amp;gt; = db.get(sender) ) != NULL ) //se non lo trova&lt;br /&gt;
    return msg;&lt;br /&gt;
  do {&lt;br /&gt;
    &amp;lt;dst, mit, msg&amp;gt; = brecv(*);                 //ricevo&lt;br /&gt;
    bool message_for_me = (dst == getpid());    //il messaggio è per me?&lt;br /&gt;
    if( message_for_me &amp;amp;&amp;amp; ( mit == sender || sender == ANY ) )     //se il messaggio è del mittente specificato&lt;br /&gt;
      break;                                    //esci dal while&lt;br /&gt;
    if( sender != ANY &amp;amp;&amp;amp; message_for_me ) {     //se devo salvarlo (sender specificato e messaggio per me)&lt;br /&gt;
      //devo mettere in db i messaggi di altri mittenti, ricevuti quando ne aspettavo uno da un mittente specificato&lt;br /&gt;
      db.add(&amp;lt;dst, mit, msg&amp;gt;);&lt;br /&gt;
    }&lt;br /&gt;
  } while (!message_for_me)&lt;br /&gt;
  return msg;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Esame 19/06/2017 ==&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2017.06.19.tot.pdf 2017.06.19.tot.pdf]&lt;br /&gt;
=== Esercizio c.1 (da controllare)===&lt;br /&gt;
&lt;br /&gt;
* Mi sembra che ci sia un errore per il giodice, potrebbe succedere in un caso che il wait non si risvegli mai [[User:Flecart|Flecart]] ([[User talk:Flecart|talk]]) 15:38, 19 January 2023 (CET)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define NATLETI n&lt;br /&gt;
&lt;br /&gt;
condition ok2lancia[NATLETI];&lt;br /&gt;
condition ok2giudice;&lt;br /&gt;
&lt;br /&gt;
int counter[NATLETI];&lt;br /&gt;
int ultimo_tiro;&lt;br /&gt;
float registro[NATLETI][3];&lt;br /&gt;
&lt;br /&gt;
Procedure entry: boolean pronto(int i)&lt;br /&gt;
{&lt;br /&gt;
    if(!(i == 0 &amp;amp;&amp;amp; counter[i] == 0)) // se è il primo lancio non devo metterlo in wait&lt;br /&gt;
        ok2lancia[i].wait()&lt;br /&gt;
    if(counter[i] &amp;lt; 3)&lt;br /&gt;
        return true;&lt;br /&gt;
    else&lt;br /&gt;
        return false;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: void lanciato (int i)&lt;br /&gt;
{&lt;br /&gt;
    counter[i]++;&lt;br /&gt;
    ultimo_tiro = i;&lt;br /&gt;
    ok2giudice.signal();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: int lanciofatto()&lt;br /&gt;
{&lt;br /&gt;
    ok2giudice.wait()&lt;br /&gt;
    if(ultimo_tiro == NATLETI-1 &amp;amp;&amp;amp; counter[0] == 3)&lt;br /&gt;
        return -1;  // devo invalidare la condizione per uscire dal while, quindi se nessuno deve più lanciare ritorno -1&lt;br /&gt;
    else&lt;br /&gt;
        return ultimo_tiro;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: void registraechiama(int i, float m)&lt;br /&gt;
{&lt;br /&gt;
    registro[i][counter[i]-1] = m; // il secondo indice indica l'iesimo lancio -1 (perchè iniziamo a contare da zero)&lt;br /&gt;
    if(i == NATLETI-1) // se ha appena tirato l'ultimo atleta non posso dare il via a NATLETI (perchè non esiste), quindi faccio ricominciare il giro&lt;br /&gt;
        ok2lancia[0].signal();&lt;br /&gt;
    else&lt;br /&gt;
        ok2lancia[i+1].signal();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: int classifica()&lt;br /&gt;
{&lt;br /&gt;
    int best[NATLETI];&lt;br /&gt;
    for(int i = 0; i &amp;lt; NATLETI; i++)&lt;br /&gt;
    {&lt;br /&gt;
        for(int j = 0; j &amp;lt; 3; j++)&lt;br /&gt;
        {&lt;br /&gt;
            if(registro[i][j] &amp;gt; best[i])&lt;br /&gt;
                best[i] = registro[i][j];&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    best.sort_in_descending_order(); // supponiamo nel nostro pseudolinguaggio esista una funzione di ordinamento qualunque&lt;br /&gt;
    return best;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Esame 29/05/2017 ==&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2017.05.29.tot.pdf 2017.05.29.tot.pdf]&lt;br /&gt;
=== Esercizio c.1 ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
condition okpartita&lt;br /&gt;
condition ok2chiama&lt;br /&gt;
condition ok2punteggio&lt;br /&gt;
condition ok2run[2][MAX]&lt;br /&gt;
int numpronti&lt;br /&gt;
int punteggio[2]&lt;br /&gt;
boolean partita=false&lt;br /&gt;
boolean partitafinita=false&lt;br /&gt;
chiamati = []&lt;br /&gt;
contabandiera[2]&lt;br /&gt;
int winner&lt;br /&gt;
&lt;br /&gt;
entry nuovapartita():&lt;br /&gt;
{&lt;br /&gt;
    punteggio[A] = punteggio[B] = 0;&lt;br /&gt;
    numpronti = 0;&lt;br /&gt;
    partita=true;&lt;br /&gt;
    okpartita.signal()&lt;br /&gt;
    chiamati = [];&lt;br /&gt;
}&lt;br /&gt;
entry chiama(l):&lt;br /&gt;
{&lt;br /&gt;
    if (numpronti&amp;lt;2*MAX)&lt;br /&gt;
    {&lt;br /&gt;
        ok2chiama.wait();&lt;br /&gt;
    }&lt;br /&gt;
    chiamati = l;&lt;br /&gt;
    contabandiera[A] = contabandiera[B] = 0&lt;br /&gt;
    winner = -1;&lt;br /&gt;
    for (s in n)&lt;br /&gt;
    {&lt;br /&gt;
        ok2run[A][s].signal();&lt;br /&gt;
        ok2run[B][s].signal()&lt;br /&gt;
    }&lt;br /&gt;
    ok2punteggio.wait();&lt;br /&gt;
    punteggio[winner++]&lt;br /&gt;
    if (max(punteggio) == 10)&lt;br /&gt;
    {&lt;br /&gt;
        partitafinita = true;&lt;br /&gt;
        for (s in A,B)&lt;br /&gt;
        {&lt;br /&gt;
            for (n in range(MAX))&lt;br /&gt;
            {&lt;br /&gt;
                ok2run[s][n].signal();&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    return punteggio;&lt;br /&gt;
}&lt;br /&gt;
entry pronto(s, n):&lt;br /&gt;
{&lt;br /&gt;
    if (partitafinita) return 1;&lt;br /&gt;
    if (!partita)&lt;br /&gt;
    {&lt;br /&gt;
        okpartita.wait();&lt;br /&gt;
    }&lt;br /&gt;
    numpronti++;&lt;br /&gt;
    if (numpronti&amp;gt;=2*MAX)&lt;br /&gt;
    {&lt;br /&gt;
        ok2chiama.signal();&lt;br /&gt;
    }&lt;br /&gt;
    if (!(n in chiamati))&lt;br /&gt;
    {&lt;br /&gt;
        ok2run[s][n].wait();&lt;br /&gt;
    }&lt;br /&gt;
    numpronti--;&lt;br /&gt;
    return 0 if partita else 1;&lt;br /&gt;
}&lt;br /&gt;
allabandiera(s, n):&lt;br /&gt;
{&lt;br /&gt;
    contabandiera[s]++;&lt;br /&gt;
    if (winner == -1 &amp;amp;&amp;amp; contabandiera[s] == len(chiamati))&lt;br /&gt;
    {&lt;br /&gt;
        winner = s;&lt;br /&gt;
    }&lt;br /&gt;
    if (contabandiera[A] == len(chiamati) &amp;amp;&amp;amp; contabandiera[B] == len(chiamati))&lt;br /&gt;
    {&lt;br /&gt;
        ok2punteggio.signal();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
casi da discutere:    &lt;br /&gt;
se arrivano studenti a pronto prima che il prof dichiara nuovapartita succedono guai.&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>LiberaL</name></author>
	</entry>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=Prove_scritte_2017&amp;diff=3013</id>
		<title>Prove scritte 2017</title>
		<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php?title=Prove_scritte_2017&amp;diff=3013"/>
		<updated>2023-05-26T12:03:07Z</updated>

		<summary type="html">&lt;p&gt;LiberaL: /* Esercizio c.2 (da controllare) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Esame 11/09/2017 ==&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2017.09.11.tot.pdf 2017.09.11.tot.pdf]&lt;br /&gt;
=== Esercizio c.1 ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
monitor crossing&lt;br /&gt;
&lt;br /&gt;
ok2dir[4];     //NESW&lt;br /&gt;
bool busy = false;&lt;br /&gt;
&lt;br /&gt;
pe entra(int dir)&lt;br /&gt;
   if (busy)&lt;br /&gt;
      ok2dir[dir].wait();&lt;br /&gt;
   busy = true;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
pe esci(int dir)&lt;br /&gt;
   busy = false;&lt;br /&gt;
   ok2dir[(dir + 1) % 4].signal();&lt;br /&gt;
   if (!busy)&lt;br /&gt;
      ok2dir[(dir + 2) % 4].signal();&lt;br /&gt;
   if (!busy)&lt;br /&gt;
      ok2dir[(dir + 3) % 4].signal();&lt;br /&gt;
   if (!busy)&lt;br /&gt;
      ok2dir[(dir + 4) % 4].signal();  //dir&lt;br /&gt;
&lt;br /&gt;
//alternativa più compatta&lt;br /&gt;
pe esci(int dir)&lt;br /&gt;
   busy = false;&lt;br /&gt;
   for (i = 0; i &amp;lt; 4; i++)&lt;br /&gt;
   if (!busy)&lt;br /&gt;
      ok2dir[(dir + i + 1) % 4].signal();&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Soluzione proposta 2 ==== &lt;br /&gt;
Soluzione proposta da [https://t.me/LLibera LLibera] e corretta da  [https://so.v2.cs.unibo.it/wiki/index.php/User:Flecart Flecart]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
const int N_DIRECTION = 4;&lt;br /&gt;
&lt;br /&gt;
// assumo N = 0, E = 1, S = 2, W = 3, oppure shiftati ciclicamente, è equivalente&lt;br /&gt;
&lt;br /&gt;
monitor crossing {&lt;br /&gt;
	bool free;										//l'incrocio è libero?&lt;br /&gt;
	int num_waiting[N_DIRECTION];&lt;br /&gt;
	condition okToCross[N_DIRECTION];				//free == True&lt;br /&gt;
	&lt;br /&gt;
	crossing() {&lt;br /&gt;
		free = True;								//parto con l'incrocio libero&lt;br /&gt;
		for (int i = 0; i &amp;lt; N_DIRECTION; i++) {&lt;br /&gt;
			num_waiting[i] = 0;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	procedure entry enter(int direction) {&lt;br /&gt;
		if(!free) {									//se l'incrocio non è libero&lt;br /&gt;
			num_waiting[direction]++;&lt;br /&gt;
			okToCross[direction].wait();			//aspetto nella mia direzione&lt;br /&gt;
			num_waiting[direction]--;&lt;br /&gt;
		}&lt;br /&gt;
													//ora sono sicurə che sia libero&lt;br /&gt;
		free = False;								//quindi lo dichiaro occupato&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	procedure entry exit(int direction) {&lt;br /&gt;
													//non devo aspettare niente per liberare l'incrocio&lt;br /&gt;
		free = True;								//lo dichiaro libero&lt;br /&gt;
		&lt;br /&gt;
		for (int i = 0; i &amp;lt; N_DIRECTION; i++) {&lt;br /&gt;
			int curr_dir = (direction + i + 1) % N_DIRECTION;&lt;br /&gt;
			if (num_waiting[curr_dir] &amp;gt; 0) {&lt;br /&gt;
				okToCross[curr_dir].signal();&lt;br /&gt;
				break;	// l'onere di risvegliare gli altri è stato passato al nuovo processo risvegliato, quindi esco.&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.2 (da controllare) ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// server[] = array contenente il PID di tutti i server&lt;br /&gt;
&lt;br /&gt;
#define BROADCAST server[0]&lt;br /&gt;
&lt;br /&gt;
server[0]&lt;br /&gt;
{&lt;br /&gt;
    while(true)&lt;br /&gt;
    {&lt;br /&gt;
        &amp;lt;msg, sender&amp;gt; = arecv(*); // ricevo il messaggio&lt;br /&gt;
        if (sender == BROADCAST)&lt;br /&gt;
            print(msg); // se il messaggio l'ho ricevuto da me stesso allora lo stampo&lt;br /&gt;
        else&lt;br /&gt;
            asend(*, &amp;lt;msg, getpid()&amp;gt;); // se il messaggio l'ho ricevuto da un client o da un altro server lo inoltro a tutti i server (compreso me stesso)&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
server[x] // x = 1...N-1&lt;br /&gt;
{&lt;br /&gt;
    while(true)&lt;br /&gt;
    {&lt;br /&gt;
        &amp;lt;msg, sender&amp;gt; = arecv(*); // ricevo il messaggio&lt;br /&gt;
        if (sender == BROADCAST)&lt;br /&gt;
            print(msg); // se il messaggio l'ho ricevuto dal server[0] allora lo stampo&lt;br /&gt;
        else&lt;br /&gt;
            asend(BROADCAST, &amp;lt;msg, getpid()&amp;gt;) // se il messaggio l'ho ricevuto da un client lo inoltro al server[0]&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Soluzione proposta 2 ====&lt;br /&gt;
&lt;br /&gt;
Soluzione proposta da [https://so.v2.cs.unibo.it/wiki/index.php/User:Flecart Flecart]&lt;br /&gt;
Soluzione corretta da [https://so.v2.cs.unibo.it/wiki/index.php/User:Gio Flecart friend]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
process server_0 {&lt;br /&gt;
&lt;br /&gt;
        while (true) {&lt;br /&gt;
                &amp;lt;msg, sender&amp;gt; = arecv(ANY);&lt;br /&gt;
                for (int i = 1 ; i &amp;lt; N; i++) {&lt;br /&gt;
                        asend(&amp;lt;msg, 0&amp;gt;, server[i]);&lt;br /&gt;
                        while(true){&lt;br /&gt;
                          msg = arecv(server[i]); // così so che tutti abbiano stampato.&lt;br /&gt;
                          if(msg==ACK)&lt;br /&gt;
                            break&lt;br /&gt;
                          asend(msg,server[0]);&lt;br /&gt;
                        }&lt;br /&gt;
                }&lt;br /&gt;
                print(msg);&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
process server_[i=1 to N - 1] {&lt;br /&gt;
        while (true) {&lt;br /&gt;
                &amp;lt;msg, sender&amp;gt; = arecv(ANY);&lt;br /&gt;
                if (sender == 0) {&lt;br /&gt;
                        print(msg);&lt;br /&gt;
                        asend(ACK, server[0]);&lt;br /&gt;
                } else {&lt;br /&gt;
                        asend(&amp;lt;msg, i&amp;gt;, server[0]);&lt;br /&gt;
                }&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Esame 17/07/2017 ==&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2017.07.17.tot.pdf 2017.07.17.tot.pdf]&lt;br /&gt;
=== Esercizio c.1 ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
monitor conf {&lt;br /&gt;
        condition finished;&lt;br /&gt;
        condition ready2present[max];&lt;br /&gt;
        bool arrived[max] = false;&lt;br /&gt;
        bool giachiamato[max] = false;&lt;br /&gt;
&lt;br /&gt;
        entry chiama(chiamato){&lt;br /&gt;
        if(arrived[chiamato] == true)&lt;br /&gt;
                ready2present[chiamato].signal;&lt;br /&gt;
                finished.wait;&lt;br /&gt;
                return true;&lt;br /&gt;
        else&lt;br /&gt;
                giachiamato[chiamato]= true&lt;br /&gt;
                return false;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        entry arrivato(nome){&lt;br /&gt;
                if(giachiamato[nome] == true)&lt;br /&gt;
                        return  false;&lt;br /&gt;
&lt;br /&gt;
                arrived[nome] = true;&lt;br /&gt;
                ok2present[nome].wait;&lt;br /&gt;
                return true;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        entry finepresentazione(nome){&lt;br /&gt;
                finished.signal;&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.2 (da controllare) ===&lt;br /&gt;
controllata da [https://t.me/LLibera LLibera] 13:41, 26 May 2023 (CEST) l'implementazione fornita gestisce solo il caso di arecv(ANY) e non arecv(mittente)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
si, è possibile: &lt;br /&gt;
&lt;br /&gt;
Implementare asend e arecv date bsend e brecv&lt;br /&gt;
&lt;br /&gt;
asend(pid_t dst, msg_type msg){&lt;br /&gt;
    bsend (&amp;lt;dst, msg&amp;gt;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
arecv(*){&lt;br /&gt;
  do {&lt;br /&gt;
    &amp;lt;dst, msg&amp;gt; = brecv(*);&lt;br /&gt;
  } while (dst != getpid())&lt;br /&gt;
  return msg;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
propongo (LLibera) quindi questa implementazione con gestione arecv da mittente specificato (sempre da controllare)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
//il messaggio mandato è la tripla &amp;lt;destinatario, mittente, messaggio&amp;gt;&lt;br /&gt;
&lt;br /&gt;
asend(pid_t dst, msg_type msg){&lt;br /&gt;
    bsend (&amp;lt;dst, getpid(), msg&amp;gt;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Queue of &amp;lt;pid_t, pid_t, msg_type&amp;gt; db;&lt;br /&gt;
arecv(pid_t sender) {&lt;br /&gt;
&lt;br /&gt;
  //devo controllare se nella coda ho già ricevuto il messaggio da quel mittente precedentemente, mentre aspettavo un messaggio da qualcun'altro&lt;br /&gt;
  //db.get(sender) cerca una tripla il cui mittente è sender&lt;br /&gt;
  //se trova il messaggio lo rimuove anche dal db.&lt;br /&gt;
  //se sender è ANY db.get(sender) ritorna il primo che trova (FIFO), e if(db.isEmpty()) return NULL;&lt;br /&gt;
&lt;br /&gt;
  if( ( &amp;lt;dst, mit, msg&amp;gt; = db.get(sender) ) != NULL ) //se non lo trova&lt;br /&gt;
    return msg;&lt;br /&gt;
  do {&lt;br /&gt;
    &amp;lt;dst, mit, msg&amp;gt; = brecv(*);                 //ricevo&lt;br /&gt;
    bool message_for_me = (dst == getpid());    //il messaggio è per me?&lt;br /&gt;
    if( message_for_me &amp;amp;&amp;amp; ( mit == sender || sender == ANY ) )     //se il messaggio è del mittente specificato&lt;br /&gt;
      break;                                    //esci dal while&lt;br /&gt;
    if( sender != ANY &amp;amp;&amp;amp; message_for_me ) {     //se devo salvarlo (sender specificato e messaggio per me)&lt;br /&gt;
      //devo mettere in db i messaggi di altri mittenti, ricevuti quando ne aspettavo uno da un mittente specificato&lt;br /&gt;
      db.add(&amp;lt;dst, mit, msg&amp;gt;);&lt;br /&gt;
    }&lt;br /&gt;
  } while (!message_for_me)&lt;br /&gt;
  return msg;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Esame 19/06/2017 ==&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2017.06.19.tot.pdf 2017.06.19.tot.pdf]&lt;br /&gt;
=== Esercizio c.1 (da controllare)===&lt;br /&gt;
&lt;br /&gt;
* Mi sembra che ci sia un errore per il giodice, potrebbe succedere in un caso che il wait non si risvegli mai [[User:Flecart|Flecart]] ([[User talk:Flecart|talk]]) 15:38, 19 January 2023 (CET)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define NATLETI n&lt;br /&gt;
&lt;br /&gt;
condition ok2lancia[NATLETI];&lt;br /&gt;
condition ok2giudice;&lt;br /&gt;
&lt;br /&gt;
int counter[NATLETI];&lt;br /&gt;
int ultimo_tiro;&lt;br /&gt;
float registro[NATLETI][3];&lt;br /&gt;
&lt;br /&gt;
Procedure entry: boolean pronto(int i)&lt;br /&gt;
{&lt;br /&gt;
    if(!(i == 0 &amp;amp;&amp;amp; counter[i] == 0)) // se è il primo lancio non devo metterlo in wait&lt;br /&gt;
        ok2lancia[i].wait()&lt;br /&gt;
    if(counter[i] &amp;lt; 3)&lt;br /&gt;
        return true;&lt;br /&gt;
    else&lt;br /&gt;
        return false;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: void lanciato (int i)&lt;br /&gt;
{&lt;br /&gt;
    counter[i]++;&lt;br /&gt;
    ultimo_tiro = i;&lt;br /&gt;
    ok2giudice.signal();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: int lanciofatto()&lt;br /&gt;
{&lt;br /&gt;
    ok2giudice.wait()&lt;br /&gt;
    if(ultimo_tiro == NATLETI-1 &amp;amp;&amp;amp; counter[0] == 3)&lt;br /&gt;
        return -1;  // devo invalidare la condizione per uscire dal while, quindi se nessuno deve più lanciare ritorno -1&lt;br /&gt;
    else&lt;br /&gt;
        return ultimo_tiro;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: void registraechiama(int i, float m)&lt;br /&gt;
{&lt;br /&gt;
    registro[i][counter[i]-1] = m; // il secondo indice indica l'iesimo lancio -1 (perchè iniziamo a contare da zero)&lt;br /&gt;
    if(i == NATLETI-1) // se ha appena tirato l'ultimo atleta non posso dare il via a NATLETI (perchè non esiste), quindi faccio ricominciare il giro&lt;br /&gt;
        ok2lancia[0].signal();&lt;br /&gt;
    else&lt;br /&gt;
        ok2lancia[i+1].signal();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: int classifica()&lt;br /&gt;
{&lt;br /&gt;
    int best[NATLETI];&lt;br /&gt;
    for(int i = 0; i &amp;lt; NATLETI; i++)&lt;br /&gt;
    {&lt;br /&gt;
        for(int j = 0; j &amp;lt; 3; j++)&lt;br /&gt;
        {&lt;br /&gt;
            if(registro[i][j] &amp;gt; best[i])&lt;br /&gt;
                best[i] = registro[i][j];&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    best.sort_in_descending_order(); // supponiamo nel nostro pseudolinguaggio esista una funzione di ordinamento qualunque&lt;br /&gt;
    return best;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Esame 29/05/2017 ==&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2017.05.29.tot.pdf 2017.05.29.tot.pdf]&lt;br /&gt;
=== Esercizio c.1 ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
condition okpartita&lt;br /&gt;
condition ok2chiama&lt;br /&gt;
condition ok2punteggio&lt;br /&gt;
condition ok2run[2][MAX]&lt;br /&gt;
int numpronti&lt;br /&gt;
int punteggio[2]&lt;br /&gt;
boolean partita=false&lt;br /&gt;
boolean partitafinita=false&lt;br /&gt;
chiamati = []&lt;br /&gt;
contabandiera[2]&lt;br /&gt;
int winner&lt;br /&gt;
&lt;br /&gt;
entry nuovapartita():&lt;br /&gt;
{&lt;br /&gt;
    punteggio[A] = punteggio[B] = 0;&lt;br /&gt;
    numpronti = 0;&lt;br /&gt;
    partita=true;&lt;br /&gt;
    okpartita.signal()&lt;br /&gt;
    chiamati = [];&lt;br /&gt;
}&lt;br /&gt;
entry chiama(l):&lt;br /&gt;
{&lt;br /&gt;
    if (numpronti&amp;lt;2*MAX)&lt;br /&gt;
    {&lt;br /&gt;
        ok2chiama.wait();&lt;br /&gt;
    }&lt;br /&gt;
    chiamati = l;&lt;br /&gt;
    contabandiera[A] = contabandiera[B] = 0&lt;br /&gt;
    winner = -1;&lt;br /&gt;
    for (s in n)&lt;br /&gt;
    {&lt;br /&gt;
        ok2run[A][s].signal();&lt;br /&gt;
        ok2run[B][s].signal()&lt;br /&gt;
    }&lt;br /&gt;
    ok2punteggio.wait();&lt;br /&gt;
    punteggio[winner++]&lt;br /&gt;
    if (max(punteggio) == 10)&lt;br /&gt;
    {&lt;br /&gt;
        partitafinita = true;&lt;br /&gt;
        for (s in A,B)&lt;br /&gt;
        {&lt;br /&gt;
            for (n in range(MAX))&lt;br /&gt;
            {&lt;br /&gt;
                ok2run[s][n].signal();&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    return punteggio;&lt;br /&gt;
}&lt;br /&gt;
entry pronto(s, n):&lt;br /&gt;
{&lt;br /&gt;
    if (partitafinita) return 1;&lt;br /&gt;
    if (!partita)&lt;br /&gt;
    {&lt;br /&gt;
        okpartita.wait();&lt;br /&gt;
    }&lt;br /&gt;
    numpronti++;&lt;br /&gt;
    if (numpronti&amp;gt;=2*MAX)&lt;br /&gt;
    {&lt;br /&gt;
        ok2chiama.signal();&lt;br /&gt;
    }&lt;br /&gt;
    if (!(n in chiamati))&lt;br /&gt;
    {&lt;br /&gt;
        ok2run[s][n].wait();&lt;br /&gt;
    }&lt;br /&gt;
    numpronti--;&lt;br /&gt;
    return 0 if partita else 1;&lt;br /&gt;
}&lt;br /&gt;
allabandiera(s, n):&lt;br /&gt;
{&lt;br /&gt;
    contabandiera[s]++;&lt;br /&gt;
    if (winner == -1 &amp;amp;&amp;amp; contabandiera[s] == len(chiamati))&lt;br /&gt;
    {&lt;br /&gt;
        winner = s;&lt;br /&gt;
    }&lt;br /&gt;
    if (contabandiera[A] == len(chiamati) &amp;amp;&amp;amp; contabandiera[B] == len(chiamati))&lt;br /&gt;
    {&lt;br /&gt;
        ok2punteggio.signal();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
casi da discutere:    &lt;br /&gt;
se arrivano studenti a pronto prima che il prof dichiara nuovapartita succedono guai.&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>LiberaL</name></author>
	</entry>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=Prove_scritte_2017&amp;diff=3012</id>
		<title>Prove scritte 2017</title>
		<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php?title=Prove_scritte_2017&amp;diff=3012"/>
		<updated>2023-05-26T11:52:35Z</updated>

		<summary type="html">&lt;p&gt;LiberaL: /* Esercizio c.2 (da controllare) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Esame 11/09/2017 ==&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2017.09.11.tot.pdf 2017.09.11.tot.pdf]&lt;br /&gt;
=== Esercizio c.1 ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
monitor crossing&lt;br /&gt;
&lt;br /&gt;
ok2dir[4];     //NESW&lt;br /&gt;
bool busy = false;&lt;br /&gt;
&lt;br /&gt;
pe entra(int dir)&lt;br /&gt;
   if (busy)&lt;br /&gt;
      ok2dir[dir].wait();&lt;br /&gt;
   busy = true;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
pe esci(int dir)&lt;br /&gt;
   busy = false;&lt;br /&gt;
   ok2dir[(dir + 1) % 4].signal();&lt;br /&gt;
   if (!busy)&lt;br /&gt;
      ok2dir[(dir + 2) % 4].signal();&lt;br /&gt;
   if (!busy)&lt;br /&gt;
      ok2dir[(dir + 3) % 4].signal();&lt;br /&gt;
   if (!busy)&lt;br /&gt;
      ok2dir[(dir + 4) % 4].signal();  //dir&lt;br /&gt;
&lt;br /&gt;
//alternativa più compatta&lt;br /&gt;
pe esci(int dir)&lt;br /&gt;
   busy = false;&lt;br /&gt;
   for (i = 0; i &amp;lt; 4; i++)&lt;br /&gt;
   if (!busy)&lt;br /&gt;
      ok2dir[(dir + i + 1) % 4].signal();&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Soluzione proposta 2 ==== &lt;br /&gt;
Soluzione proposta da [https://t.me/LLibera LLibera] e corretta da  [https://so.v2.cs.unibo.it/wiki/index.php/User:Flecart Flecart]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
const int N_DIRECTION = 4;&lt;br /&gt;
&lt;br /&gt;
// assumo N = 0, E = 1, S = 2, W = 3, oppure shiftati ciclicamente, è equivalente&lt;br /&gt;
&lt;br /&gt;
monitor crossing {&lt;br /&gt;
	bool free;										//l'incrocio è libero?&lt;br /&gt;
	int num_waiting[N_DIRECTION];&lt;br /&gt;
	condition okToCross[N_DIRECTION];				//free == True&lt;br /&gt;
	&lt;br /&gt;
	crossing() {&lt;br /&gt;
		free = True;								//parto con l'incrocio libero&lt;br /&gt;
		for (int i = 0; i &amp;lt; N_DIRECTION; i++) {&lt;br /&gt;
			num_waiting[i] = 0;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	procedure entry enter(int direction) {&lt;br /&gt;
		if(!free) {									//se l'incrocio non è libero&lt;br /&gt;
			num_waiting[direction]++;&lt;br /&gt;
			okToCross[direction].wait();			//aspetto nella mia direzione&lt;br /&gt;
			num_waiting[direction]--;&lt;br /&gt;
		}&lt;br /&gt;
													//ora sono sicurə che sia libero&lt;br /&gt;
		free = False;								//quindi lo dichiaro occupato&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	procedure entry exit(int direction) {&lt;br /&gt;
													//non devo aspettare niente per liberare l'incrocio&lt;br /&gt;
		free = True;								//lo dichiaro libero&lt;br /&gt;
		&lt;br /&gt;
		for (int i = 0; i &amp;lt; N_DIRECTION; i++) {&lt;br /&gt;
			int curr_dir = (direction + i + 1) % N_DIRECTION;&lt;br /&gt;
			if (num_waiting[curr_dir] &amp;gt; 0) {&lt;br /&gt;
				okToCross[curr_dir].signal();&lt;br /&gt;
				break;	// l'onere di risvegliare gli altri è stato passato al nuovo processo risvegliato, quindi esco.&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.2 (da controllare) ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// server[] = array contenente il PID di tutti i server&lt;br /&gt;
&lt;br /&gt;
#define BROADCAST server[0]&lt;br /&gt;
&lt;br /&gt;
server[0]&lt;br /&gt;
{&lt;br /&gt;
    while(true)&lt;br /&gt;
    {&lt;br /&gt;
        &amp;lt;msg, sender&amp;gt; = arecv(*); // ricevo il messaggio&lt;br /&gt;
        if (sender == BROADCAST)&lt;br /&gt;
            print(msg); // se il messaggio l'ho ricevuto da me stesso allora lo stampo&lt;br /&gt;
        else&lt;br /&gt;
            asend(*, &amp;lt;msg, getpid()&amp;gt;); // se il messaggio l'ho ricevuto da un client o da un altro server lo inoltro a tutti i server (compreso me stesso)&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
server[x] // x = 1...N-1&lt;br /&gt;
{&lt;br /&gt;
    while(true)&lt;br /&gt;
    {&lt;br /&gt;
        &amp;lt;msg, sender&amp;gt; = arecv(*); // ricevo il messaggio&lt;br /&gt;
        if (sender == BROADCAST)&lt;br /&gt;
            print(msg); // se il messaggio l'ho ricevuto dal server[0] allora lo stampo&lt;br /&gt;
        else&lt;br /&gt;
            asend(BROADCAST, &amp;lt;msg, getpid()&amp;gt;) // se il messaggio l'ho ricevuto da un client lo inoltro al server[0]&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Soluzione proposta 2 ====&lt;br /&gt;
&lt;br /&gt;
Soluzione proposta da [https://so.v2.cs.unibo.it/wiki/index.php/User:Flecart Flecart]&lt;br /&gt;
Soluzione corretta da [https://so.v2.cs.unibo.it/wiki/index.php/User:Gio Flecart friend]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
process server_0 {&lt;br /&gt;
&lt;br /&gt;
        while (true) {&lt;br /&gt;
                &amp;lt;msg, sender&amp;gt; = arecv(ANY);&lt;br /&gt;
                for (int i = 1 ; i &amp;lt; N; i++) {&lt;br /&gt;
                        asend(&amp;lt;msg, 0&amp;gt;, server[i]);&lt;br /&gt;
                        while(true){&lt;br /&gt;
                          msg = arecv(server[i]); // così so che tutti abbiano stampato.&lt;br /&gt;
                          if(msg==ACK)&lt;br /&gt;
                            break&lt;br /&gt;
                          asend(msg,server[0]);&lt;br /&gt;
                        }&lt;br /&gt;
                }&lt;br /&gt;
                print(msg);&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
process server_[i=1 to N - 1] {&lt;br /&gt;
        while (true) {&lt;br /&gt;
                &amp;lt;msg, sender&amp;gt; = arecv(ANY);&lt;br /&gt;
                if (sender == 0) {&lt;br /&gt;
                        print(msg);&lt;br /&gt;
                        asend(ACK, server[0]);&lt;br /&gt;
                } else {&lt;br /&gt;
                        asend(&amp;lt;msg, i&amp;gt;, server[0]);&lt;br /&gt;
                }&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Esame 17/07/2017 ==&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2017.07.17.tot.pdf 2017.07.17.tot.pdf]&lt;br /&gt;
=== Esercizio c.1 ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
monitor conf {&lt;br /&gt;
        condition finished;&lt;br /&gt;
        condition ready2present[max];&lt;br /&gt;
        bool arrived[max] = false;&lt;br /&gt;
        bool giachiamato[max] = false;&lt;br /&gt;
&lt;br /&gt;
        entry chiama(chiamato){&lt;br /&gt;
        if(arrived[chiamato] == true)&lt;br /&gt;
                ready2present[chiamato].signal;&lt;br /&gt;
                finished.wait;&lt;br /&gt;
                return true;&lt;br /&gt;
        else&lt;br /&gt;
                giachiamato[chiamato]= true&lt;br /&gt;
                return false;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        entry arrivato(nome){&lt;br /&gt;
                if(giachiamato[nome] == true)&lt;br /&gt;
                        return  false;&lt;br /&gt;
&lt;br /&gt;
                arrived[nome] = true;&lt;br /&gt;
                ok2present[nome].wait;&lt;br /&gt;
                return true;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        entry finepresentazione(nome){&lt;br /&gt;
                finished.signal;&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.2 (da controllare) ===&lt;br /&gt;
controllata da [https://t.me/LLibera LLibera] 13:41, 26 May 2023 (CEST) l'implementazione fornita gestisce solo il caso di arecv(ANY) e non arecv(mittente)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
si, è possibile: &lt;br /&gt;
&lt;br /&gt;
Implementare asend e arecv date bsend e brecv&lt;br /&gt;
&lt;br /&gt;
asend(pid_t dst, msg_type msg){&lt;br /&gt;
    bsend (&amp;lt;dst, msg&amp;gt;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
arecv(*){&lt;br /&gt;
  do {&lt;br /&gt;
    &amp;lt;dst, msg&amp;gt; = brecv(*);&lt;br /&gt;
  } while (dst != getpid())&lt;br /&gt;
  return msg;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
propongo (LLibera) quindi questa implementazione con gestione arecv da mittente specificato (sempre da controllare)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
//il messaggio mandato è la tripla &amp;lt;destinatario, mittente, messaggio&amp;gt;&lt;br /&gt;
&lt;br /&gt;
asend(pid_t dst, msg_type msg){&lt;br /&gt;
    bsend (&amp;lt;dst, getpid(), msg&amp;gt;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Queue of &amp;lt;pid_t, pid_t, msg_type&amp;gt; db;&lt;br /&gt;
arecv(pid_t sender) {&lt;br /&gt;
&lt;br /&gt;
  //devo controllare se nella coda ho già ricevuto il messaggio da quel mittente precedentemente, mentre aspettavo un messaggio da qualcun'altro&lt;br /&gt;
  //db.get(sender) cerca una tripla il cui mittente è sender&lt;br /&gt;
  //se trova il messaggio lo rimuove anche dal db.&lt;br /&gt;
  //se sender è ANY db.get(sender) ritorna il primo che trova (FIFO)&lt;br /&gt;
  if( ( &amp;lt;dst, mit, msg&amp;gt; = db.get(sender) ) != NULL )&lt;br /&gt;
    return msg;&lt;br /&gt;
  do {&lt;br /&gt;
    &amp;lt;dst, mit, msg&amp;gt; = brecv(*);                 //ricevo&lt;br /&gt;
    bool message_for_me = (dst == getpid());    //il messaggio è per me?&lt;br /&gt;
    if( mit == sender &amp;amp;&amp;amp; message_for_me )       //se il messaggio è del mittente specificato&lt;br /&gt;
      break;&lt;br /&gt;
    if( sender != ANY &amp;amp;&amp;amp; message_for_me ) {     //se devo salvarlo (sender specificato e messaggio per me)&lt;br /&gt;
      //devo mettere in db i messaggi di altri mittenti, ricevuti quando ne aspettavo uno da un mittente specificato&lt;br /&gt;
      db.add(&amp;lt;dst, mit, msg&amp;gt;);&lt;br /&gt;
    }&lt;br /&gt;
  } while (!message_for_me)&lt;br /&gt;
  return msg;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Esame 19/06/2017 ==&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2017.06.19.tot.pdf 2017.06.19.tot.pdf]&lt;br /&gt;
=== Esercizio c.1 (da controllare)===&lt;br /&gt;
&lt;br /&gt;
* Mi sembra che ci sia un errore per il giodice, potrebbe succedere in un caso che il wait non si risvegli mai [[User:Flecart|Flecart]] ([[User talk:Flecart|talk]]) 15:38, 19 January 2023 (CET)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define NATLETI n&lt;br /&gt;
&lt;br /&gt;
condition ok2lancia[NATLETI];&lt;br /&gt;
condition ok2giudice;&lt;br /&gt;
&lt;br /&gt;
int counter[NATLETI];&lt;br /&gt;
int ultimo_tiro;&lt;br /&gt;
float registro[NATLETI][3];&lt;br /&gt;
&lt;br /&gt;
Procedure entry: boolean pronto(int i)&lt;br /&gt;
{&lt;br /&gt;
    if(!(i == 0 &amp;amp;&amp;amp; counter[i] == 0)) // se è il primo lancio non devo metterlo in wait&lt;br /&gt;
        ok2lancia[i].wait()&lt;br /&gt;
    if(counter[i] &amp;lt; 3)&lt;br /&gt;
        return true;&lt;br /&gt;
    else&lt;br /&gt;
        return false;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: void lanciato (int i)&lt;br /&gt;
{&lt;br /&gt;
    counter[i]++;&lt;br /&gt;
    ultimo_tiro = i;&lt;br /&gt;
    ok2giudice.signal();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: int lanciofatto()&lt;br /&gt;
{&lt;br /&gt;
    ok2giudice.wait()&lt;br /&gt;
    if(ultimo_tiro == NATLETI-1 &amp;amp;&amp;amp; counter[0] == 3)&lt;br /&gt;
        return -1;  // devo invalidare la condizione per uscire dal while, quindi se nessuno deve più lanciare ritorno -1&lt;br /&gt;
    else&lt;br /&gt;
        return ultimo_tiro;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: void registraechiama(int i, float m)&lt;br /&gt;
{&lt;br /&gt;
    registro[i][counter[i]-1] = m; // il secondo indice indica l'iesimo lancio -1 (perchè iniziamo a contare da zero)&lt;br /&gt;
    if(i == NATLETI-1) // se ha appena tirato l'ultimo atleta non posso dare il via a NATLETI (perchè non esiste), quindi faccio ricominciare il giro&lt;br /&gt;
        ok2lancia[0].signal();&lt;br /&gt;
    else&lt;br /&gt;
        ok2lancia[i+1].signal();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: int classifica()&lt;br /&gt;
{&lt;br /&gt;
    int best[NATLETI];&lt;br /&gt;
    for(int i = 0; i &amp;lt; NATLETI; i++)&lt;br /&gt;
    {&lt;br /&gt;
        for(int j = 0; j &amp;lt; 3; j++)&lt;br /&gt;
        {&lt;br /&gt;
            if(registro[i][j] &amp;gt; best[i])&lt;br /&gt;
                best[i] = registro[i][j];&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    best.sort_in_descending_order(); // supponiamo nel nostro pseudolinguaggio esista una funzione di ordinamento qualunque&lt;br /&gt;
    return best;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Esame 29/05/2017 ==&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2017.05.29.tot.pdf 2017.05.29.tot.pdf]&lt;br /&gt;
=== Esercizio c.1 ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
condition okpartita&lt;br /&gt;
condition ok2chiama&lt;br /&gt;
condition ok2punteggio&lt;br /&gt;
condition ok2run[2][MAX]&lt;br /&gt;
int numpronti&lt;br /&gt;
int punteggio[2]&lt;br /&gt;
boolean partita=false&lt;br /&gt;
boolean partitafinita=false&lt;br /&gt;
chiamati = []&lt;br /&gt;
contabandiera[2]&lt;br /&gt;
int winner&lt;br /&gt;
&lt;br /&gt;
entry nuovapartita():&lt;br /&gt;
{&lt;br /&gt;
    punteggio[A] = punteggio[B] = 0;&lt;br /&gt;
    numpronti = 0;&lt;br /&gt;
    partita=true;&lt;br /&gt;
    okpartita.signal()&lt;br /&gt;
    chiamati = [];&lt;br /&gt;
}&lt;br /&gt;
entry chiama(l):&lt;br /&gt;
{&lt;br /&gt;
    if (numpronti&amp;lt;2*MAX)&lt;br /&gt;
    {&lt;br /&gt;
        ok2chiama.wait();&lt;br /&gt;
    }&lt;br /&gt;
    chiamati = l;&lt;br /&gt;
    contabandiera[A] = contabandiera[B] = 0&lt;br /&gt;
    winner = -1;&lt;br /&gt;
    for (s in n)&lt;br /&gt;
    {&lt;br /&gt;
        ok2run[A][s].signal();&lt;br /&gt;
        ok2run[B][s].signal()&lt;br /&gt;
    }&lt;br /&gt;
    ok2punteggio.wait();&lt;br /&gt;
    punteggio[winner++]&lt;br /&gt;
    if (max(punteggio) == 10)&lt;br /&gt;
    {&lt;br /&gt;
        partitafinita = true;&lt;br /&gt;
        for (s in A,B)&lt;br /&gt;
        {&lt;br /&gt;
            for (n in range(MAX))&lt;br /&gt;
            {&lt;br /&gt;
                ok2run[s][n].signal();&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    return punteggio;&lt;br /&gt;
}&lt;br /&gt;
entry pronto(s, n):&lt;br /&gt;
{&lt;br /&gt;
    if (partitafinita) return 1;&lt;br /&gt;
    if (!partita)&lt;br /&gt;
    {&lt;br /&gt;
        okpartita.wait();&lt;br /&gt;
    }&lt;br /&gt;
    numpronti++;&lt;br /&gt;
    if (numpronti&amp;gt;=2*MAX)&lt;br /&gt;
    {&lt;br /&gt;
        ok2chiama.signal();&lt;br /&gt;
    }&lt;br /&gt;
    if (!(n in chiamati))&lt;br /&gt;
    {&lt;br /&gt;
        ok2run[s][n].wait();&lt;br /&gt;
    }&lt;br /&gt;
    numpronti--;&lt;br /&gt;
    return 0 if partita else 1;&lt;br /&gt;
}&lt;br /&gt;
allabandiera(s, n):&lt;br /&gt;
{&lt;br /&gt;
    contabandiera[s]++;&lt;br /&gt;
    if (winner == -1 &amp;amp;&amp;amp; contabandiera[s] == len(chiamati))&lt;br /&gt;
    {&lt;br /&gt;
        winner = s;&lt;br /&gt;
    }&lt;br /&gt;
    if (contabandiera[A] == len(chiamati) &amp;amp;&amp;amp; contabandiera[B] == len(chiamati))&lt;br /&gt;
    {&lt;br /&gt;
        ok2punteggio.signal();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
casi da discutere:    &lt;br /&gt;
se arrivano studenti a pronto prima che il prof dichiara nuovapartita succedono guai.&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>LiberaL</name></author>
	</entry>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=Prove_scritte_2017&amp;diff=3011</id>
		<title>Prove scritte 2017</title>
		<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php?title=Prove_scritte_2017&amp;diff=3011"/>
		<updated>2023-05-26T11:50:42Z</updated>

		<summary type="html">&lt;p&gt;LiberaL: /* Esercizio c.2 (da controllare) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Esame 11/09/2017 ==&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2017.09.11.tot.pdf 2017.09.11.tot.pdf]&lt;br /&gt;
=== Esercizio c.1 ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
monitor crossing&lt;br /&gt;
&lt;br /&gt;
ok2dir[4];     //NESW&lt;br /&gt;
bool busy = false;&lt;br /&gt;
&lt;br /&gt;
pe entra(int dir)&lt;br /&gt;
   if (busy)&lt;br /&gt;
      ok2dir[dir].wait();&lt;br /&gt;
   busy = true;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
pe esci(int dir)&lt;br /&gt;
   busy = false;&lt;br /&gt;
   ok2dir[(dir + 1) % 4].signal();&lt;br /&gt;
   if (!busy)&lt;br /&gt;
      ok2dir[(dir + 2) % 4].signal();&lt;br /&gt;
   if (!busy)&lt;br /&gt;
      ok2dir[(dir + 3) % 4].signal();&lt;br /&gt;
   if (!busy)&lt;br /&gt;
      ok2dir[(dir + 4) % 4].signal();  //dir&lt;br /&gt;
&lt;br /&gt;
//alternativa più compatta&lt;br /&gt;
pe esci(int dir)&lt;br /&gt;
   busy = false;&lt;br /&gt;
   for (i = 0; i &amp;lt; 4; i++)&lt;br /&gt;
   if (!busy)&lt;br /&gt;
      ok2dir[(dir + i + 1) % 4].signal();&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Soluzione proposta 2 ==== &lt;br /&gt;
Soluzione proposta da [https://t.me/LLibera LLibera] e corretta da  [https://so.v2.cs.unibo.it/wiki/index.php/User:Flecart Flecart]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
const int N_DIRECTION = 4;&lt;br /&gt;
&lt;br /&gt;
// assumo N = 0, E = 1, S = 2, W = 3, oppure shiftati ciclicamente, è equivalente&lt;br /&gt;
&lt;br /&gt;
monitor crossing {&lt;br /&gt;
	bool free;										//l'incrocio è libero?&lt;br /&gt;
	int num_waiting[N_DIRECTION];&lt;br /&gt;
	condition okToCross[N_DIRECTION];				//free == True&lt;br /&gt;
	&lt;br /&gt;
	crossing() {&lt;br /&gt;
		free = True;								//parto con l'incrocio libero&lt;br /&gt;
		for (int i = 0; i &amp;lt; N_DIRECTION; i++) {&lt;br /&gt;
			num_waiting[i] = 0;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	procedure entry enter(int direction) {&lt;br /&gt;
		if(!free) {									//se l'incrocio non è libero&lt;br /&gt;
			num_waiting[direction]++;&lt;br /&gt;
			okToCross[direction].wait();			//aspetto nella mia direzione&lt;br /&gt;
			num_waiting[direction]--;&lt;br /&gt;
		}&lt;br /&gt;
													//ora sono sicurə che sia libero&lt;br /&gt;
		free = False;								//quindi lo dichiaro occupato&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	procedure entry exit(int direction) {&lt;br /&gt;
													//non devo aspettare niente per liberare l'incrocio&lt;br /&gt;
		free = True;								//lo dichiaro libero&lt;br /&gt;
		&lt;br /&gt;
		for (int i = 0; i &amp;lt; N_DIRECTION; i++) {&lt;br /&gt;
			int curr_dir = (direction + i + 1) % N_DIRECTION;&lt;br /&gt;
			if (num_waiting[curr_dir] &amp;gt; 0) {&lt;br /&gt;
				okToCross[curr_dir].signal();&lt;br /&gt;
				break;	// l'onere di risvegliare gli altri è stato passato al nuovo processo risvegliato, quindi esco.&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.2 (da controllare) ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// server[] = array contenente il PID di tutti i server&lt;br /&gt;
&lt;br /&gt;
#define BROADCAST server[0]&lt;br /&gt;
&lt;br /&gt;
server[0]&lt;br /&gt;
{&lt;br /&gt;
    while(true)&lt;br /&gt;
    {&lt;br /&gt;
        &amp;lt;msg, sender&amp;gt; = arecv(*); // ricevo il messaggio&lt;br /&gt;
        if (sender == BROADCAST)&lt;br /&gt;
            print(msg); // se il messaggio l'ho ricevuto da me stesso allora lo stampo&lt;br /&gt;
        else&lt;br /&gt;
            asend(*, &amp;lt;msg, getpid()&amp;gt;); // se il messaggio l'ho ricevuto da un client o da un altro server lo inoltro a tutti i server (compreso me stesso)&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
server[x] // x = 1...N-1&lt;br /&gt;
{&lt;br /&gt;
    while(true)&lt;br /&gt;
    {&lt;br /&gt;
        &amp;lt;msg, sender&amp;gt; = arecv(*); // ricevo il messaggio&lt;br /&gt;
        if (sender == BROADCAST)&lt;br /&gt;
            print(msg); // se il messaggio l'ho ricevuto dal server[0] allora lo stampo&lt;br /&gt;
        else&lt;br /&gt;
            asend(BROADCAST, &amp;lt;msg, getpid()&amp;gt;) // se il messaggio l'ho ricevuto da un client lo inoltro al server[0]&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Soluzione proposta 2 ====&lt;br /&gt;
&lt;br /&gt;
Soluzione proposta da [https://so.v2.cs.unibo.it/wiki/index.php/User:Flecart Flecart]&lt;br /&gt;
Soluzione corretta da [https://so.v2.cs.unibo.it/wiki/index.php/User:Gio Flecart friend]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
process server_0 {&lt;br /&gt;
&lt;br /&gt;
        while (true) {&lt;br /&gt;
                &amp;lt;msg, sender&amp;gt; = arecv(ANY);&lt;br /&gt;
                for (int i = 1 ; i &amp;lt; N; i++) {&lt;br /&gt;
                        asend(&amp;lt;msg, 0&amp;gt;, server[i]);&lt;br /&gt;
                        while(true){&lt;br /&gt;
                          msg = arecv(server[i]); // così so che tutti abbiano stampato.&lt;br /&gt;
                          if(msg==ACK)&lt;br /&gt;
                            break&lt;br /&gt;
                          asend(msg,server[0]);&lt;br /&gt;
                        }&lt;br /&gt;
                }&lt;br /&gt;
                print(msg);&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
process server_[i=1 to N - 1] {&lt;br /&gt;
        while (true) {&lt;br /&gt;
                &amp;lt;msg, sender&amp;gt; = arecv(ANY);&lt;br /&gt;
                if (sender == 0) {&lt;br /&gt;
                        print(msg);&lt;br /&gt;
                        asend(ACK, server[0]);&lt;br /&gt;
                } else {&lt;br /&gt;
                        asend(&amp;lt;msg, i&amp;gt;, server[0]);&lt;br /&gt;
                }&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Esame 17/07/2017 ==&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2017.07.17.tot.pdf 2017.07.17.tot.pdf]&lt;br /&gt;
=== Esercizio c.1 ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
monitor conf {&lt;br /&gt;
        condition finished;&lt;br /&gt;
        condition ready2present[max];&lt;br /&gt;
        bool arrived[max] = false;&lt;br /&gt;
        bool giachiamato[max] = false;&lt;br /&gt;
&lt;br /&gt;
        entry chiama(chiamato){&lt;br /&gt;
        if(arrived[chiamato] == true)&lt;br /&gt;
                ready2present[chiamato].signal;&lt;br /&gt;
                finished.wait;&lt;br /&gt;
                return true;&lt;br /&gt;
        else&lt;br /&gt;
                giachiamato[chiamato]= true&lt;br /&gt;
                return false;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        entry arrivato(nome){&lt;br /&gt;
                if(giachiamato[nome] == true)&lt;br /&gt;
                        return  false;&lt;br /&gt;
&lt;br /&gt;
                arrived[nome] = true;&lt;br /&gt;
                ok2present[nome].wait;&lt;br /&gt;
                return true;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        entry finepresentazione(nome){&lt;br /&gt;
                finished.signal;&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.2 (da controllare) ===&lt;br /&gt;
controllata da [https://t.me/LLibera LLibera] 13:41, 26 May 2023 (CEST) l'implementazione fornita gestisce solo il caso di arecv(ANY) e non arecv(mittente)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
si, è possibile: &lt;br /&gt;
&lt;br /&gt;
Implementare asend e arecv date bsend e brecv&lt;br /&gt;
&lt;br /&gt;
asend(pid_t dst, msg_type msg){&lt;br /&gt;
    bsend (&amp;lt;dst, msg&amp;gt;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
arecv(*){&lt;br /&gt;
  do {&lt;br /&gt;
    &amp;lt;dst, msg&amp;gt; = brecv(*);&lt;br /&gt;
  } while (dst != getpid())&lt;br /&gt;
  return msg;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
propongo quindi questa implementazione con gestione arecv da mittente specificato (sempre da controllare)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
//il messaggio mandato è la tripla &amp;lt;destinatario, mittente, messaggio&amp;gt;&lt;br /&gt;
&lt;br /&gt;
asend(pid_t dst, msg_type msg){&lt;br /&gt;
    bsend (&amp;lt;dst, getpid(), msg&amp;gt;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Queue of &amp;lt;pid_t, pid_t, msg_type&amp;gt; db;&lt;br /&gt;
arecv(pid_t sender) {&lt;br /&gt;
&lt;br /&gt;
  //devo controllare se nella coda ho già ricevuto il messaggio da quel mittente precedentemente, mentre aspettavo un messaggio da qualcun'altro&lt;br /&gt;
  //db.get(sender) cerca una tripla il cui mittente è sender&lt;br /&gt;
  //se trova il messaggio lo rimuove anche dal db.&lt;br /&gt;
  //se sender è ANY db.get(sender) ritorna il primo che trova (FIFO)&lt;br /&gt;
  if( ( &amp;lt;dst, mit, msg&amp;gt; = db.get(sender) ) != NULL )&lt;br /&gt;
    return msg;&lt;br /&gt;
  do {&lt;br /&gt;
    &amp;lt;dst, mit, msg&amp;gt; = brecv(*);                 //ricevo&lt;br /&gt;
    bool message_for_me = (dst == getpid());    //il messaggio è per me?&lt;br /&gt;
    if( mit == sender &amp;amp;&amp;amp; message_for_me )                         //se il messaggio è del mittente specificato&lt;br /&gt;
      break;&lt;br /&gt;
    if( sender != ANY &amp;amp;&amp;amp; message_for_me ) {     //se devo salvarlo (sender specificato e messaggio per me)&lt;br /&gt;
      //devo mettere in db i messaggi di altri mittenti, ricevuti quando ne aspettavo uno da un mittente specificato&lt;br /&gt;
      db.add(&amp;lt;dst, mit, msg&amp;gt;);&lt;br /&gt;
    }&lt;br /&gt;
  } while (!message_for_me)&lt;br /&gt;
  return msg;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Esame 19/06/2017 ==&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2017.06.19.tot.pdf 2017.06.19.tot.pdf]&lt;br /&gt;
=== Esercizio c.1 (da controllare)===&lt;br /&gt;
&lt;br /&gt;
* Mi sembra che ci sia un errore per il giodice, potrebbe succedere in un caso che il wait non si risvegli mai [[User:Flecart|Flecart]] ([[User talk:Flecart|talk]]) 15:38, 19 January 2023 (CET)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define NATLETI n&lt;br /&gt;
&lt;br /&gt;
condition ok2lancia[NATLETI];&lt;br /&gt;
condition ok2giudice;&lt;br /&gt;
&lt;br /&gt;
int counter[NATLETI];&lt;br /&gt;
int ultimo_tiro;&lt;br /&gt;
float registro[NATLETI][3];&lt;br /&gt;
&lt;br /&gt;
Procedure entry: boolean pronto(int i)&lt;br /&gt;
{&lt;br /&gt;
    if(!(i == 0 &amp;amp;&amp;amp; counter[i] == 0)) // se è il primo lancio non devo metterlo in wait&lt;br /&gt;
        ok2lancia[i].wait()&lt;br /&gt;
    if(counter[i] &amp;lt; 3)&lt;br /&gt;
        return true;&lt;br /&gt;
    else&lt;br /&gt;
        return false;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: void lanciato (int i)&lt;br /&gt;
{&lt;br /&gt;
    counter[i]++;&lt;br /&gt;
    ultimo_tiro = i;&lt;br /&gt;
    ok2giudice.signal();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: int lanciofatto()&lt;br /&gt;
{&lt;br /&gt;
    ok2giudice.wait()&lt;br /&gt;
    if(ultimo_tiro == NATLETI-1 &amp;amp;&amp;amp; counter[0] == 3)&lt;br /&gt;
        return -1;  // devo invalidare la condizione per uscire dal while, quindi se nessuno deve più lanciare ritorno -1&lt;br /&gt;
    else&lt;br /&gt;
        return ultimo_tiro;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: void registraechiama(int i, float m)&lt;br /&gt;
{&lt;br /&gt;
    registro[i][counter[i]-1] = m; // il secondo indice indica l'iesimo lancio -1 (perchè iniziamo a contare da zero)&lt;br /&gt;
    if(i == NATLETI-1) // se ha appena tirato l'ultimo atleta non posso dare il via a NATLETI (perchè non esiste), quindi faccio ricominciare il giro&lt;br /&gt;
        ok2lancia[0].signal();&lt;br /&gt;
    else&lt;br /&gt;
        ok2lancia[i+1].signal();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: int classifica()&lt;br /&gt;
{&lt;br /&gt;
    int best[NATLETI];&lt;br /&gt;
    for(int i = 0; i &amp;lt; NATLETI; i++)&lt;br /&gt;
    {&lt;br /&gt;
        for(int j = 0; j &amp;lt; 3; j++)&lt;br /&gt;
        {&lt;br /&gt;
            if(registro[i][j] &amp;gt; best[i])&lt;br /&gt;
                best[i] = registro[i][j];&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    best.sort_in_descending_order(); // supponiamo nel nostro pseudolinguaggio esista una funzione di ordinamento qualunque&lt;br /&gt;
    return best;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Esame 29/05/2017 ==&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2017.05.29.tot.pdf 2017.05.29.tot.pdf]&lt;br /&gt;
=== Esercizio c.1 ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
condition okpartita&lt;br /&gt;
condition ok2chiama&lt;br /&gt;
condition ok2punteggio&lt;br /&gt;
condition ok2run[2][MAX]&lt;br /&gt;
int numpronti&lt;br /&gt;
int punteggio[2]&lt;br /&gt;
boolean partita=false&lt;br /&gt;
boolean partitafinita=false&lt;br /&gt;
chiamati = []&lt;br /&gt;
contabandiera[2]&lt;br /&gt;
int winner&lt;br /&gt;
&lt;br /&gt;
entry nuovapartita():&lt;br /&gt;
{&lt;br /&gt;
    punteggio[A] = punteggio[B] = 0;&lt;br /&gt;
    numpronti = 0;&lt;br /&gt;
    partita=true;&lt;br /&gt;
    okpartita.signal()&lt;br /&gt;
    chiamati = [];&lt;br /&gt;
}&lt;br /&gt;
entry chiama(l):&lt;br /&gt;
{&lt;br /&gt;
    if (numpronti&amp;lt;2*MAX)&lt;br /&gt;
    {&lt;br /&gt;
        ok2chiama.wait();&lt;br /&gt;
    }&lt;br /&gt;
    chiamati = l;&lt;br /&gt;
    contabandiera[A] = contabandiera[B] = 0&lt;br /&gt;
    winner = -1;&lt;br /&gt;
    for (s in n)&lt;br /&gt;
    {&lt;br /&gt;
        ok2run[A][s].signal();&lt;br /&gt;
        ok2run[B][s].signal()&lt;br /&gt;
    }&lt;br /&gt;
    ok2punteggio.wait();&lt;br /&gt;
    punteggio[winner++]&lt;br /&gt;
    if (max(punteggio) == 10)&lt;br /&gt;
    {&lt;br /&gt;
        partitafinita = true;&lt;br /&gt;
        for (s in A,B)&lt;br /&gt;
        {&lt;br /&gt;
            for (n in range(MAX))&lt;br /&gt;
            {&lt;br /&gt;
                ok2run[s][n].signal();&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    return punteggio;&lt;br /&gt;
}&lt;br /&gt;
entry pronto(s, n):&lt;br /&gt;
{&lt;br /&gt;
    if (partitafinita) return 1;&lt;br /&gt;
    if (!partita)&lt;br /&gt;
    {&lt;br /&gt;
        okpartita.wait();&lt;br /&gt;
    }&lt;br /&gt;
    numpronti++;&lt;br /&gt;
    if (numpronti&amp;gt;=2*MAX)&lt;br /&gt;
    {&lt;br /&gt;
        ok2chiama.signal();&lt;br /&gt;
    }&lt;br /&gt;
    if (!(n in chiamati))&lt;br /&gt;
    {&lt;br /&gt;
        ok2run[s][n].wait();&lt;br /&gt;
    }&lt;br /&gt;
    numpronti--;&lt;br /&gt;
    return 0 if partita else 1;&lt;br /&gt;
}&lt;br /&gt;
allabandiera(s, n):&lt;br /&gt;
{&lt;br /&gt;
    contabandiera[s]++;&lt;br /&gt;
    if (winner == -1 &amp;amp;&amp;amp; contabandiera[s] == len(chiamati))&lt;br /&gt;
    {&lt;br /&gt;
        winner = s;&lt;br /&gt;
    }&lt;br /&gt;
    if (contabandiera[A] == len(chiamati) &amp;amp;&amp;amp; contabandiera[B] == len(chiamati))&lt;br /&gt;
    {&lt;br /&gt;
        ok2punteggio.signal();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
casi da discutere:    &lt;br /&gt;
se arrivano studenti a pronto prima che il prof dichiara nuovapartita succedono guai.&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>LiberaL</name></author>
	</entry>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=Prove_scritte_2017&amp;diff=3010</id>
		<title>Prove scritte 2017</title>
		<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php?title=Prove_scritte_2017&amp;diff=3010"/>
		<updated>2023-05-26T11:44:25Z</updated>

		<summary type="html">&lt;p&gt;LiberaL: /* Esercizio c.2 (da controllare) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Esame 11/09/2017 ==&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2017.09.11.tot.pdf 2017.09.11.tot.pdf]&lt;br /&gt;
=== Esercizio c.1 ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
monitor crossing&lt;br /&gt;
&lt;br /&gt;
ok2dir[4];     //NESW&lt;br /&gt;
bool busy = false;&lt;br /&gt;
&lt;br /&gt;
pe entra(int dir)&lt;br /&gt;
   if (busy)&lt;br /&gt;
      ok2dir[dir].wait();&lt;br /&gt;
   busy = true;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
pe esci(int dir)&lt;br /&gt;
   busy = false;&lt;br /&gt;
   ok2dir[(dir + 1) % 4].signal();&lt;br /&gt;
   if (!busy)&lt;br /&gt;
      ok2dir[(dir + 2) % 4].signal();&lt;br /&gt;
   if (!busy)&lt;br /&gt;
      ok2dir[(dir + 3) % 4].signal();&lt;br /&gt;
   if (!busy)&lt;br /&gt;
      ok2dir[(dir + 4) % 4].signal();  //dir&lt;br /&gt;
&lt;br /&gt;
//alternativa più compatta&lt;br /&gt;
pe esci(int dir)&lt;br /&gt;
   busy = false;&lt;br /&gt;
   for (i = 0; i &amp;lt; 4; i++)&lt;br /&gt;
   if (!busy)&lt;br /&gt;
      ok2dir[(dir + i + 1) % 4].signal();&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Soluzione proposta 2 ==== &lt;br /&gt;
Soluzione proposta da [https://t.me/LLibera LLibera] e corretta da  [https://so.v2.cs.unibo.it/wiki/index.php/User:Flecart Flecart]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
const int N_DIRECTION = 4;&lt;br /&gt;
&lt;br /&gt;
// assumo N = 0, E = 1, S = 2, W = 3, oppure shiftati ciclicamente, è equivalente&lt;br /&gt;
&lt;br /&gt;
monitor crossing {&lt;br /&gt;
	bool free;										//l'incrocio è libero?&lt;br /&gt;
	int num_waiting[N_DIRECTION];&lt;br /&gt;
	condition okToCross[N_DIRECTION];				//free == True&lt;br /&gt;
	&lt;br /&gt;
	crossing() {&lt;br /&gt;
		free = True;								//parto con l'incrocio libero&lt;br /&gt;
		for (int i = 0; i &amp;lt; N_DIRECTION; i++) {&lt;br /&gt;
			num_waiting[i] = 0;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	procedure entry enter(int direction) {&lt;br /&gt;
		if(!free) {									//se l'incrocio non è libero&lt;br /&gt;
			num_waiting[direction]++;&lt;br /&gt;
			okToCross[direction].wait();			//aspetto nella mia direzione&lt;br /&gt;
			num_waiting[direction]--;&lt;br /&gt;
		}&lt;br /&gt;
													//ora sono sicurə che sia libero&lt;br /&gt;
		free = False;								//quindi lo dichiaro occupato&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	procedure entry exit(int direction) {&lt;br /&gt;
													//non devo aspettare niente per liberare l'incrocio&lt;br /&gt;
		free = True;								//lo dichiaro libero&lt;br /&gt;
		&lt;br /&gt;
		for (int i = 0; i &amp;lt; N_DIRECTION; i++) {&lt;br /&gt;
			int curr_dir = (direction + i + 1) % N_DIRECTION;&lt;br /&gt;
			if (num_waiting[curr_dir] &amp;gt; 0) {&lt;br /&gt;
				okToCross[curr_dir].signal();&lt;br /&gt;
				break;	// l'onere di risvegliare gli altri è stato passato al nuovo processo risvegliato, quindi esco.&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.2 (da controllare) ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// server[] = array contenente il PID di tutti i server&lt;br /&gt;
&lt;br /&gt;
#define BROADCAST server[0]&lt;br /&gt;
&lt;br /&gt;
server[0]&lt;br /&gt;
{&lt;br /&gt;
    while(true)&lt;br /&gt;
    {&lt;br /&gt;
        &amp;lt;msg, sender&amp;gt; = arecv(*); // ricevo il messaggio&lt;br /&gt;
        if (sender == BROADCAST)&lt;br /&gt;
            print(msg); // se il messaggio l'ho ricevuto da me stesso allora lo stampo&lt;br /&gt;
        else&lt;br /&gt;
            asend(*, &amp;lt;msg, getpid()&amp;gt;); // se il messaggio l'ho ricevuto da un client o da un altro server lo inoltro a tutti i server (compreso me stesso)&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
server[x] // x = 1...N-1&lt;br /&gt;
{&lt;br /&gt;
    while(true)&lt;br /&gt;
    {&lt;br /&gt;
        &amp;lt;msg, sender&amp;gt; = arecv(*); // ricevo il messaggio&lt;br /&gt;
        if (sender == BROADCAST)&lt;br /&gt;
            print(msg); // se il messaggio l'ho ricevuto dal server[0] allora lo stampo&lt;br /&gt;
        else&lt;br /&gt;
            asend(BROADCAST, &amp;lt;msg, getpid()&amp;gt;) // se il messaggio l'ho ricevuto da un client lo inoltro al server[0]&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Soluzione proposta 2 ====&lt;br /&gt;
&lt;br /&gt;
Soluzione proposta da [https://so.v2.cs.unibo.it/wiki/index.php/User:Flecart Flecart]&lt;br /&gt;
Soluzione corretta da [https://so.v2.cs.unibo.it/wiki/index.php/User:Gio Flecart friend]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
process server_0 {&lt;br /&gt;
&lt;br /&gt;
        while (true) {&lt;br /&gt;
                &amp;lt;msg, sender&amp;gt; = arecv(ANY);&lt;br /&gt;
                for (int i = 1 ; i &amp;lt; N; i++) {&lt;br /&gt;
                        asend(&amp;lt;msg, 0&amp;gt;, server[i]);&lt;br /&gt;
                        while(true){&lt;br /&gt;
                          msg = arecv(server[i]); // così so che tutti abbiano stampato.&lt;br /&gt;
                          if(msg==ACK)&lt;br /&gt;
                            break&lt;br /&gt;
                          asend(msg,server[0]);&lt;br /&gt;
                        }&lt;br /&gt;
                }&lt;br /&gt;
                print(msg);&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
process server_[i=1 to N - 1] {&lt;br /&gt;
        while (true) {&lt;br /&gt;
                &amp;lt;msg, sender&amp;gt; = arecv(ANY);&lt;br /&gt;
                if (sender == 0) {&lt;br /&gt;
                        print(msg);&lt;br /&gt;
                        asend(ACK, server[0]);&lt;br /&gt;
                } else {&lt;br /&gt;
                        asend(&amp;lt;msg, i&amp;gt;, server[0]);&lt;br /&gt;
                }&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Esame 17/07/2017 ==&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2017.07.17.tot.pdf 2017.07.17.tot.pdf]&lt;br /&gt;
=== Esercizio c.1 ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
monitor conf {&lt;br /&gt;
        condition finished;&lt;br /&gt;
        condition ready2present[max];&lt;br /&gt;
        bool arrived[max] = false;&lt;br /&gt;
        bool giachiamato[max] = false;&lt;br /&gt;
&lt;br /&gt;
        entry chiama(chiamato){&lt;br /&gt;
        if(arrived[chiamato] == true)&lt;br /&gt;
                ready2present[chiamato].signal;&lt;br /&gt;
                finished.wait;&lt;br /&gt;
                return true;&lt;br /&gt;
        else&lt;br /&gt;
                giachiamato[chiamato]= true&lt;br /&gt;
                return false;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        entry arrivato(nome){&lt;br /&gt;
                if(giachiamato[nome] == true)&lt;br /&gt;
                        return  false;&lt;br /&gt;
&lt;br /&gt;
                arrived[nome] = true;&lt;br /&gt;
                ok2present[nome].wait;&lt;br /&gt;
                return true;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        entry finepresentazione(nome){&lt;br /&gt;
                finished.signal;&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.2 (da controllare) ===&lt;br /&gt;
controllata da [https://t.me/LLibera LLibera] 13:41, 26 May 2023 (CEST) l'implementazione fornita gestisce solo il caso di arecv(ANY) e non arecv(mittente)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
si, è possibile: &lt;br /&gt;
&lt;br /&gt;
Implementare asend e arecv date bsend e brecv&lt;br /&gt;
&lt;br /&gt;
asend(pid_t dst, msg_type msg){&lt;br /&gt;
    bsend (&amp;lt;dst, msg&amp;gt;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
arecv(*){&lt;br /&gt;
  do {&lt;br /&gt;
    &amp;lt;dst, msg&amp;gt; = brecv(*);&lt;br /&gt;
  } while (dst != getpid())&lt;br /&gt;
  return msg;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
propongo quindi questa implementazione con gestione arecv da mittente specificato (sempre da controllare)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
//il messaggio mandato è la tripla &amp;lt;destinatario, mittente, messaggio&amp;gt;&lt;br /&gt;
&lt;br /&gt;
asend(pid_t dst, msg_type msg){&lt;br /&gt;
    bsend (&amp;lt;dst, getpid(), msg&amp;gt;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Queue of &amp;lt;pid_t, pid_t, msg_type&amp;gt; db;&lt;br /&gt;
arecv(pid_t sender) {&lt;br /&gt;
&lt;br /&gt;
  //devo controllare se nella coda ho già ricevuto il messaggio da quel mittente precedentemente, mentre aspettavo un messaggio da qualcun'altro&lt;br /&gt;
  //db.get(sender) cerca una tripla il cui mittente è sender&lt;br /&gt;
  //se trova il messaggio lo rimuove anche dal db.&lt;br /&gt;
  //se sender è ANY db.get(sender) ritorna il primo che trova (FIFO)&lt;br /&gt;
  if( ( &amp;lt;dst, mit, msg&amp;gt; = db.get(sender) ) != NULL )&lt;br /&gt;
    return msg;&lt;br /&gt;
  do {&lt;br /&gt;
    &amp;lt;dst, mit, msg&amp;gt; = brecv(*);                 //ricevo&lt;br /&gt;
    bool message_for_me = (dst == getpid());    //il messaggio è per me?&lt;br /&gt;
    if( mit == sender )                         //se il messaggio è del mittente specificato&lt;br /&gt;
      break;&lt;br /&gt;
    if( sender != ANY &amp;amp;&amp;amp; message_for_me ) {     //se devo salvarlo (sender specificato e messaggio per me)&lt;br /&gt;
      //devo mettere in db i messaggi di altri mittenti, ricevuti quando ne aspettavo uno da un mittente specificato&lt;br /&gt;
      db.add(&amp;lt;dst, mit, msg&amp;gt;);&lt;br /&gt;
    }&lt;br /&gt;
  } while (!message_for_me)&lt;br /&gt;
  return msg;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Esame 19/06/2017 ==&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2017.06.19.tot.pdf 2017.06.19.tot.pdf]&lt;br /&gt;
=== Esercizio c.1 (da controllare)===&lt;br /&gt;
&lt;br /&gt;
* Mi sembra che ci sia un errore per il giodice, potrebbe succedere in un caso che il wait non si risvegli mai [[User:Flecart|Flecart]] ([[User talk:Flecart|talk]]) 15:38, 19 January 2023 (CET)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define NATLETI n&lt;br /&gt;
&lt;br /&gt;
condition ok2lancia[NATLETI];&lt;br /&gt;
condition ok2giudice;&lt;br /&gt;
&lt;br /&gt;
int counter[NATLETI];&lt;br /&gt;
int ultimo_tiro;&lt;br /&gt;
float registro[NATLETI][3];&lt;br /&gt;
&lt;br /&gt;
Procedure entry: boolean pronto(int i)&lt;br /&gt;
{&lt;br /&gt;
    if(!(i == 0 &amp;amp;&amp;amp; counter[i] == 0)) // se è il primo lancio non devo metterlo in wait&lt;br /&gt;
        ok2lancia[i].wait()&lt;br /&gt;
    if(counter[i] &amp;lt; 3)&lt;br /&gt;
        return true;&lt;br /&gt;
    else&lt;br /&gt;
        return false;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: void lanciato (int i)&lt;br /&gt;
{&lt;br /&gt;
    counter[i]++;&lt;br /&gt;
    ultimo_tiro = i;&lt;br /&gt;
    ok2giudice.signal();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: int lanciofatto()&lt;br /&gt;
{&lt;br /&gt;
    ok2giudice.wait()&lt;br /&gt;
    if(ultimo_tiro == NATLETI-1 &amp;amp;&amp;amp; counter[0] == 3)&lt;br /&gt;
        return -1;  // devo invalidare la condizione per uscire dal while, quindi se nessuno deve più lanciare ritorno -1&lt;br /&gt;
    else&lt;br /&gt;
        return ultimo_tiro;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: void registraechiama(int i, float m)&lt;br /&gt;
{&lt;br /&gt;
    registro[i][counter[i]-1] = m; // il secondo indice indica l'iesimo lancio -1 (perchè iniziamo a contare da zero)&lt;br /&gt;
    if(i == NATLETI-1) // se ha appena tirato l'ultimo atleta non posso dare il via a NATLETI (perchè non esiste), quindi faccio ricominciare il giro&lt;br /&gt;
        ok2lancia[0].signal();&lt;br /&gt;
    else&lt;br /&gt;
        ok2lancia[i+1].signal();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: int classifica()&lt;br /&gt;
{&lt;br /&gt;
    int best[NATLETI];&lt;br /&gt;
    for(int i = 0; i &amp;lt; NATLETI; i++)&lt;br /&gt;
    {&lt;br /&gt;
        for(int j = 0; j &amp;lt; 3; j++)&lt;br /&gt;
        {&lt;br /&gt;
            if(registro[i][j] &amp;gt; best[i])&lt;br /&gt;
                best[i] = registro[i][j];&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    best.sort_in_descending_order(); // supponiamo nel nostro pseudolinguaggio esista una funzione di ordinamento qualunque&lt;br /&gt;
    return best;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Esame 29/05/2017 ==&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2017.05.29.tot.pdf 2017.05.29.tot.pdf]&lt;br /&gt;
=== Esercizio c.1 ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
condition okpartita&lt;br /&gt;
condition ok2chiama&lt;br /&gt;
condition ok2punteggio&lt;br /&gt;
condition ok2run[2][MAX]&lt;br /&gt;
int numpronti&lt;br /&gt;
int punteggio[2]&lt;br /&gt;
boolean partita=false&lt;br /&gt;
boolean partitafinita=false&lt;br /&gt;
chiamati = []&lt;br /&gt;
contabandiera[2]&lt;br /&gt;
int winner&lt;br /&gt;
&lt;br /&gt;
entry nuovapartita():&lt;br /&gt;
{&lt;br /&gt;
    punteggio[A] = punteggio[B] = 0;&lt;br /&gt;
    numpronti = 0;&lt;br /&gt;
    partita=true;&lt;br /&gt;
    okpartita.signal()&lt;br /&gt;
    chiamati = [];&lt;br /&gt;
}&lt;br /&gt;
entry chiama(l):&lt;br /&gt;
{&lt;br /&gt;
    if (numpronti&amp;lt;2*MAX)&lt;br /&gt;
    {&lt;br /&gt;
        ok2chiama.wait();&lt;br /&gt;
    }&lt;br /&gt;
    chiamati = l;&lt;br /&gt;
    contabandiera[A] = contabandiera[B] = 0&lt;br /&gt;
    winner = -1;&lt;br /&gt;
    for (s in n)&lt;br /&gt;
    {&lt;br /&gt;
        ok2run[A][s].signal();&lt;br /&gt;
        ok2run[B][s].signal()&lt;br /&gt;
    }&lt;br /&gt;
    ok2punteggio.wait();&lt;br /&gt;
    punteggio[winner++]&lt;br /&gt;
    if (max(punteggio) == 10)&lt;br /&gt;
    {&lt;br /&gt;
        partitafinita = true;&lt;br /&gt;
        for (s in A,B)&lt;br /&gt;
        {&lt;br /&gt;
            for (n in range(MAX))&lt;br /&gt;
            {&lt;br /&gt;
                ok2run[s][n].signal();&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    return punteggio;&lt;br /&gt;
}&lt;br /&gt;
entry pronto(s, n):&lt;br /&gt;
{&lt;br /&gt;
    if (partitafinita) return 1;&lt;br /&gt;
    if (!partita)&lt;br /&gt;
    {&lt;br /&gt;
        okpartita.wait();&lt;br /&gt;
    }&lt;br /&gt;
    numpronti++;&lt;br /&gt;
    if (numpronti&amp;gt;=2*MAX)&lt;br /&gt;
    {&lt;br /&gt;
        ok2chiama.signal();&lt;br /&gt;
    }&lt;br /&gt;
    if (!(n in chiamati))&lt;br /&gt;
    {&lt;br /&gt;
        ok2run[s][n].wait();&lt;br /&gt;
    }&lt;br /&gt;
    numpronti--;&lt;br /&gt;
    return 0 if partita else 1;&lt;br /&gt;
}&lt;br /&gt;
allabandiera(s, n):&lt;br /&gt;
{&lt;br /&gt;
    contabandiera[s]++;&lt;br /&gt;
    if (winner == -1 &amp;amp;&amp;amp; contabandiera[s] == len(chiamati))&lt;br /&gt;
    {&lt;br /&gt;
        winner = s;&lt;br /&gt;
    }&lt;br /&gt;
    if (contabandiera[A] == len(chiamati) &amp;amp;&amp;amp; contabandiera[B] == len(chiamati))&lt;br /&gt;
    {&lt;br /&gt;
        ok2punteggio.signal();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
casi da discutere:    &lt;br /&gt;
se arrivano studenti a pronto prima che il prof dichiara nuovapartita succedono guai.&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>LiberaL</name></author>
	</entry>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=Prove_scritte_2017&amp;diff=3009</id>
		<title>Prove scritte 2017</title>
		<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php?title=Prove_scritte_2017&amp;diff=3009"/>
		<updated>2023-05-26T11:43:11Z</updated>

		<summary type="html">&lt;p&gt;LiberaL: /* Soluzione proposta 2 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Esame 11/09/2017 ==&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2017.09.11.tot.pdf 2017.09.11.tot.pdf]&lt;br /&gt;
=== Esercizio c.1 ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
monitor crossing&lt;br /&gt;
&lt;br /&gt;
ok2dir[4];     //NESW&lt;br /&gt;
bool busy = false;&lt;br /&gt;
&lt;br /&gt;
pe entra(int dir)&lt;br /&gt;
   if (busy)&lt;br /&gt;
      ok2dir[dir].wait();&lt;br /&gt;
   busy = true;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
pe esci(int dir)&lt;br /&gt;
   busy = false;&lt;br /&gt;
   ok2dir[(dir + 1) % 4].signal();&lt;br /&gt;
   if (!busy)&lt;br /&gt;
      ok2dir[(dir + 2) % 4].signal();&lt;br /&gt;
   if (!busy)&lt;br /&gt;
      ok2dir[(dir + 3) % 4].signal();&lt;br /&gt;
   if (!busy)&lt;br /&gt;
      ok2dir[(dir + 4) % 4].signal();  //dir&lt;br /&gt;
&lt;br /&gt;
//alternativa più compatta&lt;br /&gt;
pe esci(int dir)&lt;br /&gt;
   busy = false;&lt;br /&gt;
   for (i = 0; i &amp;lt; 4; i++)&lt;br /&gt;
   if (!busy)&lt;br /&gt;
      ok2dir[(dir + i + 1) % 4].signal();&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Soluzione proposta 2 ==== &lt;br /&gt;
Soluzione proposta da [https://t.me/LLibera LLibera] e corretta da  [https://so.v2.cs.unibo.it/wiki/index.php/User:Flecart Flecart]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
const int N_DIRECTION = 4;&lt;br /&gt;
&lt;br /&gt;
// assumo N = 0, E = 1, S = 2, W = 3, oppure shiftati ciclicamente, è equivalente&lt;br /&gt;
&lt;br /&gt;
monitor crossing {&lt;br /&gt;
	bool free;										//l'incrocio è libero?&lt;br /&gt;
	int num_waiting[N_DIRECTION];&lt;br /&gt;
	condition okToCross[N_DIRECTION];				//free == True&lt;br /&gt;
	&lt;br /&gt;
	crossing() {&lt;br /&gt;
		free = True;								//parto con l'incrocio libero&lt;br /&gt;
		for (int i = 0; i &amp;lt; N_DIRECTION; i++) {&lt;br /&gt;
			num_waiting[i] = 0;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	procedure entry enter(int direction) {&lt;br /&gt;
		if(!free) {									//se l'incrocio non è libero&lt;br /&gt;
			num_waiting[direction]++;&lt;br /&gt;
			okToCross[direction].wait();			//aspetto nella mia direzione&lt;br /&gt;
			num_waiting[direction]--;&lt;br /&gt;
		}&lt;br /&gt;
													//ora sono sicurə che sia libero&lt;br /&gt;
		free = False;								//quindi lo dichiaro occupato&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	procedure entry exit(int direction) {&lt;br /&gt;
													//non devo aspettare niente per liberare l'incrocio&lt;br /&gt;
		free = True;								//lo dichiaro libero&lt;br /&gt;
		&lt;br /&gt;
		for (int i = 0; i &amp;lt; N_DIRECTION; i++) {&lt;br /&gt;
			int curr_dir = (direction + i + 1) % N_DIRECTION;&lt;br /&gt;
			if (num_waiting[curr_dir] &amp;gt; 0) {&lt;br /&gt;
				okToCross[curr_dir].signal();&lt;br /&gt;
				break;	// l'onere di risvegliare gli altri è stato passato al nuovo processo risvegliato, quindi esco.&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.2 (da controllare) ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// server[] = array contenente il PID di tutti i server&lt;br /&gt;
&lt;br /&gt;
#define BROADCAST server[0]&lt;br /&gt;
&lt;br /&gt;
server[0]&lt;br /&gt;
{&lt;br /&gt;
    while(true)&lt;br /&gt;
    {&lt;br /&gt;
        &amp;lt;msg, sender&amp;gt; = arecv(*); // ricevo il messaggio&lt;br /&gt;
        if (sender == BROADCAST)&lt;br /&gt;
            print(msg); // se il messaggio l'ho ricevuto da me stesso allora lo stampo&lt;br /&gt;
        else&lt;br /&gt;
            asend(*, &amp;lt;msg, getpid()&amp;gt;); // se il messaggio l'ho ricevuto da un client o da un altro server lo inoltro a tutti i server (compreso me stesso)&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
server[x] // x = 1...N-1&lt;br /&gt;
{&lt;br /&gt;
    while(true)&lt;br /&gt;
    {&lt;br /&gt;
        &amp;lt;msg, sender&amp;gt; = arecv(*); // ricevo il messaggio&lt;br /&gt;
        if (sender == BROADCAST)&lt;br /&gt;
            print(msg); // se il messaggio l'ho ricevuto dal server[0] allora lo stampo&lt;br /&gt;
        else&lt;br /&gt;
            asend(BROADCAST, &amp;lt;msg, getpid()&amp;gt;) // se il messaggio l'ho ricevuto da un client lo inoltro al server[0]&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Soluzione proposta 2 ====&lt;br /&gt;
&lt;br /&gt;
Soluzione proposta da [https://so.v2.cs.unibo.it/wiki/index.php/User:Flecart Flecart]&lt;br /&gt;
Soluzione corretta da [https://so.v2.cs.unibo.it/wiki/index.php/User:Gio Flecart friend]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
process server_0 {&lt;br /&gt;
&lt;br /&gt;
        while (true) {&lt;br /&gt;
                &amp;lt;msg, sender&amp;gt; = arecv(ANY);&lt;br /&gt;
                for (int i = 1 ; i &amp;lt; N; i++) {&lt;br /&gt;
                        asend(&amp;lt;msg, 0&amp;gt;, server[i]);&lt;br /&gt;
                        while(true){&lt;br /&gt;
                          msg = arecv(server[i]); // così so che tutti abbiano stampato.&lt;br /&gt;
                          if(msg==ACK)&lt;br /&gt;
                            break&lt;br /&gt;
                          asend(msg,server[0]);&lt;br /&gt;
                        }&lt;br /&gt;
                }&lt;br /&gt;
                print(msg);&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
process server_[i=1 to N - 1] {&lt;br /&gt;
        while (true) {&lt;br /&gt;
                &amp;lt;msg, sender&amp;gt; = arecv(ANY);&lt;br /&gt;
                if (sender == 0) {&lt;br /&gt;
                        print(msg);&lt;br /&gt;
                        asend(ACK, server[0]);&lt;br /&gt;
                } else {&lt;br /&gt;
                        asend(&amp;lt;msg, i&amp;gt;, server[0]);&lt;br /&gt;
                }&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Esame 17/07/2017 ==&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2017.07.17.tot.pdf 2017.07.17.tot.pdf]&lt;br /&gt;
=== Esercizio c.1 ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
monitor conf {&lt;br /&gt;
        condition finished;&lt;br /&gt;
        condition ready2present[max];&lt;br /&gt;
        bool arrived[max] = false;&lt;br /&gt;
        bool giachiamato[max] = false;&lt;br /&gt;
&lt;br /&gt;
        entry chiama(chiamato){&lt;br /&gt;
        if(arrived[chiamato] == true)&lt;br /&gt;
                ready2present[chiamato].signal;&lt;br /&gt;
                finished.wait;&lt;br /&gt;
                return true;&lt;br /&gt;
        else&lt;br /&gt;
                giachiamato[chiamato]= true&lt;br /&gt;
                return false;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        entry arrivato(nome){&lt;br /&gt;
                if(giachiamato[nome] == true)&lt;br /&gt;
                        return  false;&lt;br /&gt;
&lt;br /&gt;
                arrived[nome] = true;&lt;br /&gt;
                ok2present[nome].wait;&lt;br /&gt;
                return true;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        entry finepresentazione(nome){&lt;br /&gt;
                finished.signal;&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.2 (da controllare) ===&lt;br /&gt;
controllata da 13:41, 26 May 2023 (CEST) l'implementazione fornita gestisce solo il caso di arecv(ANY) e non arecv(mittente)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
si, è possibile: &lt;br /&gt;
&lt;br /&gt;
Implementare asend e arecv date bsend e brecv&lt;br /&gt;
&lt;br /&gt;
asend(pid_t dst, msg_type msg){&lt;br /&gt;
    bsend (&amp;lt;dst, msg&amp;gt;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
arecv(*){&lt;br /&gt;
  do {&lt;br /&gt;
    &amp;lt;dst, msg&amp;gt; = brecv(*);&lt;br /&gt;
  } while (dst != getpid())&lt;br /&gt;
  return msg;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
propongo quindi questa implementazione con gestione arecv da mittente specificato (sempre da controllare)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
//il messaggio mandato è la tripla &amp;lt;destinatario, mittente, messaggio&amp;gt;&lt;br /&gt;
&lt;br /&gt;
asend(pid_t dst, msg_type msg){&lt;br /&gt;
    bsend (&amp;lt;dst, getpid(), msg&amp;gt;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Queue of &amp;lt;pid_t, pid_t, msg_type&amp;gt; db;&lt;br /&gt;
arecv(pid_t sender) {&lt;br /&gt;
&lt;br /&gt;
  //devo controllare se nella coda ho già ricevuto il messaggio da quel mittente precedentemente, mentre aspettavo un messaggio da qualcun'altro&lt;br /&gt;
  //db.get(sender) cerca una tripla il cui mittente è sender&lt;br /&gt;
  //se trova il messaggio lo rimuove anche dal db.&lt;br /&gt;
  //se sender è ANY db.get(sender) ritorna il primo che trova (FIFO)&lt;br /&gt;
  if( ( &amp;lt;dst, mit, msg&amp;gt; = db.get(sender) ) != NULL )&lt;br /&gt;
    return msg;&lt;br /&gt;
  do {&lt;br /&gt;
    &amp;lt;dst, mit, msg&amp;gt; = brecv(*);                 //ricevo&lt;br /&gt;
    bool message_for_me = (dst == getpid());    //il messaggio è per me?&lt;br /&gt;
    if( mit == sender )                         //se il messaggio è del mittente specificato&lt;br /&gt;
      break;&lt;br /&gt;
    if( sender != ANY &amp;amp;&amp;amp; message_for_me ) {     //se devo salvarlo (sender specificato e messaggio per me)&lt;br /&gt;
      //devo mettere in db i messaggi di altri mittenti, ricevuti quando ne aspettavo uno da un mittente specificato&lt;br /&gt;
      db.add(&amp;lt;dst, mit, msg&amp;gt;);&lt;br /&gt;
    }&lt;br /&gt;
  } while (!message_for_me)&lt;br /&gt;
  return msg;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Esame 19/06/2017 ==&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2017.06.19.tot.pdf 2017.06.19.tot.pdf]&lt;br /&gt;
=== Esercizio c.1 (da controllare)===&lt;br /&gt;
&lt;br /&gt;
* Mi sembra che ci sia un errore per il giodice, potrebbe succedere in un caso che il wait non si risvegli mai [[User:Flecart|Flecart]] ([[User talk:Flecart|talk]]) 15:38, 19 January 2023 (CET)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define NATLETI n&lt;br /&gt;
&lt;br /&gt;
condition ok2lancia[NATLETI];&lt;br /&gt;
condition ok2giudice;&lt;br /&gt;
&lt;br /&gt;
int counter[NATLETI];&lt;br /&gt;
int ultimo_tiro;&lt;br /&gt;
float registro[NATLETI][3];&lt;br /&gt;
&lt;br /&gt;
Procedure entry: boolean pronto(int i)&lt;br /&gt;
{&lt;br /&gt;
    if(!(i == 0 &amp;amp;&amp;amp; counter[i] == 0)) // se è il primo lancio non devo metterlo in wait&lt;br /&gt;
        ok2lancia[i].wait()&lt;br /&gt;
    if(counter[i] &amp;lt; 3)&lt;br /&gt;
        return true;&lt;br /&gt;
    else&lt;br /&gt;
        return false;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: void lanciato (int i)&lt;br /&gt;
{&lt;br /&gt;
    counter[i]++;&lt;br /&gt;
    ultimo_tiro = i;&lt;br /&gt;
    ok2giudice.signal();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: int lanciofatto()&lt;br /&gt;
{&lt;br /&gt;
    ok2giudice.wait()&lt;br /&gt;
    if(ultimo_tiro == NATLETI-1 &amp;amp;&amp;amp; counter[0] == 3)&lt;br /&gt;
        return -1;  // devo invalidare la condizione per uscire dal while, quindi se nessuno deve più lanciare ritorno -1&lt;br /&gt;
    else&lt;br /&gt;
        return ultimo_tiro;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: void registraechiama(int i, float m)&lt;br /&gt;
{&lt;br /&gt;
    registro[i][counter[i]-1] = m; // il secondo indice indica l'iesimo lancio -1 (perchè iniziamo a contare da zero)&lt;br /&gt;
    if(i == NATLETI-1) // se ha appena tirato l'ultimo atleta non posso dare il via a NATLETI (perchè non esiste), quindi faccio ricominciare il giro&lt;br /&gt;
        ok2lancia[0].signal();&lt;br /&gt;
    else&lt;br /&gt;
        ok2lancia[i+1].signal();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: int classifica()&lt;br /&gt;
{&lt;br /&gt;
    int best[NATLETI];&lt;br /&gt;
    for(int i = 0; i &amp;lt; NATLETI; i++)&lt;br /&gt;
    {&lt;br /&gt;
        for(int j = 0; j &amp;lt; 3; j++)&lt;br /&gt;
        {&lt;br /&gt;
            if(registro[i][j] &amp;gt; best[i])&lt;br /&gt;
                best[i] = registro[i][j];&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    best.sort_in_descending_order(); // supponiamo nel nostro pseudolinguaggio esista una funzione di ordinamento qualunque&lt;br /&gt;
    return best;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Esame 29/05/2017 ==&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2017.05.29.tot.pdf 2017.05.29.tot.pdf]&lt;br /&gt;
=== Esercizio c.1 ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
condition okpartita&lt;br /&gt;
condition ok2chiama&lt;br /&gt;
condition ok2punteggio&lt;br /&gt;
condition ok2run[2][MAX]&lt;br /&gt;
int numpronti&lt;br /&gt;
int punteggio[2]&lt;br /&gt;
boolean partita=false&lt;br /&gt;
boolean partitafinita=false&lt;br /&gt;
chiamati = []&lt;br /&gt;
contabandiera[2]&lt;br /&gt;
int winner&lt;br /&gt;
&lt;br /&gt;
entry nuovapartita():&lt;br /&gt;
{&lt;br /&gt;
    punteggio[A] = punteggio[B] = 0;&lt;br /&gt;
    numpronti = 0;&lt;br /&gt;
    partita=true;&lt;br /&gt;
    okpartita.signal()&lt;br /&gt;
    chiamati = [];&lt;br /&gt;
}&lt;br /&gt;
entry chiama(l):&lt;br /&gt;
{&lt;br /&gt;
    if (numpronti&amp;lt;2*MAX)&lt;br /&gt;
    {&lt;br /&gt;
        ok2chiama.wait();&lt;br /&gt;
    }&lt;br /&gt;
    chiamati = l;&lt;br /&gt;
    contabandiera[A] = contabandiera[B] = 0&lt;br /&gt;
    winner = -1;&lt;br /&gt;
    for (s in n)&lt;br /&gt;
    {&lt;br /&gt;
        ok2run[A][s].signal();&lt;br /&gt;
        ok2run[B][s].signal()&lt;br /&gt;
    }&lt;br /&gt;
    ok2punteggio.wait();&lt;br /&gt;
    punteggio[winner++]&lt;br /&gt;
    if (max(punteggio) == 10)&lt;br /&gt;
    {&lt;br /&gt;
        partitafinita = true;&lt;br /&gt;
        for (s in A,B)&lt;br /&gt;
        {&lt;br /&gt;
            for (n in range(MAX))&lt;br /&gt;
            {&lt;br /&gt;
                ok2run[s][n].signal();&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    return punteggio;&lt;br /&gt;
}&lt;br /&gt;
entry pronto(s, n):&lt;br /&gt;
{&lt;br /&gt;
    if (partitafinita) return 1;&lt;br /&gt;
    if (!partita)&lt;br /&gt;
    {&lt;br /&gt;
        okpartita.wait();&lt;br /&gt;
    }&lt;br /&gt;
    numpronti++;&lt;br /&gt;
    if (numpronti&amp;gt;=2*MAX)&lt;br /&gt;
    {&lt;br /&gt;
        ok2chiama.signal();&lt;br /&gt;
    }&lt;br /&gt;
    if (!(n in chiamati))&lt;br /&gt;
    {&lt;br /&gt;
        ok2run[s][n].wait();&lt;br /&gt;
    }&lt;br /&gt;
    numpronti--;&lt;br /&gt;
    return 0 if partita else 1;&lt;br /&gt;
}&lt;br /&gt;
allabandiera(s, n):&lt;br /&gt;
{&lt;br /&gt;
    contabandiera[s]++;&lt;br /&gt;
    if (winner == -1 &amp;amp;&amp;amp; contabandiera[s] == len(chiamati))&lt;br /&gt;
    {&lt;br /&gt;
        winner = s;&lt;br /&gt;
    }&lt;br /&gt;
    if (contabandiera[A] == len(chiamati) &amp;amp;&amp;amp; contabandiera[B] == len(chiamati))&lt;br /&gt;
    {&lt;br /&gt;
        ok2punteggio.signal();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
casi da discutere:    &lt;br /&gt;
se arrivano studenti a pronto prima che il prof dichiara nuovapartita succedono guai.&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>LiberaL</name></author>
	</entry>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=Prove_scritte_2017&amp;diff=3008</id>
		<title>Prove scritte 2017</title>
		<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php?title=Prove_scritte_2017&amp;diff=3008"/>
		<updated>2023-05-26T11:41:45Z</updated>

		<summary type="html">&lt;p&gt;LiberaL: /* Esercizio c.2 (da controllare) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Esame 11/09/2017 ==&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2017.09.11.tot.pdf 2017.09.11.tot.pdf]&lt;br /&gt;
=== Esercizio c.1 ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
monitor crossing&lt;br /&gt;
&lt;br /&gt;
ok2dir[4];     //NESW&lt;br /&gt;
bool busy = false;&lt;br /&gt;
&lt;br /&gt;
pe entra(int dir)&lt;br /&gt;
   if (busy)&lt;br /&gt;
      ok2dir[dir].wait();&lt;br /&gt;
   busy = true;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
pe esci(int dir)&lt;br /&gt;
   busy = false;&lt;br /&gt;
   ok2dir[(dir + 1) % 4].signal();&lt;br /&gt;
   if (!busy)&lt;br /&gt;
      ok2dir[(dir + 2) % 4].signal();&lt;br /&gt;
   if (!busy)&lt;br /&gt;
      ok2dir[(dir + 3) % 4].signal();&lt;br /&gt;
   if (!busy)&lt;br /&gt;
      ok2dir[(dir + 4) % 4].signal();  //dir&lt;br /&gt;
&lt;br /&gt;
//alternativa più compatta&lt;br /&gt;
pe esci(int dir)&lt;br /&gt;
   busy = false;&lt;br /&gt;
   for (i = 0; i &amp;lt; 4; i++)&lt;br /&gt;
   if (!busy)&lt;br /&gt;
      ok2dir[(dir + i + 1) % 4].signal();&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Soluzione proposta 2 ==== &lt;br /&gt;
Soluzione proposta da Libera e corretta da  [https://so.v2.cs.unibo.it/wiki/index.php/User:Flecart Flecart]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
const int N_DIRECTION = 4;&lt;br /&gt;
&lt;br /&gt;
// assumo N = 0, E = 1, S = 2, W = 3, oppure shiftati ciclicamente, è equivalente&lt;br /&gt;
&lt;br /&gt;
monitor crossing {&lt;br /&gt;
	bool free;										//l'incrocio è libero?&lt;br /&gt;
	int num_waiting[N_DIRECTION];&lt;br /&gt;
	condition okToCross[N_DIRECTION];				//free == True&lt;br /&gt;
	&lt;br /&gt;
	crossing() {&lt;br /&gt;
		free = True;								//parto con l'incrocio libero&lt;br /&gt;
		for (int i = 0; i &amp;lt; N_DIRECTION; i++) {&lt;br /&gt;
			num_waiting[i] = 0;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	procedure entry enter(int direction) {&lt;br /&gt;
		if(!free) {									//se l'incrocio non è libero&lt;br /&gt;
			num_waiting[direction]++;&lt;br /&gt;
			okToCross[direction].wait();			//aspetto nella mia direzione&lt;br /&gt;
			num_waiting[direction]--;&lt;br /&gt;
		}&lt;br /&gt;
													//ora sono sicurə che sia libero&lt;br /&gt;
		free = False;								//quindi lo dichiaro occupato&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	procedure entry exit(int direction) {&lt;br /&gt;
													//non devo aspettare niente per liberare l'incrocio&lt;br /&gt;
		free = True;								//lo dichiaro libero&lt;br /&gt;
		&lt;br /&gt;
		for (int i = 0; i &amp;lt; N_DIRECTION; i++) {&lt;br /&gt;
			int curr_dir = (direction + i + 1) % N_DIRECTION;&lt;br /&gt;
			if (num_waiting[curr_dir] &amp;gt; 0) {&lt;br /&gt;
				okToCross[curr_dir].signal();&lt;br /&gt;
				break;	// l'onere di risvegliare gli altri è stato passato al nuovo processo risvegliato, quindi esco.&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.2 (da controllare) ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// server[] = array contenente il PID di tutti i server&lt;br /&gt;
&lt;br /&gt;
#define BROADCAST server[0]&lt;br /&gt;
&lt;br /&gt;
server[0]&lt;br /&gt;
{&lt;br /&gt;
    while(true)&lt;br /&gt;
    {&lt;br /&gt;
        &amp;lt;msg, sender&amp;gt; = arecv(*); // ricevo il messaggio&lt;br /&gt;
        if (sender == BROADCAST)&lt;br /&gt;
            print(msg); // se il messaggio l'ho ricevuto da me stesso allora lo stampo&lt;br /&gt;
        else&lt;br /&gt;
            asend(*, &amp;lt;msg, getpid()&amp;gt;); // se il messaggio l'ho ricevuto da un client o da un altro server lo inoltro a tutti i server (compreso me stesso)&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
server[x] // x = 1...N-1&lt;br /&gt;
{&lt;br /&gt;
    while(true)&lt;br /&gt;
    {&lt;br /&gt;
        &amp;lt;msg, sender&amp;gt; = arecv(*); // ricevo il messaggio&lt;br /&gt;
        if (sender == BROADCAST)&lt;br /&gt;
            print(msg); // se il messaggio l'ho ricevuto dal server[0] allora lo stampo&lt;br /&gt;
        else&lt;br /&gt;
            asend(BROADCAST, &amp;lt;msg, getpid()&amp;gt;) // se il messaggio l'ho ricevuto da un client lo inoltro al server[0]&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Soluzione proposta 2 ====&lt;br /&gt;
&lt;br /&gt;
Soluzione proposta da [https://so.v2.cs.unibo.it/wiki/index.php/User:Flecart Flecart]&lt;br /&gt;
Soluzione corretta da [https://so.v2.cs.unibo.it/wiki/index.php/User:Gio Flecart friend]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
process server_0 {&lt;br /&gt;
&lt;br /&gt;
        while (true) {&lt;br /&gt;
                &amp;lt;msg, sender&amp;gt; = arecv(ANY);&lt;br /&gt;
                for (int i = 1 ; i &amp;lt; N; i++) {&lt;br /&gt;
                        asend(&amp;lt;msg, 0&amp;gt;, server[i]);&lt;br /&gt;
                        while(true){&lt;br /&gt;
                          msg = arecv(server[i]); // così so che tutti abbiano stampato.&lt;br /&gt;
                          if(msg==ACK)&lt;br /&gt;
                            break&lt;br /&gt;
                          asend(msg,server[0]);&lt;br /&gt;
                        }&lt;br /&gt;
                }&lt;br /&gt;
                print(msg);&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
process server_[i=1 to N - 1] {&lt;br /&gt;
        while (true) {&lt;br /&gt;
                &amp;lt;msg, sender&amp;gt; = arecv(ANY);&lt;br /&gt;
                if (sender == 0) {&lt;br /&gt;
                        print(msg);&lt;br /&gt;
                        asend(ACK, server[0]);&lt;br /&gt;
                } else {&lt;br /&gt;
                        asend(&amp;lt;msg, i&amp;gt;, server[0]);&lt;br /&gt;
                }&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Esame 17/07/2017 ==&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2017.07.17.tot.pdf 2017.07.17.tot.pdf]&lt;br /&gt;
=== Esercizio c.1 ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
monitor conf {&lt;br /&gt;
        condition finished;&lt;br /&gt;
        condition ready2present[max];&lt;br /&gt;
        bool arrived[max] = false;&lt;br /&gt;
        bool giachiamato[max] = false;&lt;br /&gt;
&lt;br /&gt;
        entry chiama(chiamato){&lt;br /&gt;
        if(arrived[chiamato] == true)&lt;br /&gt;
                ready2present[chiamato].signal;&lt;br /&gt;
                finished.wait;&lt;br /&gt;
                return true;&lt;br /&gt;
        else&lt;br /&gt;
                giachiamato[chiamato]= true&lt;br /&gt;
                return false;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        entry arrivato(nome){&lt;br /&gt;
                if(giachiamato[nome] == true)&lt;br /&gt;
                        return  false;&lt;br /&gt;
&lt;br /&gt;
                arrived[nome] = true;&lt;br /&gt;
                ok2present[nome].wait;&lt;br /&gt;
                return true;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        entry finepresentazione(nome){&lt;br /&gt;
                finished.signal;&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.2 (da controllare) ===&lt;br /&gt;
controllata da 13:41, 26 May 2023 (CEST) l'implementazione fornita gestisce solo il caso di arecv(ANY) e non arecv(mittente)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
si, è possibile: &lt;br /&gt;
&lt;br /&gt;
Implementare asend e arecv date bsend e brecv&lt;br /&gt;
&lt;br /&gt;
asend(pid_t dst, msg_type msg){&lt;br /&gt;
    bsend (&amp;lt;dst, msg&amp;gt;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
arecv(*){&lt;br /&gt;
  do {&lt;br /&gt;
    &amp;lt;dst, msg&amp;gt; = brecv(*);&lt;br /&gt;
  } while (dst != getpid())&lt;br /&gt;
  return msg;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
propongo quindi questa implementazione con gestione arecv da mittente specificato (sempre da controllare)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
//il messaggio mandato è la tripla &amp;lt;destinatario, mittente, messaggio&amp;gt;&lt;br /&gt;
&lt;br /&gt;
asend(pid_t dst, msg_type msg){&lt;br /&gt;
    bsend (&amp;lt;dst, getpid(), msg&amp;gt;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Queue of &amp;lt;pid_t, pid_t, msg_type&amp;gt; db;&lt;br /&gt;
arecv(pid_t sender) {&lt;br /&gt;
&lt;br /&gt;
  //devo controllare se nella coda ho già ricevuto il messaggio da quel mittente precedentemente, mentre aspettavo un messaggio da qualcun'altro&lt;br /&gt;
  //db.get(sender) cerca una tripla il cui mittente è sender&lt;br /&gt;
  //se trova il messaggio lo rimuove anche dal db.&lt;br /&gt;
  //se sender è ANY db.get(sender) ritorna il primo che trova (FIFO)&lt;br /&gt;
  if( ( &amp;lt;dst, mit, msg&amp;gt; = db.get(sender) ) != NULL )&lt;br /&gt;
    return msg;&lt;br /&gt;
  do {&lt;br /&gt;
    &amp;lt;dst, mit, msg&amp;gt; = brecv(*);                 //ricevo&lt;br /&gt;
    bool message_for_me = (dst == getpid());    //il messaggio è per me?&lt;br /&gt;
    if( mit == sender )                         //se il messaggio è del mittente specificato&lt;br /&gt;
      break;&lt;br /&gt;
    if( sender != ANY &amp;amp;&amp;amp; message_for_me ) {     //se devo salvarlo (sender specificato e messaggio per me)&lt;br /&gt;
      //devo mettere in db i messaggi di altri mittenti, ricevuti quando ne aspettavo uno da un mittente specificato&lt;br /&gt;
      db.add(&amp;lt;dst, mit, msg&amp;gt;);&lt;br /&gt;
    }&lt;br /&gt;
  } while (!message_for_me)&lt;br /&gt;
  return msg;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Esame 19/06/2017 ==&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2017.06.19.tot.pdf 2017.06.19.tot.pdf]&lt;br /&gt;
=== Esercizio c.1 (da controllare)===&lt;br /&gt;
&lt;br /&gt;
* Mi sembra che ci sia un errore per il giodice, potrebbe succedere in un caso che il wait non si risvegli mai [[User:Flecart|Flecart]] ([[User talk:Flecart|talk]]) 15:38, 19 January 2023 (CET)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define NATLETI n&lt;br /&gt;
&lt;br /&gt;
condition ok2lancia[NATLETI];&lt;br /&gt;
condition ok2giudice;&lt;br /&gt;
&lt;br /&gt;
int counter[NATLETI];&lt;br /&gt;
int ultimo_tiro;&lt;br /&gt;
float registro[NATLETI][3];&lt;br /&gt;
&lt;br /&gt;
Procedure entry: boolean pronto(int i)&lt;br /&gt;
{&lt;br /&gt;
    if(!(i == 0 &amp;amp;&amp;amp; counter[i] == 0)) // se è il primo lancio non devo metterlo in wait&lt;br /&gt;
        ok2lancia[i].wait()&lt;br /&gt;
    if(counter[i] &amp;lt; 3)&lt;br /&gt;
        return true;&lt;br /&gt;
    else&lt;br /&gt;
        return false;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: void lanciato (int i)&lt;br /&gt;
{&lt;br /&gt;
    counter[i]++;&lt;br /&gt;
    ultimo_tiro = i;&lt;br /&gt;
    ok2giudice.signal();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: int lanciofatto()&lt;br /&gt;
{&lt;br /&gt;
    ok2giudice.wait()&lt;br /&gt;
    if(ultimo_tiro == NATLETI-1 &amp;amp;&amp;amp; counter[0] == 3)&lt;br /&gt;
        return -1;  // devo invalidare la condizione per uscire dal while, quindi se nessuno deve più lanciare ritorno -1&lt;br /&gt;
    else&lt;br /&gt;
        return ultimo_tiro;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: void registraechiama(int i, float m)&lt;br /&gt;
{&lt;br /&gt;
    registro[i][counter[i]-1] = m; // il secondo indice indica l'iesimo lancio -1 (perchè iniziamo a contare da zero)&lt;br /&gt;
    if(i == NATLETI-1) // se ha appena tirato l'ultimo atleta non posso dare il via a NATLETI (perchè non esiste), quindi faccio ricominciare il giro&lt;br /&gt;
        ok2lancia[0].signal();&lt;br /&gt;
    else&lt;br /&gt;
        ok2lancia[i+1].signal();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: int classifica()&lt;br /&gt;
{&lt;br /&gt;
    int best[NATLETI];&lt;br /&gt;
    for(int i = 0; i &amp;lt; NATLETI; i++)&lt;br /&gt;
    {&lt;br /&gt;
        for(int j = 0; j &amp;lt; 3; j++)&lt;br /&gt;
        {&lt;br /&gt;
            if(registro[i][j] &amp;gt; best[i])&lt;br /&gt;
                best[i] = registro[i][j];&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    best.sort_in_descending_order(); // supponiamo nel nostro pseudolinguaggio esista una funzione di ordinamento qualunque&lt;br /&gt;
    return best;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Esame 29/05/2017 ==&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2017.05.29.tot.pdf 2017.05.29.tot.pdf]&lt;br /&gt;
=== Esercizio c.1 ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
condition okpartita&lt;br /&gt;
condition ok2chiama&lt;br /&gt;
condition ok2punteggio&lt;br /&gt;
condition ok2run[2][MAX]&lt;br /&gt;
int numpronti&lt;br /&gt;
int punteggio[2]&lt;br /&gt;
boolean partita=false&lt;br /&gt;
boolean partitafinita=false&lt;br /&gt;
chiamati = []&lt;br /&gt;
contabandiera[2]&lt;br /&gt;
int winner&lt;br /&gt;
&lt;br /&gt;
entry nuovapartita():&lt;br /&gt;
{&lt;br /&gt;
    punteggio[A] = punteggio[B] = 0;&lt;br /&gt;
    numpronti = 0;&lt;br /&gt;
    partita=true;&lt;br /&gt;
    okpartita.signal()&lt;br /&gt;
    chiamati = [];&lt;br /&gt;
}&lt;br /&gt;
entry chiama(l):&lt;br /&gt;
{&lt;br /&gt;
    if (numpronti&amp;lt;2*MAX)&lt;br /&gt;
    {&lt;br /&gt;
        ok2chiama.wait();&lt;br /&gt;
    }&lt;br /&gt;
    chiamati = l;&lt;br /&gt;
    contabandiera[A] = contabandiera[B] = 0&lt;br /&gt;
    winner = -1;&lt;br /&gt;
    for (s in n)&lt;br /&gt;
    {&lt;br /&gt;
        ok2run[A][s].signal();&lt;br /&gt;
        ok2run[B][s].signal()&lt;br /&gt;
    }&lt;br /&gt;
    ok2punteggio.wait();&lt;br /&gt;
    punteggio[winner++]&lt;br /&gt;
    if (max(punteggio) == 10)&lt;br /&gt;
    {&lt;br /&gt;
        partitafinita = true;&lt;br /&gt;
        for (s in A,B)&lt;br /&gt;
        {&lt;br /&gt;
            for (n in range(MAX))&lt;br /&gt;
            {&lt;br /&gt;
                ok2run[s][n].signal();&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    return punteggio;&lt;br /&gt;
}&lt;br /&gt;
entry pronto(s, n):&lt;br /&gt;
{&lt;br /&gt;
    if (partitafinita) return 1;&lt;br /&gt;
    if (!partita)&lt;br /&gt;
    {&lt;br /&gt;
        okpartita.wait();&lt;br /&gt;
    }&lt;br /&gt;
    numpronti++;&lt;br /&gt;
    if (numpronti&amp;gt;=2*MAX)&lt;br /&gt;
    {&lt;br /&gt;
        ok2chiama.signal();&lt;br /&gt;
    }&lt;br /&gt;
    if (!(n in chiamati))&lt;br /&gt;
    {&lt;br /&gt;
        ok2run[s][n].wait();&lt;br /&gt;
    }&lt;br /&gt;
    numpronti--;&lt;br /&gt;
    return 0 if partita else 1;&lt;br /&gt;
}&lt;br /&gt;
allabandiera(s, n):&lt;br /&gt;
{&lt;br /&gt;
    contabandiera[s]++;&lt;br /&gt;
    if (winner == -1 &amp;amp;&amp;amp; contabandiera[s] == len(chiamati))&lt;br /&gt;
    {&lt;br /&gt;
        winner = s;&lt;br /&gt;
    }&lt;br /&gt;
    if (contabandiera[A] == len(chiamati) &amp;amp;&amp;amp; contabandiera[B] == len(chiamati))&lt;br /&gt;
    {&lt;br /&gt;
        ok2punteggio.signal();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
casi da discutere:    &lt;br /&gt;
se arrivano studenti a pronto prima che il prof dichiara nuovapartita succedono guai.&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>LiberaL</name></author>
	</entry>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=Prove_scritte_2017&amp;diff=3007</id>
		<title>Prove scritte 2017</title>
		<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php?title=Prove_scritte_2017&amp;diff=3007"/>
		<updated>2023-05-26T11:37:57Z</updated>

		<summary type="html">&lt;p&gt;LiberaL: /* gestione arecv(mittente) 17/07/2017 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Esame 11/09/2017 ==&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2017.09.11.tot.pdf 2017.09.11.tot.pdf]&lt;br /&gt;
=== Esercizio c.1 ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
monitor crossing&lt;br /&gt;
&lt;br /&gt;
ok2dir[4];     //NESW&lt;br /&gt;
bool busy = false;&lt;br /&gt;
&lt;br /&gt;
pe entra(int dir)&lt;br /&gt;
   if (busy)&lt;br /&gt;
      ok2dir[dir].wait();&lt;br /&gt;
   busy = true;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
pe esci(int dir)&lt;br /&gt;
   busy = false;&lt;br /&gt;
   ok2dir[(dir + 1) % 4].signal();&lt;br /&gt;
   if (!busy)&lt;br /&gt;
      ok2dir[(dir + 2) % 4].signal();&lt;br /&gt;
   if (!busy)&lt;br /&gt;
      ok2dir[(dir + 3) % 4].signal();&lt;br /&gt;
   if (!busy)&lt;br /&gt;
      ok2dir[(dir + 4) % 4].signal();  //dir&lt;br /&gt;
&lt;br /&gt;
//alternativa più compatta&lt;br /&gt;
pe esci(int dir)&lt;br /&gt;
   busy = false;&lt;br /&gt;
   for (i = 0; i &amp;lt; 4; i++)&lt;br /&gt;
   if (!busy)&lt;br /&gt;
      ok2dir[(dir + i + 1) % 4].signal();&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Soluzione proposta 2 ==== &lt;br /&gt;
Soluzione proposta da Libera e corretta da  [https://so.v2.cs.unibo.it/wiki/index.php/User:Flecart Flecart]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
const int N_DIRECTION = 4;&lt;br /&gt;
&lt;br /&gt;
// assumo N = 0, E = 1, S = 2, W = 3, oppure shiftati ciclicamente, è equivalente&lt;br /&gt;
&lt;br /&gt;
monitor crossing {&lt;br /&gt;
	bool free;										//l'incrocio è libero?&lt;br /&gt;
	int num_waiting[N_DIRECTION];&lt;br /&gt;
	condition okToCross[N_DIRECTION];				//free == True&lt;br /&gt;
	&lt;br /&gt;
	crossing() {&lt;br /&gt;
		free = True;								//parto con l'incrocio libero&lt;br /&gt;
		for (int i = 0; i &amp;lt; N_DIRECTION; i++) {&lt;br /&gt;
			num_waiting[i] = 0;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	procedure entry enter(int direction) {&lt;br /&gt;
		if(!free) {									//se l'incrocio non è libero&lt;br /&gt;
			num_waiting[direction]++;&lt;br /&gt;
			okToCross[direction].wait();			//aspetto nella mia direzione&lt;br /&gt;
			num_waiting[direction]--;&lt;br /&gt;
		}&lt;br /&gt;
													//ora sono sicurə che sia libero&lt;br /&gt;
		free = False;								//quindi lo dichiaro occupato&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	procedure entry exit(int direction) {&lt;br /&gt;
													//non devo aspettare niente per liberare l'incrocio&lt;br /&gt;
		free = True;								//lo dichiaro libero&lt;br /&gt;
		&lt;br /&gt;
		for (int i = 0; i &amp;lt; N_DIRECTION; i++) {&lt;br /&gt;
			int curr_dir = (direction + i + 1) % N_DIRECTION;&lt;br /&gt;
			if (num_waiting[curr_dir] &amp;gt; 0) {&lt;br /&gt;
				okToCross[curr_dir].signal();&lt;br /&gt;
				break;	// l'onere di risvegliare gli altri è stato passato al nuovo processo risvegliato, quindi esco.&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.2 (da controllare) ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// server[] = array contenente il PID di tutti i server&lt;br /&gt;
&lt;br /&gt;
#define BROADCAST server[0]&lt;br /&gt;
&lt;br /&gt;
server[0]&lt;br /&gt;
{&lt;br /&gt;
    while(true)&lt;br /&gt;
    {&lt;br /&gt;
        &amp;lt;msg, sender&amp;gt; = arecv(*); // ricevo il messaggio&lt;br /&gt;
        if (sender == BROADCAST)&lt;br /&gt;
            print(msg); // se il messaggio l'ho ricevuto da me stesso allora lo stampo&lt;br /&gt;
        else&lt;br /&gt;
            asend(*, &amp;lt;msg, getpid()&amp;gt;); // se il messaggio l'ho ricevuto da un client o da un altro server lo inoltro a tutti i server (compreso me stesso)&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
server[x] // x = 1...N-1&lt;br /&gt;
{&lt;br /&gt;
    while(true)&lt;br /&gt;
    {&lt;br /&gt;
        &amp;lt;msg, sender&amp;gt; = arecv(*); // ricevo il messaggio&lt;br /&gt;
        if (sender == BROADCAST)&lt;br /&gt;
            print(msg); // se il messaggio l'ho ricevuto dal server[0] allora lo stampo&lt;br /&gt;
        else&lt;br /&gt;
            asend(BROADCAST, &amp;lt;msg, getpid()&amp;gt;) // se il messaggio l'ho ricevuto da un client lo inoltro al server[0]&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Soluzione proposta 2 ====&lt;br /&gt;
&lt;br /&gt;
Soluzione proposta da [https://so.v2.cs.unibo.it/wiki/index.php/User:Flecart Flecart]&lt;br /&gt;
Soluzione corretta da [https://so.v2.cs.unibo.it/wiki/index.php/User:Gio Flecart friend]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
process server_0 {&lt;br /&gt;
&lt;br /&gt;
        while (true) {&lt;br /&gt;
                &amp;lt;msg, sender&amp;gt; = arecv(ANY);&lt;br /&gt;
                for (int i = 1 ; i &amp;lt; N; i++) {&lt;br /&gt;
                        asend(&amp;lt;msg, 0&amp;gt;, server[i]);&lt;br /&gt;
                        while(true){&lt;br /&gt;
                          msg = arecv(server[i]); // così so che tutti abbiano stampato.&lt;br /&gt;
                          if(msg==ACK)&lt;br /&gt;
                            break&lt;br /&gt;
                          asend(msg,server[0]);&lt;br /&gt;
                        }&lt;br /&gt;
                }&lt;br /&gt;
                print(msg);&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
process server_[i=1 to N - 1] {&lt;br /&gt;
        while (true) {&lt;br /&gt;
                &amp;lt;msg, sender&amp;gt; = arecv(ANY);&lt;br /&gt;
                if (sender == 0) {&lt;br /&gt;
                        print(msg);&lt;br /&gt;
                        asend(ACK, server[0]);&lt;br /&gt;
                } else {&lt;br /&gt;
                        asend(&amp;lt;msg, i&amp;gt;, server[0]);&lt;br /&gt;
                }&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Esame 17/07/2017 ==&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2017.07.17.tot.pdf 2017.07.17.tot.pdf]&lt;br /&gt;
=== Esercizio c.1 ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
monitor conf {&lt;br /&gt;
        condition finished;&lt;br /&gt;
        condition ready2present[max];&lt;br /&gt;
        bool arrived[max] = false;&lt;br /&gt;
        bool giachiamato[max] = false;&lt;br /&gt;
&lt;br /&gt;
        entry chiama(chiamato){&lt;br /&gt;
        if(arrived[chiamato] == true)&lt;br /&gt;
                ready2present[chiamato].signal;&lt;br /&gt;
                finished.wait;&lt;br /&gt;
                return true;&lt;br /&gt;
        else&lt;br /&gt;
                giachiamato[chiamato]= true&lt;br /&gt;
                return false;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        entry arrivato(nome){&lt;br /&gt;
                if(giachiamato[nome] == true)&lt;br /&gt;
                        return  false;&lt;br /&gt;
&lt;br /&gt;
                arrived[nome] = true;&lt;br /&gt;
                ok2present[nome].wait;&lt;br /&gt;
                return true;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        entry finepresentazione(nome){&lt;br /&gt;
                finished.signal;&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.2 (da controllare) ===&lt;br /&gt;
controllata da 13:37, 26 May 2023 (CEST) l'implementazione fornita gestisce solo il caso di arecv(ANY) e non arecv(mittente)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
si, è possibile: &lt;br /&gt;
&lt;br /&gt;
Implementare asend e arecv date bsend e brecv&lt;br /&gt;
&lt;br /&gt;
asend(pid_t dst, msg_type msg){&lt;br /&gt;
    bsend (&amp;lt;dst, msg&amp;gt;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
arecv(*){&lt;br /&gt;
  do {&lt;br /&gt;
    &amp;lt;dst, msg&amp;gt; = brecv(*);&lt;br /&gt;
  } while (dst != getpid())&lt;br /&gt;
  return msg;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
propongo quindi questa implementazione con gestione arecv da mittente specificato (sempre da controllare)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
//il messaggio mandato è la tripla &amp;lt;destinatario, mittente, messaggio&amp;gt;&lt;br /&gt;
&lt;br /&gt;
asend(pid_t dst, msg_type msg){&lt;br /&gt;
    bsend (&amp;lt;dst, getpid(), msg&amp;gt;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Queue of &amp;lt;pid_t, pid_t, msg_type&amp;gt; db;&lt;br /&gt;
arecv(pid_t sender) {&lt;br /&gt;
&lt;br /&gt;
  //devo controllare se nella coda ho già ricevuto il messaggio da quel mittente precedentemente, mentre aspettavo un messaggio da qualcun'altro&lt;br /&gt;
  //db.get(sender) cerca una tripla il cui mittente è sender&lt;br /&gt;
  //se trova il messaggio lo rimuove anche dal db.&lt;br /&gt;
  //se sender è ANY db.get(sender) ritorna il primo che trova (FIFO)&lt;br /&gt;
  if( ( &amp;lt;dst, mit, msg&amp;gt; = db.get(sender) ) != NULL )&lt;br /&gt;
    return msg;&lt;br /&gt;
  do {&lt;br /&gt;
    &amp;lt;dst, mit, msg&amp;gt; = brecv(*);                 //ricevo&lt;br /&gt;
    bool message_for_me = (dst == getpid());    //il messaggio è per me?&lt;br /&gt;
    if( mit == sender )                         //se il messaggio è del mittente specificato&lt;br /&gt;
      break;&lt;br /&gt;
    if( sender != ANY &amp;amp;&amp;amp; message_for_me ) {     //se devo salvarlo (sender specificato e messaggio per me)&lt;br /&gt;
      //devo mettere in db i messaggi di altri mittenti, ricevuti quando ne aspettavo uno da un mittente specificato&lt;br /&gt;
      db.add(&amp;lt;dst, mit, msg&amp;gt;);&lt;br /&gt;
    }&lt;br /&gt;
  } while (!message_for_me)&lt;br /&gt;
  return msg;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Esame 19/06/2017 ==&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2017.06.19.tot.pdf 2017.06.19.tot.pdf]&lt;br /&gt;
=== Esercizio c.1 (da controllare)===&lt;br /&gt;
&lt;br /&gt;
* Mi sembra che ci sia un errore per il giodice, potrebbe succedere in un caso che il wait non si risvegli mai [[User:Flecart|Flecart]] ([[User talk:Flecart|talk]]) 15:38, 19 January 2023 (CET)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define NATLETI n&lt;br /&gt;
&lt;br /&gt;
condition ok2lancia[NATLETI];&lt;br /&gt;
condition ok2giudice;&lt;br /&gt;
&lt;br /&gt;
int counter[NATLETI];&lt;br /&gt;
int ultimo_tiro;&lt;br /&gt;
float registro[NATLETI][3];&lt;br /&gt;
&lt;br /&gt;
Procedure entry: boolean pronto(int i)&lt;br /&gt;
{&lt;br /&gt;
    if(!(i == 0 &amp;amp;&amp;amp; counter[i] == 0)) // se è il primo lancio non devo metterlo in wait&lt;br /&gt;
        ok2lancia[i].wait()&lt;br /&gt;
    if(counter[i] &amp;lt; 3)&lt;br /&gt;
        return true;&lt;br /&gt;
    else&lt;br /&gt;
        return false;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: void lanciato (int i)&lt;br /&gt;
{&lt;br /&gt;
    counter[i]++;&lt;br /&gt;
    ultimo_tiro = i;&lt;br /&gt;
    ok2giudice.signal();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: int lanciofatto()&lt;br /&gt;
{&lt;br /&gt;
    ok2giudice.wait()&lt;br /&gt;
    if(ultimo_tiro == NATLETI-1 &amp;amp;&amp;amp; counter[0] == 3)&lt;br /&gt;
        return -1;  // devo invalidare la condizione per uscire dal while, quindi se nessuno deve più lanciare ritorno -1&lt;br /&gt;
    else&lt;br /&gt;
        return ultimo_tiro;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: void registraechiama(int i, float m)&lt;br /&gt;
{&lt;br /&gt;
    registro[i][counter[i]-1] = m; // il secondo indice indica l'iesimo lancio -1 (perchè iniziamo a contare da zero)&lt;br /&gt;
    if(i == NATLETI-1) // se ha appena tirato l'ultimo atleta non posso dare il via a NATLETI (perchè non esiste), quindi faccio ricominciare il giro&lt;br /&gt;
        ok2lancia[0].signal();&lt;br /&gt;
    else&lt;br /&gt;
        ok2lancia[i+1].signal();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: int classifica()&lt;br /&gt;
{&lt;br /&gt;
    int best[NATLETI];&lt;br /&gt;
    for(int i = 0; i &amp;lt; NATLETI; i++)&lt;br /&gt;
    {&lt;br /&gt;
        for(int j = 0; j &amp;lt; 3; j++)&lt;br /&gt;
        {&lt;br /&gt;
            if(registro[i][j] &amp;gt; best[i])&lt;br /&gt;
                best[i] = registro[i][j];&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    best.sort_in_descending_order(); // supponiamo nel nostro pseudolinguaggio esista una funzione di ordinamento qualunque&lt;br /&gt;
    return best;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Esame 29/05/2017 ==&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2017.05.29.tot.pdf 2017.05.29.tot.pdf]&lt;br /&gt;
=== Esercizio c.1 ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
condition okpartita&lt;br /&gt;
condition ok2chiama&lt;br /&gt;
condition ok2punteggio&lt;br /&gt;
condition ok2run[2][MAX]&lt;br /&gt;
int numpronti&lt;br /&gt;
int punteggio[2]&lt;br /&gt;
boolean partita=false&lt;br /&gt;
boolean partitafinita=false&lt;br /&gt;
chiamati = []&lt;br /&gt;
contabandiera[2]&lt;br /&gt;
int winner&lt;br /&gt;
&lt;br /&gt;
entry nuovapartita():&lt;br /&gt;
{&lt;br /&gt;
    punteggio[A] = punteggio[B] = 0;&lt;br /&gt;
    numpronti = 0;&lt;br /&gt;
    partita=true;&lt;br /&gt;
    okpartita.signal()&lt;br /&gt;
    chiamati = [];&lt;br /&gt;
}&lt;br /&gt;
entry chiama(l):&lt;br /&gt;
{&lt;br /&gt;
    if (numpronti&amp;lt;2*MAX)&lt;br /&gt;
    {&lt;br /&gt;
        ok2chiama.wait();&lt;br /&gt;
    }&lt;br /&gt;
    chiamati = l;&lt;br /&gt;
    contabandiera[A] = contabandiera[B] = 0&lt;br /&gt;
    winner = -1;&lt;br /&gt;
    for (s in n)&lt;br /&gt;
    {&lt;br /&gt;
        ok2run[A][s].signal();&lt;br /&gt;
        ok2run[B][s].signal()&lt;br /&gt;
    }&lt;br /&gt;
    ok2punteggio.wait();&lt;br /&gt;
    punteggio[winner++]&lt;br /&gt;
    if (max(punteggio) == 10)&lt;br /&gt;
    {&lt;br /&gt;
        partitafinita = true;&lt;br /&gt;
        for (s in A,B)&lt;br /&gt;
        {&lt;br /&gt;
            for (n in range(MAX))&lt;br /&gt;
            {&lt;br /&gt;
                ok2run[s][n].signal();&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    return punteggio;&lt;br /&gt;
}&lt;br /&gt;
entry pronto(s, n):&lt;br /&gt;
{&lt;br /&gt;
    if (partitafinita) return 1;&lt;br /&gt;
    if (!partita)&lt;br /&gt;
    {&lt;br /&gt;
        okpartita.wait();&lt;br /&gt;
    }&lt;br /&gt;
    numpronti++;&lt;br /&gt;
    if (numpronti&amp;gt;=2*MAX)&lt;br /&gt;
    {&lt;br /&gt;
        ok2chiama.signal();&lt;br /&gt;
    }&lt;br /&gt;
    if (!(n in chiamati))&lt;br /&gt;
    {&lt;br /&gt;
        ok2run[s][n].wait();&lt;br /&gt;
    }&lt;br /&gt;
    numpronti--;&lt;br /&gt;
    return 0 if partita else 1;&lt;br /&gt;
}&lt;br /&gt;
allabandiera(s, n):&lt;br /&gt;
{&lt;br /&gt;
    contabandiera[s]++;&lt;br /&gt;
    if (winner == -1 &amp;amp;&amp;amp; contabandiera[s] == len(chiamati))&lt;br /&gt;
    {&lt;br /&gt;
        winner = s;&lt;br /&gt;
    }&lt;br /&gt;
    if (contabandiera[A] == len(chiamati) &amp;amp;&amp;amp; contabandiera[B] == len(chiamati))&lt;br /&gt;
    {&lt;br /&gt;
        ok2punteggio.signal();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
casi da discutere:    &lt;br /&gt;
se arrivano studenti a pronto prima che il prof dichiara nuovapartita succedono guai.&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>LiberaL</name></author>
	</entry>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=Prove_scritte_2018&amp;diff=2978</id>
		<title>Prove scritte 2018</title>
		<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php?title=Prove_scritte_2018&amp;diff=2978"/>
		<updated>2023-05-12T15:00:06Z</updated>

		<summary type="html">&lt;p&gt;LiberaL: /* Soluzione &amp;quot;schiacciasassi&amp;quot; */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Esame 19/09/2018 =&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2018.09.19.tot.pdf Testo dell'esame].&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.2 (da controllare) ===&lt;br /&gt;
&lt;br /&gt;
* Controllato dall'utente ? in data ?&lt;br /&gt;
* ...&lt;br /&gt;
&lt;br /&gt;
Nello pseudocodice seguente, il termine this fa riferimento al processo corrente, mentre ANY ad uno qualunque.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
stack&amp;lt;message&amp;gt; messages;&lt;br /&gt;
&lt;br /&gt;
void lifo_send(string m, process dest) {&lt;br /&gt;
	do {&lt;br /&gt;
		asend(m, dest);&lt;br /&gt;
	} while (areceive(dest).text != &amp;quot;ACK&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
message lifo_receive(process source) {&lt;br /&gt;
	if (source != ANY) {&lt;br /&gt;
		message m = areceive(source);&lt;br /&gt;
&lt;br /&gt;
		asend(&amp;quot;ACK&amp;quot;, source);&lt;br /&gt;
&lt;br /&gt;
		return m;&lt;br /&gt;
	} else {&lt;br /&gt;
		message m;&lt;br /&gt;
&lt;br /&gt;
		asend(&amp;quot;END&amp;quot;, this);&lt;br /&gt;
		m = areceive(ANY);&lt;br /&gt;
&lt;br /&gt;
		while (m.text != &amp;quot;END&amp;quot; || m.sender != this) {&lt;br /&gt;
			messages.push(m);&lt;br /&gt;
			asend(&amp;quot;ACK&amp;quot;, m.sender);&lt;br /&gt;
&lt;br /&gt;
			m = areceive(ANY);&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
                /* Bisogna tenere conto dei casi in cui lifo_receive() viene invocata quando nessun&lt;br /&gt;
                 * messaggio è stato ancora spedito da altri processi. In tal caso si attende il&lt;br /&gt;
                 * il primo e lo si restituisce.&lt;br /&gt;
                 */&lt;br /&gt;
		if (messages.empty()) {&lt;br /&gt;
			m = areceive(ANY);&lt;br /&gt;
			asend(&amp;quot;ACK&amp;quot;, m.sender);&lt;br /&gt;
&lt;br /&gt;
			return m;&lt;br /&gt;
		} else {&lt;br /&gt;
			return messages.pop();&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Esame 17/07/2018 =&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2018.07.17.tot.pdf 2018.07.17.tot.pdf]&lt;br /&gt;
== Esercizio c.1 ==&lt;br /&gt;
A Bruxelles c'è un locale chiamato Delirium Café. Alla vigilia del FOSDEM tutti gli anni gli sviluppatori europei di&lt;br /&gt;
software libero si ritrovano a bere birra (il locale è nel guinnes dei primati con più di duemila tipi di birra). Il prossimo appuntamento è&lt;br /&gt;
fissato per il 1 febbraio 2019 ore 20. Numerosi sono i tipi di birra alla spina. I baristi (tanti) prendono gli ordini (es. mezza pinta, 1 o 2&lt;br /&gt;
pinte) e riempiono i bicchieri. Quando un fusto e' vuoto avvertono i magazzinieri che prendono un nuovo fusto che contiene più di&lt;br /&gt;
cento pinte e lo sostituiscono, a questo punto il barista può completare il riempimento del bicchiere.&lt;br /&gt;
La vita di un barista del Delirium è:&lt;br /&gt;
 while True:&lt;br /&gt;
   (type, quantity) = get_order()&lt;br /&gt;
   delirium.pour(type, quantity)&lt;br /&gt;
La vita di un Magazziniere è:&lt;br /&gt;
 while True:&lt;br /&gt;
   type = delirium.isempty()&lt;br /&gt;
   capacity = change_keg(type)&lt;br /&gt;
   delirium.loaded(type, capacity)&lt;br /&gt;
&lt;br /&gt;
Attenzione: se il fusto (keg) è quasi vuoto il barista dovrà riempire parzialmente il bicchiere, occorrerà attivare il magazziniere che&lt;br /&gt;
cambierà il fusto e poi il barista riempirà il bicchiere fino alla quantità richiesta dal cliente. Mentre un barista sta attendendo il&lt;br /&gt;
cambiamento di un fusto altri baristi potrebbero ricevere ordini per lo stesso tipo di birra: gestire opportunamente questo caso.&lt;br /&gt;
Scrivere il monitor Delirium.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Proposta di soluzione 1 === &lt;br /&gt;
* ERRORE: Secondo me c'è un leggero errore nella parte di load, nel caso in cui la nuova pinta non riesca a soddisfare completamente la richiesta ossia quando vale availableBeer[t] &amp;lt;= requests[t].head(), allora non lo risveglio nemmeno, invece dovrei risvegliare il pour, fargli versare quanto può, e richiedere una altra pinta, perché questo era un requisito del problema. [[User:Flecart|Flecart]] ([[User talk:Flecart|talk]]) 12:00, 15 January 2023 (CET)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
/* Monitor Delirum: */&lt;br /&gt;
&lt;br /&gt;
// Condition: Ok2Load;&lt;br /&gt;
// Condition: Ok2Pour[]; // Un elemento per Type&lt;br /&gt;
int availableBeer[]; // Un elemento per Type &lt;br /&gt;
Queue requests[]; // Un elemento per Type&lt;br /&gt;
Queue pendingRequests;&lt;br /&gt;
&lt;br /&gt;
Procedure entry: void Pour(Type t, Quantity c)&lt;br /&gt;
{&lt;br /&gt;
    if (c &amp;gt; availableBeer[t]) // Richiesta maggiore della birra disponibile&lt;br /&gt;
    {&lt;br /&gt;
        c -= availableBeer[t];&lt;br /&gt;
        availableBeer[t] = 0;              &lt;br /&gt;
        requests[t].Enqueue(c);&lt;br /&gt;
        if (requests[t].Length == 1) // Risveglio un magazziniere solo se è la prima richiesta di questo tipo di birra&lt;br /&gt;
        {&lt;br /&gt;
            pendingRequests.Enqueue(t);&lt;br /&gt;
            Ok2Load().Signal();&lt;br /&gt;
        }&lt;br /&gt;
        Ok2Pour[t].Wait();&lt;br /&gt;
        requests[t].Dequeue(); // Quando ho ottenuto la birra che voglio, elimino la mia richiesta&lt;br /&gt;
    }&lt;br /&gt;
    availableBeer[t] -= c;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: Type isEmpty()&lt;br /&gt;
{&lt;br /&gt;
    if (pendingRequests.Length == 0)&lt;br /&gt;
    {&lt;br /&gt;
        Ok2Load.Wait();&lt;br /&gt;
    }&lt;br /&gt;
    return pendingRequests.Dequeue();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: Loaded(Type t, Capacity c)&lt;br /&gt;
{&lt;br /&gt;
    availableBeer[t] += c;&lt;br /&gt;
    while (requests[t].Length &amp;gt; 0 &amp;amp;&amp;amp; availableBeer[t] &amp;gt; requests[t].head())&lt;br /&gt;
    {&lt;br /&gt;
        Ok2Pour[t].Signal();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (requests[t].Length &amp;gt; 0) // serve per evitare che a causa di un magazziniere lento si accodino cosi tante richieste che mentre si sta caricando si svuota subito il fusto&lt;br /&gt;
    {&lt;br /&gt;
        pendingRequests.Enqueue(t);&lt;br /&gt;
        Ok2Load.Signal();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Proposta di soluzione 2 ===&lt;br /&gt;
* Proposto da [[User:Flecart|Flecart]] ([[User talk:Flecart|talk]]) 13:41, 15 January 2023 (CET)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
extern int MAX_TYPE;&lt;br /&gt;
class Delirium {&lt;br /&gt;
    int keg[MAX_TYPE];      // qnty fusto attuale&lt;br /&gt;
    int orders[MAX_TYPE];   // qnty richiesta&lt;br /&gt;
    bool worked[MAX_TYPE];  // 1 se magazziniere sta lavorando su questo.&lt;br /&gt;
&lt;br /&gt;
    condition type_wait[MAX_TYPE];&lt;br /&gt;
    int num_wait[MAX_TYPE];&lt;br /&gt;
&lt;br /&gt;
    queue&amp;lt;int&amp;gt; empty_type;&lt;br /&gt;
    condition is_empty;&lt;br /&gt;
&lt;br /&gt;
    entry pour(type, quantity) {&lt;br /&gt;
        while (keg[type] &amp;lt; quantity) {&lt;br /&gt;
            quantity -= keg[type];&lt;br /&gt;
            keg[type] = 0;&lt;br /&gt;
            if (!empty_type.find(type) &amp;amp;&amp;amp; !worked[type]) {&lt;br /&gt;
                empty_type.enqueue(type);&lt;br /&gt;
                is_empty.signal();&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            num_wait[type]++;&lt;br /&gt;
            type_wait[type].wait();&lt;br /&gt;
            num_wait[type]--;&lt;br /&gt;
        }&lt;br /&gt;
        keg[type] -= quantity;&lt;br /&gt;
        quantity = 0;  // questo è inutile, ma concettualmente è corretto, l'ordine è completato.&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    entry loaded(type, capacity) {&lt;br /&gt;
        keg[type] += capacity;&lt;br /&gt;
        worked[type] = false;&lt;br /&gt;
&lt;br /&gt;
        for (int i = num_wait[type]; i &amp;gt; 0; i--) {&lt;br /&gt;
            type_wait[type].signal();&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // si suppone che un singolo tipo di fusto è lavorabile da un solo magazziniere alla volta.&lt;br /&gt;
    // worked impedisce di avere nella coda un fusto su cuisi sta già lavorando.&lt;br /&gt;
    entry isempty() {&lt;br /&gt;
        if (empty_type.size() &amp;lt;= 0) {&lt;br /&gt;
            is_emtpy.wait();&lt;br /&gt;
        }&lt;br /&gt;
        int type = emtpy_type.dequeue();&lt;br /&gt;
        worked[type] = true;&lt;br /&gt;
        return type;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Esercizio c.2 ==&lt;br /&gt;
&lt;br /&gt;
=== Proposta di soluzione 1 ===&lt;br /&gt;
* Visto e corretto dall'utente [[User:Acsor|Acsor]] in data 23/08/2020&lt;br /&gt;
* Visto e corretto dall'utente ? in data ?&lt;br /&gt;
* Visto, ritenuto corretto [[User:Flecart|Flecart]] ([[User talk:Flecart|talk]]) 09:27, 15 January 2023 (CET)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
class LIFOBuffer {&lt;br /&gt;
	stack&amp;lt;T&amp;gt; s;&lt;br /&gt;
	semaphore mutex(1); // mutua esclusione&lt;br /&gt;
	semaphore ok2consume(0);&lt;br /&gt;
&lt;br /&gt;
	void push (T value) {&lt;br /&gt;
		mutex.P();&lt;br /&gt;
		s.push(value);&lt;br /&gt;
                // (1)&lt;br /&gt;
		mutex.V()&lt;br /&gt;
&lt;br /&gt;
		ok2consume.V()  // Curiosità: che succede se spostiamo quest'istruzione in (1)? Edit: funziona lo stesso, solo che aggiorni il valore del semaforo prima di uscire dalla mutex.&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	T pop () {&lt;br /&gt;
		T value;&lt;br /&gt;
&lt;br /&gt;
		ok2consume.P();&lt;br /&gt;
		mutex.P();&lt;br /&gt;
		value = s.pop();&lt;br /&gt;
		mutex.V();&lt;br /&gt;
&lt;br /&gt;
		return value;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Proposta di soluzione 2 ===&lt;br /&gt;
Proposto da [[User:Flecart|Flecart]] ([[User talk:Flecart|talk]]) 09:27, 15 January 2023 (CET)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
class lifobuf {&lt;br /&gt;
	semaphore mutex(1);&lt;br /&gt;
	stack&amp;lt;int&amp;gt; values;	// empty initialized&lt;br /&gt;
	stack&amp;lt;semaphore&amp;gt; waiting;	&lt;br /&gt;
&lt;br /&gt;
	push(int value) {&lt;br /&gt;
		mutex.P();&lt;br /&gt;
		values.push(value);&lt;br /&gt;
		if (waiting.size() &amp;gt; 0) {&lt;br /&gt;
			semaphore s = waiting.pop();&lt;br /&gt;
			s.V();&lt;br /&gt;
			return;&lt;br /&gt;
		}&lt;br /&gt;
			&lt;br /&gt;
		mutex.V();	&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	pop() {&lt;br /&gt;
		int ret_val;&lt;br /&gt;
		mutex.P();&lt;br /&gt;
		if (values.size() &amp;lt;= 0) {&lt;br /&gt;
			semaphore s = new semaphore(0);&lt;br /&gt;
			waiting.push(s);&lt;br /&gt;
			mutex.V();&lt;br /&gt;
			s.P();&lt;br /&gt;
			free(s);&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		ret_val = values.pop();&lt;br /&gt;
		mutex.V();	&lt;br /&gt;
&lt;br /&gt;
		return ret_val;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Esercizio g.1 ==&lt;br /&gt;
Possiamo notare subito che il sistema ha due processori ed un dispositivo di I/O.&lt;br /&gt;
'''A''' e '''B''' partono insieme al tempo 0.&amp;lt;br&amp;gt;&lt;br /&gt;
'''C''' parte tra il tempo 0 ed il tempo 2 (non possiamo sapere di preciso quando perchè entrambe le CPU sono occupate).&amp;lt;br&amp;gt;&lt;br /&gt;
'''D''' parte tra il tempo 0 ed il tempo 3.&amp;lt;br&amp;gt;&lt;br /&gt;
A questo punto possiamo supporre che tutti e 4 i processi partano in sequenza ('''A''', '''B''', '''C''', '''D''') nello stesso momento, e ognuno prende la prima CPU libera che trova.&amp;lt;br&amp;gt;&lt;br /&gt;
'''A''' lavora per 3ms, poi scade il time slice.&amp;lt;br&amp;gt;&lt;br /&gt;
Nel frattempo '''B''' lavora per 2ms, poi richiede I/O per 4ms.&amp;lt;br&amp;gt;&lt;br /&gt;
La CPU su cui lavora '''B''' quindi si libera, e si manda in esecuzione il processo '''C'''.&amp;lt;br&amp;gt;&lt;br /&gt;
Scaduto il time slice per '''A''', si da il controllo ad un nuovo processo. '''B''' è occupato con I/O, '''C''' sta già lavorando, quindi è il turno di '''D'''.&amp;lt;br&amp;gt;&lt;br /&gt;
'''C''' lavora per 3ms, poi richiede I/O per 3ms, che però è occupato da '''B''', quindi si mette in coda per utilizzarlo.&amp;lt;br&amp;gt;&lt;br /&gt;
La CPU su cui lavorava '''C''' si libera ed il controllo torna ad '''A''', che doveva lavorare ancora per 2ms prima di chiedere il controllo di I/O, quindi lavora e si mette in coda dietro a '''C'''.&amp;lt;br&amp;gt;&lt;br /&gt;
Tornando a '''D''', questo lavora per 3ms prima che scada il time slice. Anche '''B''' ha finito il lavoro e ha bisogno di una CPU.&amp;lt;br&amp;gt;&lt;br /&gt;
In questo momento sia '''D''' che '''B''' sono nella coda dei processi in stato ready, ma dal diagramma possiamo notare che il controllo torna a '''D'''.&amp;lt;br&amp;gt;&lt;br /&gt;
La CPU ha scelto a caso un processo tra i due, perchè arrivati a questo punto possiamo supporre che lo scheduler sia Round-Robin.&amp;lt;br&amp;gt;&lt;br /&gt;
'''B''' prende possesso della prima CPU che si libera, ovvero quella occupata da '''A''', poi lavora per 2ms e termina il suo lavoro.&amp;lt;br&amp;gt;&lt;br /&gt;
Nel momento in cui '''B''' termina il lavoro, scade anche il time slice per '''D''', e '''C''' termina di usare I/O.&amp;lt;br&amp;gt;&lt;br /&gt;
Abbiamo due processi ('''C''' e '''D''') in coda ready. Ma abbiamo anche due CPU libere, perchè '''A''' è in coda per I/O e ci entra appena '''C''' finisce di usarlo.&amp;lt;br&amp;gt;&lt;br /&gt;
Lo scheduler sceglie di mandare '''C''' sul primo processore e '''D''' sul secondo.&amp;lt;br&amp;gt;&lt;br /&gt;
'''A''' nel frattempo, lavora per 4ms con I/O.&amp;lt;br&amp;gt;&lt;br /&gt;
'''C''' lavora per 3ms, poi termina il suo lavoro.&amp;lt;br&amp;gt;&lt;br /&gt;
'''D''' lavora per 3ms, poi scade il time slice. Ci sono due processori liberi, quindi '''D''' riparte subito in esecuzione.&amp;lt;br&amp;gt;&lt;br /&gt;
'''D''' doveva lavorare ancora per 1ms prima di aver bisogno di I/O, quindi finisce e si mette in coda.&amp;lt;br&amp;gt;&lt;br /&gt;
Ma nello stesso momento '''A''' termina di usare I/O, si prende un processore libero e lavora per i suoi ultimi 2ms.&amp;lt;br&amp;gt;&lt;br /&gt;
'''D''' lavora per 1ms con I/O, poi prende il secondo processore libero e lavora per 1ms prima di terminare il suo lavoro.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Il time slice è di 3ms, lo scheduler è di tipo Round-Robin.&amp;lt;br&amp;gt;&lt;br /&gt;
Il dispositivo di I/O è FIFO. L'ordine con cui partono i processi è quello alfabetico.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
A(){&lt;br /&gt;
    compute_a1(); // 5ms&lt;br /&gt;
    io_a(); // 4ms&lt;br /&gt;
    compute_a2(); // 2ms&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
B(){&lt;br /&gt;
    compute_b(); // 2ms&lt;br /&gt;
    io_b(); // 4ms&lt;br /&gt;
    compute_b(); // 2ms&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
C(){&lt;br /&gt;
    compute_c(); // 3ms&lt;br /&gt;
    io_c(); // 3ms&lt;br /&gt;
    compute_c(); // 3ms&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
D(){&lt;br /&gt;
    compute_d1(); // 10ms&lt;br /&gt;
    io_d(); // 1ms&lt;br /&gt;
    compute_d2(); // 1ms&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Lo scheduler potrebbe anche essere a priorità:&amp;lt;br&amp;gt;&lt;br /&gt;
Priorità '''B''' &amp;lt; priorità '''D''' &amp;lt; priorità '''C'''&amp;lt;br&amp;gt;&lt;br /&gt;
Priorità '''A''' = ?&amp;lt;br&amp;gt;&lt;br /&gt;
'''B''' fatto partire prima di '''C''' e '''D'''.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Esercizio g.2 (da controllare) ==&lt;br /&gt;
# In sistemi dove dispositivi di archiviazione o supporti hardware per la memoria virtuale (e dunque per la paginazione, spesso utilizzata per realizzare il supporto di memoria virtuale) non sono presenti (es. sistemi embedded). ''(In sistemi real-time la memoria virtuale è praticabile? Annotare.)''&lt;br /&gt;
# Perchè ad esempio sulle chiavette USB quasi mai abbiamo il problema di dover utilizzare file di dimensione maggiore ai 4GB. Non utilizza il journaling, che richiede molteplici scritture per ogni azione ed in dispositivi portatili può ridurre di molto la durata. Non supporta i permessi sui file, e questo è un vantaggio per le chiavette USB, pensate per trasferire dati tra PC diversi.&lt;br /&gt;
# Per fornire parallelismo e ridondanza. Non è necessario fare backup dei dati sul disco, nel senso di mantenere una copia identica di dati già memorizzati altrove, in quanto diversi sistemi di codici permettono il rilevamento e/o la correzione di errori.&lt;br /&gt;
# Se in un grafo di Holt multirisorsa esiste un ciclo tra più processi e risorse, ciò non significa che allo stesso tempo non siano coinvolti processi con archi esclusivamente entranti. Ogni processo appartenente a questa categoria non è in attesa di risorse, e può dunque procedere con i suoi calcoli; quando avrà terminato rilascerà le risorse precedentemente allocategli, eventualmente sbloccando uno dei processi coinvolti nel ciclo.&lt;br /&gt;
&lt;br /&gt;
= Esame 21/06/2018 =&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2018.06.21.tot.pdf 2018.06.21.tot.pdf]&lt;br /&gt;
=== Esercizio c.1 (sbagliato) ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
/* Monitor tmon */&lt;br /&gt;
&lt;br /&gt;
define MAX n;&lt;br /&gt;
define TERRAFERMA 1;&lt;br /&gt;
define ISOLA 2;&lt;br /&gt;
&lt;br /&gt;
semaphore ok2unload;&lt;br /&gt;
semaphore ok2load;&lt;br /&gt;
semaphore ok2ship;&lt;br /&gt;
semaphore mutex(1); // la rampa è zona critica --&amp;gt; mutua esclusione&lt;br /&gt;
&lt;br /&gt;
stack ferry;&lt;br /&gt;
int current_port = 0;&lt;br /&gt;
&lt;br /&gt;
Procedure entry: al_porto(int location)&lt;br /&gt;
{&lt;br /&gt;
    current_port = location; // traghetto arriva a destinazione&lt;br /&gt;
    ok2unload.signal(); // da il via per far sbarcare le macchine&lt;br /&gt;
    ok2ship.wait(); // si ferma&lt;br /&gt;
    current_port = 0; // traghetto sta viaggiando tra i due porti&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: imbarca(int location)&lt;br /&gt;
{&lt;br /&gt;
    mutex.wait(); // prende possesso della rampa&lt;br /&gt;
    ferry.push(1); // sale sul traghetto&lt;br /&gt;
    mutex.signal(); // libera la rampa&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: imbarcato(int location)&lt;br /&gt;
{&lt;br /&gt;
    if(ferry.lenght() == MAX) // se il traghetto è pieno da il via per farlo salpare&lt;br /&gt;
    {&lt;br /&gt;
        ok2load.wait();&lt;br /&gt;
        ok2ship.signal();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: sbarca(int location)&lt;br /&gt;
{&lt;br /&gt;
    mutex.wait(); // prende possesso della rampa&lt;br /&gt;
    ferry.pop(); // scende dal traghetto&lt;br /&gt;
    mutex.signal(); // libera la rampa&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: sbarcato(int location)&lt;br /&gt;
{&lt;br /&gt;
    if(ferry.lenght() == 0) // se il traghetto è vuoto da il via per far imbarcare le macchine&lt;br /&gt;
    {&lt;br /&gt;
        ok2unload.wait();&lt;br /&gt;
        ok2load.signal();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.1 ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
/* Monitor tmon */&lt;br /&gt;
 &lt;br /&gt;
#define MAX n&lt;br /&gt;
#define NONE 0&lt;br /&gt;
#define TERRAFERMA 1&lt;br /&gt;
#define ISOLA 2&lt;br /&gt;
 &lt;br /&gt;
condition ok2unload;&lt;br /&gt;
condition ok2load[2];&lt;br /&gt;
condition ok2ship;&lt;br /&gt;
condition empty;&lt;br /&gt;
 &lt;br /&gt;
int onboard = 0;&lt;br /&gt;
int onramp = 0;&lt;br /&gt;
int current_port = NONE;&lt;br /&gt;
&lt;br /&gt;
Procedure entry: al_porto(int location)&lt;br /&gt;
{&lt;br /&gt;
    //arrivando&lt;br /&gt;
    current_port = location;&lt;br /&gt;
    ok2unload.signal();&lt;br /&gt;
    if (onboard &amp;gt; 0)&lt;br /&gt;
        empty.wait()&lt;br /&gt;
    ok2load[location].signal()&lt;br /&gt;
    if (onboard &amp;lt; MAX)&lt;br /&gt;
        ok2ship.wait()&lt;br /&gt;
    //partendo&lt;br /&gt;
    current_port = NONE;&lt;br /&gt;
}&lt;br /&gt;
 &lt;br /&gt;
Procedure entry: imbarca(int location)&lt;br /&gt;
{&lt;br /&gt;
    if (current_port != location || onramp &amp;gt; 0 || onboard &amp;gt;= MAX)&lt;br /&gt;
        ok2load[location].wait()&lt;br /&gt;
    onramp = 1;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: imbarcato(int location)&lt;br /&gt;
{&lt;br /&gt;
    onramp = 0; onboard++;&lt;br /&gt;
    if (onboard &amp;lt; MAX)&lt;br /&gt;
        ok2load[location].signal();&lt;br /&gt;
    else&lt;br /&gt;
        ok2ship.signal();&lt;br /&gt;
}&lt;br /&gt;
 &lt;br /&gt;
Procedure entry: sbarca(int location)&lt;br /&gt;
{&lt;br /&gt;
    if (current_port != location || onramp &amp;gt; 0)&lt;br /&gt;
        ok2unload.wait()&lt;br /&gt;
    onramp = 1;&lt;br /&gt;
}&lt;br /&gt;
 &lt;br /&gt;
Procedure entry: sbarcato(int location)&lt;br /&gt;
{&lt;br /&gt;
    onramp = 0; onboard--;&lt;br /&gt;
    if (onboard == 0)&lt;br /&gt;
        empty.signal();&lt;br /&gt;
    else&lt;br /&gt;
        ok2unload.signal();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.2 (sbagliato) ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define N n // limite operazioni&lt;br /&gt;
semaphore mutex(1); // sezione critica&lt;br /&gt;
&lt;br /&gt;
class lim_semaphore()&lt;br /&gt;
{&lt;br /&gt;
    int value;&lt;br /&gt;
    semaphore plus;&lt;br /&gt;
    semaphore minus;&lt;br /&gt;
    &lt;br /&gt;
    P()&lt;br /&gt;
    {&lt;br /&gt;
        mutex.P();&lt;br /&gt;
        if(value &amp;lt; N)&lt;br /&gt;
        {&lt;br /&gt;
            if (value &amp;gt;= 0)&lt;br /&gt;
            {&lt;br /&gt;
                plus.P();&lt;br /&gt;
            }&lt;br /&gt;
            else&lt;br /&gt;
            {&lt;br /&gt;
                minus.V();&lt;br /&gt;
            }&lt;br /&gt;
            value--;&lt;br /&gt;
        }&lt;br /&gt;
        mutex.V();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    V()&lt;br /&gt;
    {&lt;br /&gt;
        mutex.P();&lt;br /&gt;
        if(value &amp;gt; -N)&lt;br /&gt;
        {&lt;br /&gt;
            if (value &amp;lt;= 0)&lt;br /&gt;
            {&lt;br /&gt;
                minus.P();&lt;br /&gt;
            } &lt;br /&gt;
            else&lt;br /&gt;
            {&lt;br /&gt;
                plus.V();&lt;br /&gt;
            }&lt;br /&gt;
            value++;&lt;br /&gt;
        }&lt;br /&gt;
        mutex.V();        &lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.2 ===&lt;br /&gt;
==== Soluzione &amp;quot;furba e facile&amp;quot; ====&lt;br /&gt;
* Visto dall'utente [[User:Acsor|Acsor]] ([[User talk:Acsor|talk]]) in data 18:53, 9 September 2020 (CEST). Ritengo sia: corretto (perché l'ho fatto pressappoco uguale). (Ritengo anche che possedere strumenti di analisi formale per verificare la correttezza di codice simile sarebbe di grande ausilio.)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
class bounded_semaphore {&lt;br /&gt;
    semaphore plus;&lt;br /&gt;
    semaphore minus;&lt;br /&gt;
    int value;   // serve per significato&lt;br /&gt;
    &lt;br /&gt;
    bounded_semaphore (int initval, unsigned maxval) {&lt;br /&gt;
        value = initval;&lt;br /&gt;
        plus = new semaphore(maxval + initval);&lt;br /&gt;
        minus = new semaphore(maxval - initval);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void P() {&lt;br /&gt;
        plus.P();&lt;br /&gt;
        value--;&lt;br /&gt;
        minus.V(); &lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void V() {&lt;br /&gt;
        minus.P();&lt;br /&gt;
        value++;&lt;br /&gt;
        plus.V();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Soluzione &amp;quot;schiacciasassi&amp;quot; ====&lt;br /&gt;
visto da [https://t.me/llibera LiberaL] in data 2023/05/12, perchè nel primo if della V() si fa value &amp;gt;= - maxval? non dovrebbe essere + maxval?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
class bounded_semaphore {&lt;br /&gt;
    semaphore mutex;&lt;br /&gt;
    queue&amp;lt;semaphore&amp;gt; okmin, okmax;&lt;br /&gt;
    int value;&lt;br /&gt;
    unsigned maxval;&lt;br /&gt;
&lt;br /&gt;
    bounded_semaphore (int initval, unsigned maxval) {&lt;br /&gt;
	value = initval;&lt;br /&gt;
        this.maxval = maxval;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void P() {&lt;br /&gt;
        mutex.P();&lt;br /&gt;
&lt;br /&gt;
        if (value &amp;lt;= -maxval)  {&lt;br /&gt;
            s=semaphore(0);&lt;br /&gt;
            okmin.enqueue(s);&lt;br /&gt;
            mutex.V();&lt;br /&gt;
            s.P();&lt;br /&gt;
        } else if (okmax.length() &amp;gt; 0) {&lt;br /&gt;
            s = okmax.dequeue()&lt;br /&gt;
            s.V();&lt;br /&gt;
            mutex.V();&lt;br /&gt;
        } else {&lt;br /&gt;
            value--;&lt;br /&gt;
            mutex.V();&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void V() {&lt;br /&gt;
        mutex.P();&lt;br /&gt;
&lt;br /&gt;
        if (value &amp;gt;= -maxval)  {  //qui...&lt;br /&gt;
            s=semaphore(0);&lt;br /&gt;
            okmax.enqueue(s);&lt;br /&gt;
            mutex.V();&lt;br /&gt;
            s.P();&lt;br /&gt;
        } else if (okmin.length() &amp;gt; 0) {&lt;br /&gt;
            s = okmin.dequeue()&lt;br /&gt;
            s.V();&lt;br /&gt;
            mutex.V();&lt;br /&gt;
        } else {&lt;br /&gt;
            value++;&lt;br /&gt;
            mutex.V();&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Esercizio g.1 ===&lt;br /&gt;
* Controllato dall'utente [[User:Acsor|Acsor]] ([[User talk:Acsor|talk]]), 23:17, 9 September 2020 (CEST). Ritengo sia: corretto&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
IC = 10,10,10 // Capitale iniziale&lt;br /&gt;
COH = 4,4,4   // Saldo in cassa&lt;br /&gt;
 &lt;br /&gt;
      MAX     ATT     RES    AVAIL&lt;br /&gt;
P1 | 6,6,6 | 1,1,1 | 5,5,5 | 4,4,4&lt;br /&gt;
P2 | 6,6,6 | 1,1,1 | 5,5,5 | 5,5,5&lt;br /&gt;
P3 | 9,9,9 | 4,4,4 | 5,5,5 | 6,6,6&lt;br /&gt;
 &amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Minimizzato&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
IC = 4,4,4&lt;br /&gt;
COH = 1,1,1&lt;br /&gt;
 &lt;br /&gt;
      MAX     ATT     RES  &lt;br /&gt;
P1 | 3,3,3 | 1,1,1 | 2,2,2&lt;br /&gt;
P2 | 3,3,3 | 1,1,1 | 2,2,2&lt;br /&gt;
P3 | 3,3,3 | 1,1,1 | 2,2,2&lt;br /&gt;
 &amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Esercizio g.2 (da controllare) ===&lt;br /&gt;
&lt;br /&gt;
* Visto e rimaneggiato in data 19:40, 10 September 2020 (CEST) dall'utente [[User:Acsor|Acsor]] ([[User talk:Acsor|talk]])&lt;br /&gt;
&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
&lt;br /&gt;
# Il calcolo del working set serve a determinare il numero di processi che possono essere mantenuti attivi sulla base del limite della memoria principale, più precisamente del suo numero di frame. Può essere svolto ad ogni page fault, ossia quando un processo tra quelli attivi richiede una pagina non presente in memoria, o prima di avviare un nuovo processo.&lt;br /&gt;
# La lunghezza massima di un file che può essere memorizzato su un file system di tipo FAT viene calcolata moltiplicando il massimo numero di cluster (dimensione dell'unità di allocazione) identificabili per la loro dimensione. Il massimo numero di cluster identificabili dipende da quanti bit sono allocati per numerarli, e per questa distinzione esistono varie versioni di FAT (FAT12, FAT16, FAT32).&lt;br /&gt;
## FAT32 memorizza la dimensione dei file in un intero unsigned da 32bit, e non può quindi gestire un file di dimensione superiore ai 2^32 bit = ~4GB.&lt;br /&gt;
## FAT16, allocando 16bit per identificare i cluster, può contarne al massimo 2^16 (65536). Prendendo quindi, ad esempio, un file system FAT16 con cluster da 32KB, possiamo avere file grandi al massimo 32KB*65536 = ~2GB.&lt;br /&gt;
## FAT12 di conseguenza può numerare al massimo 2^12 (4096) cluster, ma dato che il numero dei settori del disco viene memorizzato in un intero signed a 16bit, la massima dimensione del disco è 2^15 = 32MB. Ovviamente, non si può memorizzare un file di grandezza superiore alla dimensione dell'unità di memorizzazione stessa, e quindi anche i file in FAT12 possono avere dimensione massima di 32MB.&lt;br /&gt;
# Entrambi condividono l'intento di infettare host con codice malevolo, ma differiscono fondamentalmente nella modalità: i virus infettano programmi già esistenti mediante un ''virus dropper'', mentre i worm diffondono copie di se stessi, solitamente attraverso la rete.&lt;br /&gt;
# In vari casi sulla base della natura del sistema. Innanzitutto, in sistemi batch ciò avviene se non sono stati inseriti più processi per un certo lasso di tempo. In sistemi general-purpose (es. per PC o dispositivi mobili) tale condizione è verificabile se tutti i processi sono in attesa su una coda che non è quella dello scheduler (ad. es. di un semaforo o di una periferica di I/O); casi concreti sono pertanto il deadlock (di tutti i processi del sistema) o attesa generale di I/O. Infine sempre in sistemi general-purpose tale condizione può manifestarsi, stavolta in condizioni patologiche, se ogni processo è assegnato ad una propria CPU/core, lasciando pertanto la coda d'attesa vuota.&lt;br /&gt;
&lt;br /&gt;
= Esame 28/05/2018 =&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2018.05.28.tot.pdf 2018.05.28.tot.pdf]&lt;br /&gt;
=== Esercizio c.1 ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
Stack&amp;lt;int&amp;gt; entriesStack;&lt;br /&gt;
&lt;br /&gt;
int vid[MAX];&lt;br /&gt;
condition ok2esci[MAX]&lt;br /&gt;
int in = 0; &lt;br /&gt;
int out = -1;&lt;br /&gt;
&lt;br /&gt;
Procedure-entry: entra(int id) {&lt;br /&gt;
    if (in &amp;gt;= MAX)&lt;br /&gt;
        ok2entra.wait()&lt;br /&gt;
    vid[in++] = id;&lt;br /&gt;
    if (in &amp;lt; MAX)&lt;br /&gt;
        ok2entra.signal()&lt;br /&gt;
    else&lt;br /&gt;
        out = MAX - 1;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure-entry: esci(int id) {&lt;br /&gt;
    int i;&lt;br /&gt;
    for (i = 0; i &amp;lt; in; i++)&lt;br /&gt;
        if (vid[i] == id)&lt;br /&gt;
            break; //cerco l'indice di id nel vettore vid&lt;br /&gt;
&lt;br /&gt;
    if (i != out)&lt;br /&gt;
        ok2esci[i].wait();&lt;br /&gt;
&lt;br /&gt;
    if (out &amp;gt; 0) {&lt;br /&gt;
        out--;&lt;br /&gt;
        ok2esci[out].signal();&lt;br /&gt;
    } else {&lt;br /&gt;
        out--;&lt;br /&gt;
        in = 0; &lt;br /&gt;
        ok2entra.signal();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.1 (da controllare) ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
Monitor riempisvuota {&lt;br /&gt;
    Int MAXPROCESSI;&lt;br /&gt;
    Stack s;&lt;br /&gt;
    condition ok2enter;&lt;br /&gt;
    condition ok2exit;&lt;br /&gt;
 &lt;br /&gt;
    p.e void entra(getPid()){ &lt;br /&gt;
        if( s.size() &amp;gt;= MAXPROCESSI)&lt;br /&gt;
            ok2enter.wait();&lt;br /&gt;
        s.insert(getPid());&lt;br /&gt;
        if(s.size() &amp;gt; MAXPROCESSI)&lt;br /&gt;
            ok2exit.signal() &lt;br /&gt;
    }&lt;br /&gt;
 &lt;br /&gt;
    p.e void esci(getPid()){ &lt;br /&gt;
        if(s.size() &amp;gt; MAXPROCESSI &amp;amp;&amp;amp; s.top == getPid()) {&lt;br /&gt;
            s.pop();&lt;br /&gt;
            ok2entra.signal()&lt;br /&gt;
        }&lt;br /&gt;
        else&lt;br /&gt;
            ok2exit.wait();&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Esercizio c.2 (ERRATO) ===&lt;br /&gt;
&lt;br /&gt;
* Soluzione proposta è errata, non puoi riceve in modo greedy e printare subito il carattere [[User:Flecart|Flecart]] ([[User talk:Flecart|talk]]) 11:33, 18 January 2023 (CET)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
proc[x]: x='a',...,'z'&lt;br /&gt;
 while True:&lt;br /&gt;
  //c sarà il carattere stampato dal processo precedente&lt;br /&gt;
  (c, string) = arecv(*)&lt;br /&gt;
  if(string == wait){&lt;br /&gt;
    //mi metto in attesa di ricevere l'ACK da proc[x]&lt;br /&gt;
    m=arecv(x);&lt;br /&gt;
  }&lt;br /&gt;
  if (c == NONE){&lt;br /&gt;
    //significa che sei il primo a ricevere quella stringa&lt;br /&gt;
    print(x);&lt;br /&gt;
    if (len(string) &amp;gt; 1){&lt;br /&gt;
      //mando la wait a tutti, il primo che riceve qualcosa da stampare manda una wait a tutti&lt;br /&gt;
      asend(wait,*);&lt;br /&gt;
      int l = len(string);&lt;br /&gt;
      int i = 1;&lt;br /&gt;
      while(l != 0){&lt;br /&gt;
        asend(proc[string[i]], (x, string[i...]));&lt;br /&gt;
        //si mette in attesa di ricevere l'ACK dal processo dell'ultima lettera della parola&lt;br /&gt;
        m=areceive(proc[string[i]]);&lt;br /&gt;
        //rimando la wait al processo per ribloccarlo&lt;br /&gt;
        asend(wait, proc[string[i]])&lt;br /&gt;
        l--;&lt;br /&gt;
        i++;&lt;br /&gt;
      }&lt;br /&gt;
      //dopo aver finito la stampa della stringa sblocco tutti i processi&lt;br /&gt;
      asend(ACK, *);&lt;br /&gt;
    }&lt;br /&gt;
  }else{&lt;br /&gt;
    print(x);&lt;br /&gt;
    asend(ACK, x);&lt;br /&gt;
    //ricomincia il ciclo while, si rimette in attesa e il 'gestore gli rimanda la wait'&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.2  ===&lt;br /&gt;
[[User:Flecart|Flecart friend]] ([[User talk:Flecart|talk]]) cedo la proprità intellettuale di questa soluzione a flecart&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
process [x]: x='a'..'z'&lt;br /&gt;
  if(x=='a'){&lt;br /&gt;
    asend(&amp;lt;NULL,NULL&amp;gt;,'b');&lt;br /&gt;
    asend(&amp;lt;NULL,NULL&amp;gt;,'b');&lt;br /&gt;
  }&lt;br /&gt;
  While True:&lt;br /&gt;
    &amp;lt;c,string&amp;gt;=arecv(x-1+26%26);&lt;br /&gt;
    if(string==NULL):&lt;br /&gt;
      &amp;lt;c,string&amp;gt;=arecv(*);&lt;br /&gt;
      if(string!=NULL):&lt;br /&gt;
        &amp;lt;c,string&amp;gt;=arecv(x-1+26%26);&lt;br /&gt;
&lt;br /&gt;
    if(string!=NULL):&lt;br /&gt;
      if(string[0]==x):&lt;br /&gt;
        print(string[0]);&lt;br /&gt;
        if(string.len()&amp;gt;1):&lt;br /&gt;
          aasend(&amp;lt;NULL,string[1:]&amp;gt;,(x+1)%26);&lt;br /&gt;
        else:&lt;br /&gt;
          aasend(&amp;lt;NULL,NULL&amp;gt;,(x+1)%26);&lt;br /&gt;
          aasend(&amp;lt;NULL,NULL&amp;gt;,(x+1)%26);&lt;br /&gt;
      else:&lt;br /&gt;
          aasend(&amp;lt;NULL,string&amp;gt;,(x+1)%26);&lt;br /&gt;
    else:&lt;br /&gt;
      aasend(&amp;lt;NULL,NULL&amp;gt;,(x+1)%26);&lt;br /&gt;
      aasend(&amp;lt;NULL,NULL&amp;gt;,(x+1)%26);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Proposta c2 ===&lt;br /&gt;
* Proposto [[User:Flecart|Flecart]] ([[User talk:Flecart|talk]]) 11:31, 18 January 2023 (CET)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
proc[a]:&lt;br /&gt;
	bool occupied = false;&lt;br /&gt;
	queue&amp;lt;string&amp;gt; s;&lt;br /&gt;
	&lt;br /&gt;
	while True {&lt;br /&gt;
		(c, string) = arecv(*);&lt;br /&gt;
		&lt;br /&gt;
		if (c == NONE) {&lt;br /&gt;
			if (occupied) {&lt;br /&gt;
				s.enqueue(string);&lt;br /&gt;
			} else {&lt;br /&gt;
				if (string.len() &amp;lt; 1)&lt;br /&gt;
					continue;&lt;br /&gt;
			&lt;br /&gt;
				occupied = true;&lt;br /&gt;
				asend(string[0], (MIDDLE, string));&lt;br /&gt;
			}&lt;br /&gt;
		} else if (c == END) {&lt;br /&gt;
			if (s.size() &amp;gt; 0) {&lt;br /&gt;
				string ss = s.dequeue();&lt;br /&gt;
				asend(string[0], (MIDLLE, string));&lt;br /&gt;
			} else {&lt;br /&gt;
				occupied = false;&lt;br /&gt;
			}&lt;br /&gt;
		} else {&lt;br /&gt;
			print(x);&lt;br /&gt;
			if (len(string) &amp;gt; 1) &lt;br /&gt;
				asend(proc[string[0]], (MIDDLE, string[1:]));&lt;br /&gt;
			else:&lt;br /&gt;
				asend(proc[a], (END, &amp;quot;&amp;quot;));&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
		&lt;br /&gt;
proc[x]: x = 'b', ... 'z';&lt;br /&gt;
	while True {&lt;br /&gt;
		(c, string) = arecv(*);&lt;br /&gt;
		if (c == NONE) {&lt;br /&gt;
			asend(proc['a'], (NONE, string));&lt;br /&gt;
		} else {  // potrà essere solo MIDDLE&lt;br /&gt;
			print(x);&lt;br /&gt;
			if (len(string) &amp;gt; 1) &lt;br /&gt;
				asend(proc[string[0]], (MIDDLE, string[1:]));&lt;br /&gt;
			else:&lt;br /&gt;
				asend(proc[a], (END, &amp;quot;&amp;quot;));&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Esame 12/02/2018 =&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2018.02.12.tot.pdf 2018.02.12.tot.pdf]&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.1 (da controllare) ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
monitor bridge:&lt;br /&gt;
&lt;br /&gt;
    int ncar&lt;br /&gt;
    bool boat_on_0&lt;br /&gt;
    bool boat_on_1       // per semplicità, quando nel codice si trova boat_on_(direction) oppure isBoat(direction)(),&lt;br /&gt;
                         // si valuta il valore booleano di direction e lo si applica sotto forma di stringa al simbolo&lt;br /&gt;
                         // ad esso adiacente&lt;br /&gt;
    bool is_raised&lt;br /&gt;
    queue waiting_mean   // i valori possibili sono: boat0, boat1 oppure car&lt;br /&gt;
    condition ok2go&lt;br /&gt;
  &lt;br /&gt;
    entry car_enter(direction): &lt;br /&gt;
        if is_raised || ncar == MAXCAR:&lt;br /&gt;
            waiting_mean.enqueue(car)&lt;br /&gt;
            ok2go.wait()&lt;br /&gt;
        is_raised = false&lt;br /&gt;
        ++ncar&lt;br /&gt;
  &lt;br /&gt;
    entry car_exit(direction):&lt;br /&gt;
        --ncar&lt;br /&gt;
        if (waiting_mean.top().isBoat() &amp;amp;&amp;amp; ncar == 0) || waiting_mean.top().isCar():    // isBoat ritorna true se l'oggetto su cui&lt;br /&gt;
            waiting_mean.dequeue()                                                      // è invocata è boat0 oppure boat1&lt;br /&gt;
            ok2go.signal()&lt;br /&gt;
  &lt;br /&gt;
    entry boat_enter(direction):&lt;br /&gt;
        if !is_raised || boat_on_(direction):&lt;br /&gt;
            waiting_mean.enqueue(boat)&lt;br /&gt;
            ok2go.wait()&lt;br /&gt;
        if waiting_mean.top().isBoat(!direction)():&lt;br /&gt;
            waiting_mean.dequeue()&lt;br /&gt;
            ok2go.signal()&lt;br /&gt;
        is_raised = true&lt;br /&gt;
        boat_on_(direction) = true&lt;br /&gt;
  &lt;br /&gt;
    entry boat_exit(direction):&lt;br /&gt;
        boat_on_(direction) = false&lt;br /&gt;
        if !boat_on_(!direction):&lt;br /&gt;
            waiting_mean.dequeue()&lt;br /&gt;
            ok2go.signal()&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.1 ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
monitor bridge  {&lt;br /&gt;
  int carsOnBridge = 0;&lt;br /&gt;
  int shipping[2] = {0, 0}; //navi da entrambe le direzioni&lt;br /&gt;
  int status = NONE; //UP DOWN NONE&lt;br /&gt;
  int last2pass = 0;     //ultimo che ha passato il ponte&lt;br /&gt;
  int waitingC = 0;      //coda delle macchine che aspettano&lt;br /&gt;
  int waitingS[2] = {0,0};  //navi che stanno aspettando&lt;br /&gt;
   &lt;br /&gt;
  condition ok2ship[2]&lt;br /&gt;
  condition ok2drive&lt;br /&gt;
 &lt;br /&gt;
entry car_enter(int direction){&lt;br /&gt;
    if(carsOnBridge &amp;gt;= MAX || status == UP || waitingS[0] + waitingS[1] &amp;gt; 0 ){&lt;br /&gt;
        waitingC++;ok2drive.wait;waitingC--;}&lt;br /&gt;
    status = DOWN;&lt;br /&gt;
    carsOnBridge++&lt;br /&gt;
    if (carsOnBridge &amp;lt; MAX)&lt;br /&gt;
       ok2drive.signal();     //vanno tutte le MAX car che stanno aspettando&lt;br /&gt;
} &lt;br /&gt;
entry car_exit(int direction){&lt;br /&gt;
    carsOnBridge--&lt;br /&gt;
    if (waitingS[0] + waitingS[1] == 0)&lt;br /&gt;
    ok2drive.signal();&lt;br /&gt;
    if(carsOnBridge == 0){&lt;br /&gt;
        ok2ship[0].signal(); ok2ship[1].signal();&lt;br /&gt;
    }&lt;br /&gt;
    if(carsOnBridge + waitingS[0] + waitingS[1] == 0) &lt;br /&gt;
    status = NONE&lt;br /&gt;
}&lt;br /&gt;
 &lt;br /&gt;
entry ship_enter(int direction){&lt;br /&gt;
    if (bridge = DOWN || shipping[direction] != 0 || waitingC &amp;gt; 0)&lt;br /&gt;
    {&lt;br /&gt;
        waitingS[i]++; ok2ship[i].wait(); waitingS[i]--; &lt;br /&gt;
    }&lt;br /&gt;
    isBridgeUp = false;&lt;br /&gt;
    shipping[i] = 1;&lt;br /&gt;
 &lt;br /&gt;
entry ship_exit(int direction){&lt;br /&gt;
      shipping[i] = 0;&lt;br /&gt;
      if (waitingC == 0)&lt;br /&gt;
          ok2ship[i].signal()&lt;br /&gt;
      else if(shipping[1-i] == 0)&lt;br /&gt;
          ok2drive.signal();&lt;br /&gt;
      if(carsOnBridge + waitingS[0] + waitingS[1] == 0) &lt;br /&gt;
      status = NONE&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.1 (da controllare) ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
monitor bridge {&lt;br /&gt;
&lt;br /&gt;
  UP=0;&lt;br /&gt;
  DOWN=1;&lt;br /&gt;
  bridgeis = DOWN;&lt;br /&gt;
&lt;br /&gt;
  bool carAreExiting = false;&lt;br /&gt;
&lt;br /&gt;
  condition ok2drive;&lt;br /&gt;
  condition ok2barca[2];&lt;br /&gt;
&lt;br /&gt;
  waitingCar = 0;&lt;br /&gt;
  carOnBridge = 0;&lt;br /&gt;
&lt;br /&gt;
  boatWaiting[2] = {0,0};&lt;br /&gt;
  boatIsPassing[2] = {false,false}&lt;br /&gt;
&lt;br /&gt;
  entry car_enter(direction) {&lt;br /&gt;
&lt;br /&gt;
    if (bridgeis == DOWN)&lt;br /&gt;
      if(carOnBridge == MAXCAR)&lt;br /&gt;
        waitingCar++;&lt;br /&gt;
        ok2drive.wait();&lt;br /&gt;
        waitingCar--;&lt;br /&gt;
      else if (carAreExiting)&lt;br /&gt;
        waitingCar++;&lt;br /&gt;
        ok2drive.wait();&lt;br /&gt;
        waitingCar--;&lt;br /&gt;
    else &lt;br /&gt;
      if (boatIsPassing[0] || boatIsPassing[1])&lt;br /&gt;
        waitingCar++;&lt;br /&gt;
        ok2drive.wait();&lt;br /&gt;
        waitingCar--;&lt;br /&gt;
        bridgeis = DOWN;&lt;br /&gt;
&lt;br /&gt;
    carOnBridge++;&lt;br /&gt;
    carAreExiting = false;&lt;br /&gt;
    if(carOnBridge &amp;lt; MAXCAR &amp;amp;&amp;amp; !carAreExiting) &lt;br /&gt;
      ok2drive.signal();&lt;br /&gt;
      &lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  entry car_exit(direction) {&lt;br /&gt;
&lt;br /&gt;
    carOnBridge--;&lt;br /&gt;
    carAreExiting = true;&lt;br /&gt;
&lt;br /&gt;
    if(carOnBridge == 0)&lt;br /&gt;
      carAreExiting = false;&lt;br /&gt;
      if(boatWaiting[0] &amp;gt; 0)&lt;br /&gt;
        bridgeis = UP;&lt;br /&gt;
        ok2barca[0].signal();&lt;br /&gt;
      else if (boatWaiting[1] &amp;gt; 0)&lt;br /&gt;
        bridgeis = UP;&lt;br /&gt;
        ok2barca[1].signal();&lt;br /&gt;
      else &lt;br /&gt;
        ok2drive.signal();&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  entry boat_enter(direction) {&lt;br /&gt;
&lt;br /&gt;
    if (bridgeis == UP)&lt;br /&gt;
    | if (boatIsPassing[direction] == true)&lt;br /&gt;
    | |  boatWaiting[direction]++;&lt;br /&gt;
    | |  ok2barca.wait();&lt;br /&gt;
    | |  boatWaiting[direction]--;&lt;br /&gt;
    else &lt;br /&gt;
    | if (carOnBridge &amp;gt; 0)&lt;br /&gt;
    | | boatWaiting[direction]++;&lt;br /&gt;
    | | ok2barca.wait();&lt;br /&gt;
    | | boatWaiting[direction]--;&lt;br /&gt;
    | | bridgeis = UP;&lt;br /&gt;
&lt;br /&gt;
    boatIsPassing[direction] = true;&lt;br /&gt;
&lt;br /&gt;
    if(boatIsPassing[1-direction] == false &amp;amp;&amp;amp; boatWaiting[1-direction] &amp;gt; 0)&lt;br /&gt;
      ok2barca[1-direction].signal();&lt;br /&gt;
    &lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  entry boat_exit(direction) {&lt;br /&gt;
&lt;br /&gt;
    boatIsPassing[direction] = false;&lt;br /&gt;
&lt;br /&gt;
    if (boatIsPassing[1-direction] == false)&lt;br /&gt;
      if (waitingCar &amp;gt; 0)&lt;br /&gt;
        bridgeis = DOWN;&lt;br /&gt;
        ok2drive.signal();&lt;br /&gt;
    else&lt;br /&gt;
        if (waitingCar == 0)&lt;br /&gt;
          ok2barca[direction].signal();&lt;br /&gt;
          &lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.1 (sbagliato) ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
monitor bridge&lt;br /&gt;
  condition ok2passCar;&lt;br /&gt;
  condition ok2passBoat;&lt;br /&gt;
  condition ok2up;&lt;br /&gt;
  condition ok2down;&lt;br /&gt;
  int carOnBridge[2] = 0; //2 sensi di marcia&lt;br /&gt;
  int boatUnderBridge[2] = 0;&lt;br /&gt;
  boolean bridge_down = false; //vuol dire che il ponte parte alzato, true ponte abbassato&lt;br /&gt;
  &lt;br /&gt;
  procedure entry car_enter(direction){&lt;br /&gt;
      if(bridge_down &amp;amp;&amp;amp; carOnBridge[direction] &amp;lt; MAXCAR){&lt;br /&gt;
        carOnBridge[direction]++;&lt;br /&gt;
        ok2passCar.signal();&lt;br /&gt;
      }else if (bridge_down &amp;amp;&amp;amp; boatUnderBridge[0] == 0 &amp;amp;&amp;amp; boatUnderBridge[1] == 0){&lt;br /&gt;
        //se non ci sono navi in transito e arriva una macchina abbassa ponte&lt;br /&gt;
        ok2down.signal();&lt;br /&gt;
        ok2passCar.signal();&lt;br /&gt;
        ok2passBoat.wait();&lt;br /&gt;
      }else{&lt;br /&gt;
        ok2passCar.wait();&lt;br /&gt;
      }&lt;br /&gt;
  }     &lt;br /&gt;
        &lt;br /&gt;
  procedure entry car_exit(direction){&lt;br /&gt;
      carOnBridge[direction]--;&lt;br /&gt;
      if(carOnBridge[0] == 0 &amp;amp;&amp;amp; carOnBridge[1] == 0){&lt;br /&gt;
        bridge_down = false;&lt;br /&gt;
        ok2up.signal();&lt;br /&gt;
      }else{&lt;br /&gt;
        ok2up.wait();&lt;br /&gt;
      }&lt;br /&gt;
  }&lt;br /&gt;
      &lt;br /&gt;
  procedure entry boat_enter(direction){&lt;br /&gt;
      if(!bridge_down &amp;amp;&amp;amp; boatUnderBridge[direction] &amp;lt; 1){&lt;br /&gt;
        boatUnderBridge[direction]++;&lt;br /&gt;
        ok2passBoat.signal();&lt;br /&gt;
      }else if(!bridge_down &amp;amp;&amp;amp; carOnBridge[0] == 0 &amp;amp;&amp;amp; carOnBridge[1] == 0){&lt;br /&gt;
        ok2up.signal();&lt;br /&gt;
        ok2passBoat.signal();&lt;br /&gt;
        ok2passCar.wait();&lt;br /&gt;
      }else {&lt;br /&gt;
        ok2passBoat.wait();&lt;br /&gt;
      }&lt;br /&gt;
  }&lt;br /&gt;
      &lt;br /&gt;
  procedure entry boat_exit(direction){  &lt;br /&gt;
      boatUnderBridge[direction]--;&lt;br /&gt;
      if(boatUnderBridge[0] == 0 &amp;amp;&amp;amp; boatUnderBridge[1] == 0){&lt;br /&gt;
        bridge_down = true;&lt;br /&gt;
        ok2down.signal();&lt;br /&gt;
      }else{&lt;br /&gt;
        ok2down.wait();&lt;br /&gt;
      }&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.1 2o (sbagliato) ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define car 1&lt;br /&gt;
#define ship 2 &lt;br /&gt;
#define fromDX 1&lt;br /&gt;
#define fromSX 0&lt;br /&gt;
&lt;br /&gt;
monitor bridge  {&lt;br /&gt;
  int carsOnBridge = 0;&lt;br /&gt;
  int shippingDX = 0; //nave che sta passando dal lato destro&lt;br /&gt;
  int shippingSX = 0; //nave che sta passando dal lato sinistro&lt;br /&gt;
  bool isBridgeUp = false;&lt;br /&gt;
  int last2pass = 0;     //ultimo che ha passato il ponte&lt;br /&gt;
  int waitingS = 0;  //navi che stanno aspettando&lt;br /&gt;
  int waitingC = 0 ; //auto che stanno aspettando&lt;br /&gt;
  &lt;br /&gt;
  condition ok2ship&lt;br /&gt;
  condition ok2drive&lt;br /&gt;
&lt;br /&gt;
entry car_enter(int direction){&lt;br /&gt;
    //un auto si ferma se il numero di auto sul ponte è massimo&lt;br /&gt;
    //e se l'ultima a passare è stata un auto mentre ci sono navi in attesa&lt;br /&gt;
    if(carsOnBridge == MAX || isBridgeUp || (last2pass==car &amp;amp;&amp;amp; waitingS &amp;gt; 0) ){&lt;br /&gt;
        waitingC++;&lt;br /&gt;
        ok2drive.wait;&lt;br /&gt;
    }&lt;br /&gt;
    carsOnBridge++;&lt;br /&gt;
    waitingC--;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
entry car_exit(int direction){&lt;br /&gt;
    carsOnBridge--;&lt;br /&gt;
    last2pass = car;&lt;br /&gt;
    if(carsOnBridge == 0 &amp;amp;&amp;amp; waitingS&amp;gt;0){&lt;br /&gt;
        isBrigdeUp = true;&lt;br /&gt;
        ok2ship.signal;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
entry ship_enter(int direction){&lt;br /&gt;
    //se la barca viene da destra&lt;br /&gt;
    if(direction == fromDX){&lt;br /&gt;
        //si ferma anche quando c'è una nave che sta già attraversando nella sua stessa direzione&lt;br /&gt;
        if (isBridgeup == false || shippingDX || (last2pass==ship &amp;amp;&amp;amp; waitingC &amp;gt; 0) ){&lt;br /&gt;
            waitingS++;&lt;br /&gt;
            ok2ship.wait;&lt;br /&gt;
        }&lt;br /&gt;
        if (waitingS &amp;gt; 0)&lt;br /&gt;
            waitingS--;&lt;br /&gt;
        shippingDX = 1;&lt;br /&gt;
        }&lt;br /&gt;
    //se la barca viene da sinistra&lt;br /&gt;
    else if(direction == fromSX){&lt;br /&gt;
        if (isBridgeup == false || shippingSX || ( (last2pass==ship &amp;amp;&amp;amp; waitingC &amp;gt; 0))){&lt;br /&gt;
        waitingS++;&lt;br /&gt;
        ok2ship.wait;&lt;br /&gt;
        }&lt;br /&gt;
        if (waitingS &amp;gt; 0)&lt;br /&gt;
            waitingS--;        &lt;br /&gt;
        shippingSX = 1;&lt;br /&gt;
    &lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
entry ship_exit(int direction){&lt;br /&gt;
        if(direction == fromDX)&lt;br /&gt;
            shippingDX = 0;&lt;br /&gt;
        else if (direction == fromSX)&lt;br /&gt;
            shippingSX = 0;&lt;br /&gt;
        last2pass = ship;&lt;br /&gt;
        if(shippingDX == 0 &amp;amp;&amp;amp; shippingSX == 0 &amp;amp;&amp;amp; waitingC)&lt;br /&gt;
            isBrigdeUp == false;&lt;br /&gt;
            ok2drive.signal;&lt;br /&gt;
        else if(shippingDX == 0 &amp;amp;&amp;amp; shippingSX == 0 &amp;amp;&amp;amp; waitingS &amp;gt; 0)&lt;br /&gt;
            ok2ship.signal;    &lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.2 (sbagliato) ===&lt;br /&gt;
&lt;br /&gt;
# (Ri)Controllato dall'utente [[User:Acsor|Acsor]] ([[User talk:Acsor|talk]]) in data 26/08/2020&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
list printed_msg;  # questa è una variabile condivisa che ai fini dell'esercizio non si può utilizzare (message passing)&lt;br /&gt;
&lt;br /&gt;
process server[i]:&lt;br /&gt;
  while true:&lt;br /&gt;
    &amp;lt;msg, pid&amp;gt; = arecv(*)&lt;br /&gt;
&lt;br /&gt;
    if printed_msg.length == 0 or &amp;lt;msg, pid&amp;gt; is not in printed_msg:&lt;br /&gt;
      printed_msg.append(&amp;lt;msg,id&amp;gt;)&lt;br /&gt;
      print(msg)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.2 (da controllare) ===&lt;br /&gt;
Nello svolgimento seguente, receiver incapsula l'ambiente privato del processo; _peers rappresenta il vettore di processi &amp;quot;fratelli&amp;quot; ai quali può essere chiesto di stampare un messaggio, mentre _printed contiene l'hash di tutti i messaggi stampati dal processo locale. Si suppone che istanze della classe receiver possano essere passate come parametro ad areceive() ed asend() (non implementate).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
class receiver:&lt;br /&gt;
    def __init__(self, peers):&lt;br /&gt;
        &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
        :param peers: list of processes this process communicates with.&lt;br /&gt;
        &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
        self._peers = tuple(peers)&lt;br /&gt;
        self._printed = list()&lt;br /&gt;
    &lt;br /&gt;
    def run(self):&lt;br /&gt;
        while True:&lt;br /&gt;
            process, message = areceive(ANY)&lt;br /&gt;
&lt;br /&gt;
            if process in self._peers:&lt;br /&gt;
                self._reply_query(process, message)&lt;br /&gt;
            else:&lt;br /&gt;
                self._print(process, message)&lt;br /&gt;
&lt;br /&gt;
    def _print(self, sender, message):&lt;br /&gt;
        h = hash(message.text)&lt;br /&gt;
&lt;br /&gt;
        if h not in self._printed and not self._printed_from_peers(message):&lt;br /&gt;
            self._printed.append(h)&lt;br /&gt;
            print(message.text)&lt;br /&gt;
&lt;br /&gt;
    def _reply_query(self, sender, h):&lt;br /&gt;
        &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
        Invoked when the current process receive a &amp;quot;query&amp;quot; from a peer process.&lt;br /&gt;
        `h` contains the hash of a message which may or may have not been&lt;br /&gt;
        sent from this process; if it was sent, the reply is `Yes`, otherwise `No`.&lt;br /&gt;
        &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
        reply = &amp;quot;Yes&amp;quot; if int(h) in self._printed else &amp;quot;No&amp;quot;&lt;br /&gt;
        asend(sender, reply)&lt;br /&gt;
&lt;br /&gt;
    def _printed_from_peers(self, message):&lt;br /&gt;
        &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
        :return: `True` if this message has already been printed from any of the&lt;br /&gt;
        peer processes, `False` otherwise.&lt;br /&gt;
        &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
        h = hash(message)&lt;br /&gt;
&lt;br /&gt;
        for p in self._peers:&lt;br /&gt;
            asend(p, str(h))&lt;br /&gt;
&lt;br /&gt;
        for p in self._peers:&lt;br /&gt;
            _, reply = areceive(p)&lt;br /&gt;
&lt;br /&gt;
            if reply.text == &amp;quot;Yes&amp;quot;:&lt;br /&gt;
                return True&lt;br /&gt;
            else if reply.text != &amp;quot;No&amp;quot;:&lt;br /&gt;
                # If the response is neither &amp;quot;Yes&amp;quot; nor &amp;quot;No&amp;quot;, then we have got a query&lt;br /&gt;
                self._reply_query(p, reply)&lt;br /&gt;
&lt;br /&gt;
        return False&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Esercizio g.1 (da controllare) ===&lt;br /&gt;
Sulla base dei valori in entrata, è possibile costruire le matrici Allocation (q.tà di risorse allocate per processo e per tipo), Need (q.tà di risorse che ogni processo potrebbe ancora chiedere) e il vettore Available (num. di risorse correntemente disponibili).&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;float: left&amp;quot;&lt;br /&gt;
! colspan=3 | Allocation&lt;br /&gt;
|-&lt;br /&gt;
   !   !! A !! B&lt;br /&gt;
|-&lt;br /&gt;
   | p1 || 4 || 5&lt;br /&gt;
|-&lt;br /&gt;
   | p2 || 3 || 3&lt;br /&gt;
|-&lt;br /&gt;
   | p3 || 2 || 4&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;float: left; margin-left: 1em&amp;quot;&lt;br /&gt;
! colspan=3 | Need&lt;br /&gt;
|-&lt;br /&gt;
   !    !! A !! B&lt;br /&gt;
|-&lt;br /&gt;
   | p1 || 6 || 8&lt;br /&gt;
|-&lt;br /&gt;
   | p2 || 6 || 3&lt;br /&gt;
|-&lt;br /&gt;
   | p3 || 6 || 8&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;float: left; margin-left: 1em&amp;quot;&lt;br /&gt;
! colspan=2 | Available&lt;br /&gt;
|-&lt;br /&gt;
   ! A !! B&lt;br /&gt;
|-&lt;br /&gt;
   | x || y&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nel caso delle risorse di tipo A, deve aversi x &amp;gt;= 6 in quanto un processo dovrà essere selezionato come primo nella permutazione dell'algoritmo del banchiere multivaluta, e tutti quelli correnti hanno lo stesso valore Need(i)(1); per ciò che riguarda le risorse di tipo B, possiamo ragionare per esaustione&lt;br /&gt;
&lt;br /&gt;
* Se il primo processo della permutazione è p1, allora y &amp;gt;= 8 (con questo valore posso soddisfare la richiesta di p1 e in seguito tutte le altre)&lt;br /&gt;
* Se il primo processo della permutazione è p2, allora y &amp;gt;= 5: con questo valore è possibile soddisfare la richiesta di p2; una volta che esso avrà finito, restituirà 3 unità della risorsa B, che permetteranno di soddisfare sia le richieste di A sia quelle di C&lt;br /&gt;
* Se il primo processo della permutazione è p3, allora y &amp;gt;= 8 (ragionamento analogo come per p1)&lt;br /&gt;
&lt;br /&gt;
Volendo scegliere il minimo, y &amp;gt;= 5, ed in conclusione (x, y) &amp;gt;= (6, 5).&lt;br /&gt;
&lt;br /&gt;
''Svolgimento basato in parte sull'approccio di Operating System Concepts di Silberschatz. et al, 9th edition, cap. 7.''&lt;br /&gt;
&lt;br /&gt;
=== Esercizio g.2 (da controllare) ===&lt;br /&gt;
# Può accadere che il sistema torni in uno stato di safety o che invece porti a deadlock. Diversamente uno stato di safety non può portare direttamente ad uno stato di deadlock, ma solo ad uno di non-safety.&lt;br /&gt;
# Selezionare uno o più tra i processi attivi e sospenderli, salvando il loro stato su memoria secondaria operando delle operazioni di swap-out, finché l'insieme dei frame nella memoria centrale non è in grado di soddisfare tutti i processi rimasti attivi.&lt;br /&gt;
# La scelta è determinata perlopiù dal fattore costo. Con un sistema RAID 1 è possibile ripristinare un disco guasto molto brevemente, in quanto le operazioni coinvolte prevedono una semplice ricopiatura dal disco di backup; con un sistema RAID 5 il ripristino del disco guasto deve coinvolgere tutti i dischi dell'intero array, e ciò può richiedere anche ore per dischi di grandi dimensioni. D'altra parte RAID 1 è più costoso (con n dischi, posso memorizzare tanta informazione quanto potrei con n / 2 dischi) rispetto a RAID 5 dove, tra gli n dischi, complessivamente soltanto uno è destinato alle informazioni di ridondanza.&lt;br /&gt;
# ''Completare.''&lt;/div&gt;</summary>
		<author><name>LiberaL</name></author>
	</entry>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=Prove_scritte_2018&amp;diff=2977</id>
		<title>Prove scritte 2018</title>
		<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php?title=Prove_scritte_2018&amp;diff=2977"/>
		<updated>2023-05-12T14:48:40Z</updated>

		<summary type="html">&lt;p&gt;LiberaL: /* Soluzione &amp;quot;schiacciasassi&amp;quot; */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Esame 19/09/2018 =&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2018.09.19.tot.pdf Testo dell'esame].&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.2 (da controllare) ===&lt;br /&gt;
&lt;br /&gt;
* Controllato dall'utente ? in data ?&lt;br /&gt;
* ...&lt;br /&gt;
&lt;br /&gt;
Nello pseudocodice seguente, il termine this fa riferimento al processo corrente, mentre ANY ad uno qualunque.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
stack&amp;lt;message&amp;gt; messages;&lt;br /&gt;
&lt;br /&gt;
void lifo_send(string m, process dest) {&lt;br /&gt;
	do {&lt;br /&gt;
		asend(m, dest);&lt;br /&gt;
	} while (areceive(dest).text != &amp;quot;ACK&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
message lifo_receive(process source) {&lt;br /&gt;
	if (source != ANY) {&lt;br /&gt;
		message m = areceive(source);&lt;br /&gt;
&lt;br /&gt;
		asend(&amp;quot;ACK&amp;quot;, source);&lt;br /&gt;
&lt;br /&gt;
		return m;&lt;br /&gt;
	} else {&lt;br /&gt;
		message m;&lt;br /&gt;
&lt;br /&gt;
		asend(&amp;quot;END&amp;quot;, this);&lt;br /&gt;
		m = areceive(ANY);&lt;br /&gt;
&lt;br /&gt;
		while (m.text != &amp;quot;END&amp;quot; || m.sender != this) {&lt;br /&gt;
			messages.push(m);&lt;br /&gt;
			asend(&amp;quot;ACK&amp;quot;, m.sender);&lt;br /&gt;
&lt;br /&gt;
			m = areceive(ANY);&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
                /* Bisogna tenere conto dei casi in cui lifo_receive() viene invocata quando nessun&lt;br /&gt;
                 * messaggio è stato ancora spedito da altri processi. In tal caso si attende il&lt;br /&gt;
                 * il primo e lo si restituisce.&lt;br /&gt;
                 */&lt;br /&gt;
		if (messages.empty()) {&lt;br /&gt;
			m = areceive(ANY);&lt;br /&gt;
			asend(&amp;quot;ACK&amp;quot;, m.sender);&lt;br /&gt;
&lt;br /&gt;
			return m;&lt;br /&gt;
		} else {&lt;br /&gt;
			return messages.pop();&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Esame 17/07/2018 =&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2018.07.17.tot.pdf 2018.07.17.tot.pdf]&lt;br /&gt;
== Esercizio c.1 ==&lt;br /&gt;
A Bruxelles c'è un locale chiamato Delirium Café. Alla vigilia del FOSDEM tutti gli anni gli sviluppatori europei di&lt;br /&gt;
software libero si ritrovano a bere birra (il locale è nel guinnes dei primati con più di duemila tipi di birra). Il prossimo appuntamento è&lt;br /&gt;
fissato per il 1 febbraio 2019 ore 20. Numerosi sono i tipi di birra alla spina. I baristi (tanti) prendono gli ordini (es. mezza pinta, 1 o 2&lt;br /&gt;
pinte) e riempiono i bicchieri. Quando un fusto e' vuoto avvertono i magazzinieri che prendono un nuovo fusto che contiene più di&lt;br /&gt;
cento pinte e lo sostituiscono, a questo punto il barista può completare il riempimento del bicchiere.&lt;br /&gt;
La vita di un barista del Delirium è:&lt;br /&gt;
 while True:&lt;br /&gt;
   (type, quantity) = get_order()&lt;br /&gt;
   delirium.pour(type, quantity)&lt;br /&gt;
La vita di un Magazziniere è:&lt;br /&gt;
 while True:&lt;br /&gt;
   type = delirium.isempty()&lt;br /&gt;
   capacity = change_keg(type)&lt;br /&gt;
   delirium.loaded(type, capacity)&lt;br /&gt;
&lt;br /&gt;
Attenzione: se il fusto (keg) è quasi vuoto il barista dovrà riempire parzialmente il bicchiere, occorrerà attivare il magazziniere che&lt;br /&gt;
cambierà il fusto e poi il barista riempirà il bicchiere fino alla quantità richiesta dal cliente. Mentre un barista sta attendendo il&lt;br /&gt;
cambiamento di un fusto altri baristi potrebbero ricevere ordini per lo stesso tipo di birra: gestire opportunamente questo caso.&lt;br /&gt;
Scrivere il monitor Delirium.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Proposta di soluzione 1 === &lt;br /&gt;
* ERRORE: Secondo me c'è un leggero errore nella parte di load, nel caso in cui la nuova pinta non riesca a soddisfare completamente la richiesta ossia quando vale availableBeer[t] &amp;lt;= requests[t].head(), allora non lo risveglio nemmeno, invece dovrei risvegliare il pour, fargli versare quanto può, e richiedere una altra pinta, perché questo era un requisito del problema. [[User:Flecart|Flecart]] ([[User talk:Flecart|talk]]) 12:00, 15 January 2023 (CET)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
/* Monitor Delirum: */&lt;br /&gt;
&lt;br /&gt;
// Condition: Ok2Load;&lt;br /&gt;
// Condition: Ok2Pour[]; // Un elemento per Type&lt;br /&gt;
int availableBeer[]; // Un elemento per Type &lt;br /&gt;
Queue requests[]; // Un elemento per Type&lt;br /&gt;
Queue pendingRequests;&lt;br /&gt;
&lt;br /&gt;
Procedure entry: void Pour(Type t, Quantity c)&lt;br /&gt;
{&lt;br /&gt;
    if (c &amp;gt; availableBeer[t]) // Richiesta maggiore della birra disponibile&lt;br /&gt;
    {&lt;br /&gt;
        c -= availableBeer[t];&lt;br /&gt;
        availableBeer[t] = 0;              &lt;br /&gt;
        requests[t].Enqueue(c);&lt;br /&gt;
        if (requests[t].Length == 1) // Risveglio un magazziniere solo se è la prima richiesta di questo tipo di birra&lt;br /&gt;
        {&lt;br /&gt;
            pendingRequests.Enqueue(t);&lt;br /&gt;
            Ok2Load().Signal();&lt;br /&gt;
        }&lt;br /&gt;
        Ok2Pour[t].Wait();&lt;br /&gt;
        requests[t].Dequeue(); // Quando ho ottenuto la birra che voglio, elimino la mia richiesta&lt;br /&gt;
    }&lt;br /&gt;
    availableBeer[t] -= c;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: Type isEmpty()&lt;br /&gt;
{&lt;br /&gt;
    if (pendingRequests.Length == 0)&lt;br /&gt;
    {&lt;br /&gt;
        Ok2Load.Wait();&lt;br /&gt;
    }&lt;br /&gt;
    return pendingRequests.Dequeue();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: Loaded(Type t, Capacity c)&lt;br /&gt;
{&lt;br /&gt;
    availableBeer[t] += c;&lt;br /&gt;
    while (requests[t].Length &amp;gt; 0 &amp;amp;&amp;amp; availableBeer[t] &amp;gt; requests[t].head())&lt;br /&gt;
    {&lt;br /&gt;
        Ok2Pour[t].Signal();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (requests[t].Length &amp;gt; 0) // serve per evitare che a causa di un magazziniere lento si accodino cosi tante richieste che mentre si sta caricando si svuota subito il fusto&lt;br /&gt;
    {&lt;br /&gt;
        pendingRequests.Enqueue(t);&lt;br /&gt;
        Ok2Load.Signal();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Proposta di soluzione 2 ===&lt;br /&gt;
* Proposto da [[User:Flecart|Flecart]] ([[User talk:Flecart|talk]]) 13:41, 15 January 2023 (CET)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
extern int MAX_TYPE;&lt;br /&gt;
class Delirium {&lt;br /&gt;
    int keg[MAX_TYPE];      // qnty fusto attuale&lt;br /&gt;
    int orders[MAX_TYPE];   // qnty richiesta&lt;br /&gt;
    bool worked[MAX_TYPE];  // 1 se magazziniere sta lavorando su questo.&lt;br /&gt;
&lt;br /&gt;
    condition type_wait[MAX_TYPE];&lt;br /&gt;
    int num_wait[MAX_TYPE];&lt;br /&gt;
&lt;br /&gt;
    queue&amp;lt;int&amp;gt; empty_type;&lt;br /&gt;
    condition is_empty;&lt;br /&gt;
&lt;br /&gt;
    entry pour(type, quantity) {&lt;br /&gt;
        while (keg[type] &amp;lt; quantity) {&lt;br /&gt;
            quantity -= keg[type];&lt;br /&gt;
            keg[type] = 0;&lt;br /&gt;
            if (!empty_type.find(type) &amp;amp;&amp;amp; !worked[type]) {&lt;br /&gt;
                empty_type.enqueue(type);&lt;br /&gt;
                is_empty.signal();&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            num_wait[type]++;&lt;br /&gt;
            type_wait[type].wait();&lt;br /&gt;
            num_wait[type]--;&lt;br /&gt;
        }&lt;br /&gt;
        keg[type] -= quantity;&lt;br /&gt;
        quantity = 0;  // questo è inutile, ma concettualmente è corretto, l'ordine è completato.&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    entry loaded(type, capacity) {&lt;br /&gt;
        keg[type] += capacity;&lt;br /&gt;
        worked[type] = false;&lt;br /&gt;
&lt;br /&gt;
        for (int i = num_wait[type]; i &amp;gt; 0; i--) {&lt;br /&gt;
            type_wait[type].signal();&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // si suppone che un singolo tipo di fusto è lavorabile da un solo magazziniere alla volta.&lt;br /&gt;
    // worked impedisce di avere nella coda un fusto su cuisi sta già lavorando.&lt;br /&gt;
    entry isempty() {&lt;br /&gt;
        if (empty_type.size() &amp;lt;= 0) {&lt;br /&gt;
            is_emtpy.wait();&lt;br /&gt;
        }&lt;br /&gt;
        int type = emtpy_type.dequeue();&lt;br /&gt;
        worked[type] = true;&lt;br /&gt;
        return type;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Esercizio c.2 ==&lt;br /&gt;
&lt;br /&gt;
=== Proposta di soluzione 1 ===&lt;br /&gt;
* Visto e corretto dall'utente [[User:Acsor|Acsor]] in data 23/08/2020&lt;br /&gt;
* Visto e corretto dall'utente ? in data ?&lt;br /&gt;
* Visto, ritenuto corretto [[User:Flecart|Flecart]] ([[User talk:Flecart|talk]]) 09:27, 15 January 2023 (CET)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
class LIFOBuffer {&lt;br /&gt;
	stack&amp;lt;T&amp;gt; s;&lt;br /&gt;
	semaphore mutex(1); // mutua esclusione&lt;br /&gt;
	semaphore ok2consume(0);&lt;br /&gt;
&lt;br /&gt;
	void push (T value) {&lt;br /&gt;
		mutex.P();&lt;br /&gt;
		s.push(value);&lt;br /&gt;
                // (1)&lt;br /&gt;
		mutex.V()&lt;br /&gt;
&lt;br /&gt;
		ok2consume.V()  // Curiosità: che succede se spostiamo quest'istruzione in (1)? Edit: funziona lo stesso, solo che aggiorni il valore del semaforo prima di uscire dalla mutex.&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	T pop () {&lt;br /&gt;
		T value;&lt;br /&gt;
&lt;br /&gt;
		ok2consume.P();&lt;br /&gt;
		mutex.P();&lt;br /&gt;
		value = s.pop();&lt;br /&gt;
		mutex.V();&lt;br /&gt;
&lt;br /&gt;
		return value;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Proposta di soluzione 2 ===&lt;br /&gt;
Proposto da [[User:Flecart|Flecart]] ([[User talk:Flecart|talk]]) 09:27, 15 January 2023 (CET)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
class lifobuf {&lt;br /&gt;
	semaphore mutex(1);&lt;br /&gt;
	stack&amp;lt;int&amp;gt; values;	// empty initialized&lt;br /&gt;
	stack&amp;lt;semaphore&amp;gt; waiting;	&lt;br /&gt;
&lt;br /&gt;
	push(int value) {&lt;br /&gt;
		mutex.P();&lt;br /&gt;
		values.push(value);&lt;br /&gt;
		if (waiting.size() &amp;gt; 0) {&lt;br /&gt;
			semaphore s = waiting.pop();&lt;br /&gt;
			s.V();&lt;br /&gt;
			return;&lt;br /&gt;
		}&lt;br /&gt;
			&lt;br /&gt;
		mutex.V();	&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	pop() {&lt;br /&gt;
		int ret_val;&lt;br /&gt;
		mutex.P();&lt;br /&gt;
		if (values.size() &amp;lt;= 0) {&lt;br /&gt;
			semaphore s = new semaphore(0);&lt;br /&gt;
			waiting.push(s);&lt;br /&gt;
			mutex.V();&lt;br /&gt;
			s.P();&lt;br /&gt;
			free(s);&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		ret_val = values.pop();&lt;br /&gt;
		mutex.V();	&lt;br /&gt;
&lt;br /&gt;
		return ret_val;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Esercizio g.1 ==&lt;br /&gt;
Possiamo notare subito che il sistema ha due processori ed un dispositivo di I/O.&lt;br /&gt;
'''A''' e '''B''' partono insieme al tempo 0.&amp;lt;br&amp;gt;&lt;br /&gt;
'''C''' parte tra il tempo 0 ed il tempo 2 (non possiamo sapere di preciso quando perchè entrambe le CPU sono occupate).&amp;lt;br&amp;gt;&lt;br /&gt;
'''D''' parte tra il tempo 0 ed il tempo 3.&amp;lt;br&amp;gt;&lt;br /&gt;
A questo punto possiamo supporre che tutti e 4 i processi partano in sequenza ('''A''', '''B''', '''C''', '''D''') nello stesso momento, e ognuno prende la prima CPU libera che trova.&amp;lt;br&amp;gt;&lt;br /&gt;
'''A''' lavora per 3ms, poi scade il time slice.&amp;lt;br&amp;gt;&lt;br /&gt;
Nel frattempo '''B''' lavora per 2ms, poi richiede I/O per 4ms.&amp;lt;br&amp;gt;&lt;br /&gt;
La CPU su cui lavora '''B''' quindi si libera, e si manda in esecuzione il processo '''C'''.&amp;lt;br&amp;gt;&lt;br /&gt;
Scaduto il time slice per '''A''', si da il controllo ad un nuovo processo. '''B''' è occupato con I/O, '''C''' sta già lavorando, quindi è il turno di '''D'''.&amp;lt;br&amp;gt;&lt;br /&gt;
'''C''' lavora per 3ms, poi richiede I/O per 3ms, che però è occupato da '''B''', quindi si mette in coda per utilizzarlo.&amp;lt;br&amp;gt;&lt;br /&gt;
La CPU su cui lavorava '''C''' si libera ed il controllo torna ad '''A''', che doveva lavorare ancora per 2ms prima di chiedere il controllo di I/O, quindi lavora e si mette in coda dietro a '''C'''.&amp;lt;br&amp;gt;&lt;br /&gt;
Tornando a '''D''', questo lavora per 3ms prima che scada il time slice. Anche '''B''' ha finito il lavoro e ha bisogno di una CPU.&amp;lt;br&amp;gt;&lt;br /&gt;
In questo momento sia '''D''' che '''B''' sono nella coda dei processi in stato ready, ma dal diagramma possiamo notare che il controllo torna a '''D'''.&amp;lt;br&amp;gt;&lt;br /&gt;
La CPU ha scelto a caso un processo tra i due, perchè arrivati a questo punto possiamo supporre che lo scheduler sia Round-Robin.&amp;lt;br&amp;gt;&lt;br /&gt;
'''B''' prende possesso della prima CPU che si libera, ovvero quella occupata da '''A''', poi lavora per 2ms e termina il suo lavoro.&amp;lt;br&amp;gt;&lt;br /&gt;
Nel momento in cui '''B''' termina il lavoro, scade anche il time slice per '''D''', e '''C''' termina di usare I/O.&amp;lt;br&amp;gt;&lt;br /&gt;
Abbiamo due processi ('''C''' e '''D''') in coda ready. Ma abbiamo anche due CPU libere, perchè '''A''' è in coda per I/O e ci entra appena '''C''' finisce di usarlo.&amp;lt;br&amp;gt;&lt;br /&gt;
Lo scheduler sceglie di mandare '''C''' sul primo processore e '''D''' sul secondo.&amp;lt;br&amp;gt;&lt;br /&gt;
'''A''' nel frattempo, lavora per 4ms con I/O.&amp;lt;br&amp;gt;&lt;br /&gt;
'''C''' lavora per 3ms, poi termina il suo lavoro.&amp;lt;br&amp;gt;&lt;br /&gt;
'''D''' lavora per 3ms, poi scade il time slice. Ci sono due processori liberi, quindi '''D''' riparte subito in esecuzione.&amp;lt;br&amp;gt;&lt;br /&gt;
'''D''' doveva lavorare ancora per 1ms prima di aver bisogno di I/O, quindi finisce e si mette in coda.&amp;lt;br&amp;gt;&lt;br /&gt;
Ma nello stesso momento '''A''' termina di usare I/O, si prende un processore libero e lavora per i suoi ultimi 2ms.&amp;lt;br&amp;gt;&lt;br /&gt;
'''D''' lavora per 1ms con I/O, poi prende il secondo processore libero e lavora per 1ms prima di terminare il suo lavoro.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Il time slice è di 3ms, lo scheduler è di tipo Round-Robin.&amp;lt;br&amp;gt;&lt;br /&gt;
Il dispositivo di I/O è FIFO. L'ordine con cui partono i processi è quello alfabetico.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
A(){&lt;br /&gt;
    compute_a1(); // 5ms&lt;br /&gt;
    io_a(); // 4ms&lt;br /&gt;
    compute_a2(); // 2ms&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
B(){&lt;br /&gt;
    compute_b(); // 2ms&lt;br /&gt;
    io_b(); // 4ms&lt;br /&gt;
    compute_b(); // 2ms&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
C(){&lt;br /&gt;
    compute_c(); // 3ms&lt;br /&gt;
    io_c(); // 3ms&lt;br /&gt;
    compute_c(); // 3ms&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
D(){&lt;br /&gt;
    compute_d1(); // 10ms&lt;br /&gt;
    io_d(); // 1ms&lt;br /&gt;
    compute_d2(); // 1ms&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Lo scheduler potrebbe anche essere a priorità:&amp;lt;br&amp;gt;&lt;br /&gt;
Priorità '''B''' &amp;lt; priorità '''D''' &amp;lt; priorità '''C'''&amp;lt;br&amp;gt;&lt;br /&gt;
Priorità '''A''' = ?&amp;lt;br&amp;gt;&lt;br /&gt;
'''B''' fatto partire prima di '''C''' e '''D'''.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Esercizio g.2 (da controllare) ==&lt;br /&gt;
# In sistemi dove dispositivi di archiviazione o supporti hardware per la memoria virtuale (e dunque per la paginazione, spesso utilizzata per realizzare il supporto di memoria virtuale) non sono presenti (es. sistemi embedded). ''(In sistemi real-time la memoria virtuale è praticabile? Annotare.)''&lt;br /&gt;
# Perchè ad esempio sulle chiavette USB quasi mai abbiamo il problema di dover utilizzare file di dimensione maggiore ai 4GB. Non utilizza il journaling, che richiede molteplici scritture per ogni azione ed in dispositivi portatili può ridurre di molto la durata. Non supporta i permessi sui file, e questo è un vantaggio per le chiavette USB, pensate per trasferire dati tra PC diversi.&lt;br /&gt;
# Per fornire parallelismo e ridondanza. Non è necessario fare backup dei dati sul disco, nel senso di mantenere una copia identica di dati già memorizzati altrove, in quanto diversi sistemi di codici permettono il rilevamento e/o la correzione di errori.&lt;br /&gt;
# Se in un grafo di Holt multirisorsa esiste un ciclo tra più processi e risorse, ciò non significa che allo stesso tempo non siano coinvolti processi con archi esclusivamente entranti. Ogni processo appartenente a questa categoria non è in attesa di risorse, e può dunque procedere con i suoi calcoli; quando avrà terminato rilascerà le risorse precedentemente allocategli, eventualmente sbloccando uno dei processi coinvolti nel ciclo.&lt;br /&gt;
&lt;br /&gt;
= Esame 21/06/2018 =&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2018.06.21.tot.pdf 2018.06.21.tot.pdf]&lt;br /&gt;
=== Esercizio c.1 (sbagliato) ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
/* Monitor tmon */&lt;br /&gt;
&lt;br /&gt;
define MAX n;&lt;br /&gt;
define TERRAFERMA 1;&lt;br /&gt;
define ISOLA 2;&lt;br /&gt;
&lt;br /&gt;
semaphore ok2unload;&lt;br /&gt;
semaphore ok2load;&lt;br /&gt;
semaphore ok2ship;&lt;br /&gt;
semaphore mutex(1); // la rampa è zona critica --&amp;gt; mutua esclusione&lt;br /&gt;
&lt;br /&gt;
stack ferry;&lt;br /&gt;
int current_port = 0;&lt;br /&gt;
&lt;br /&gt;
Procedure entry: al_porto(int location)&lt;br /&gt;
{&lt;br /&gt;
    current_port = location; // traghetto arriva a destinazione&lt;br /&gt;
    ok2unload.signal(); // da il via per far sbarcare le macchine&lt;br /&gt;
    ok2ship.wait(); // si ferma&lt;br /&gt;
    current_port = 0; // traghetto sta viaggiando tra i due porti&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: imbarca(int location)&lt;br /&gt;
{&lt;br /&gt;
    mutex.wait(); // prende possesso della rampa&lt;br /&gt;
    ferry.push(1); // sale sul traghetto&lt;br /&gt;
    mutex.signal(); // libera la rampa&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: imbarcato(int location)&lt;br /&gt;
{&lt;br /&gt;
    if(ferry.lenght() == MAX) // se il traghetto è pieno da il via per farlo salpare&lt;br /&gt;
    {&lt;br /&gt;
        ok2load.wait();&lt;br /&gt;
        ok2ship.signal();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: sbarca(int location)&lt;br /&gt;
{&lt;br /&gt;
    mutex.wait(); // prende possesso della rampa&lt;br /&gt;
    ferry.pop(); // scende dal traghetto&lt;br /&gt;
    mutex.signal(); // libera la rampa&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: sbarcato(int location)&lt;br /&gt;
{&lt;br /&gt;
    if(ferry.lenght() == 0) // se il traghetto è vuoto da il via per far imbarcare le macchine&lt;br /&gt;
    {&lt;br /&gt;
        ok2unload.wait();&lt;br /&gt;
        ok2load.signal();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.1 ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
/* Monitor tmon */&lt;br /&gt;
 &lt;br /&gt;
#define MAX n&lt;br /&gt;
#define NONE 0&lt;br /&gt;
#define TERRAFERMA 1&lt;br /&gt;
#define ISOLA 2&lt;br /&gt;
 &lt;br /&gt;
condition ok2unload;&lt;br /&gt;
condition ok2load[2];&lt;br /&gt;
condition ok2ship;&lt;br /&gt;
condition empty;&lt;br /&gt;
 &lt;br /&gt;
int onboard = 0;&lt;br /&gt;
int onramp = 0;&lt;br /&gt;
int current_port = NONE;&lt;br /&gt;
&lt;br /&gt;
Procedure entry: al_porto(int location)&lt;br /&gt;
{&lt;br /&gt;
    //arrivando&lt;br /&gt;
    current_port = location;&lt;br /&gt;
    ok2unload.signal();&lt;br /&gt;
    if (onboard &amp;gt; 0)&lt;br /&gt;
        empty.wait()&lt;br /&gt;
    ok2load[location].signal()&lt;br /&gt;
    if (onboard &amp;lt; MAX)&lt;br /&gt;
        ok2ship.wait()&lt;br /&gt;
    //partendo&lt;br /&gt;
    current_port = NONE;&lt;br /&gt;
}&lt;br /&gt;
 &lt;br /&gt;
Procedure entry: imbarca(int location)&lt;br /&gt;
{&lt;br /&gt;
    if (current_port != location || onramp &amp;gt; 0 || onboard &amp;gt;= MAX)&lt;br /&gt;
        ok2load[location].wait()&lt;br /&gt;
    onramp = 1;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: imbarcato(int location)&lt;br /&gt;
{&lt;br /&gt;
    onramp = 0; onboard++;&lt;br /&gt;
    if (onboard &amp;lt; MAX)&lt;br /&gt;
        ok2load[location].signal();&lt;br /&gt;
    else&lt;br /&gt;
        ok2ship.signal();&lt;br /&gt;
}&lt;br /&gt;
 &lt;br /&gt;
Procedure entry: sbarca(int location)&lt;br /&gt;
{&lt;br /&gt;
    if (current_port != location || onramp &amp;gt; 0)&lt;br /&gt;
        ok2unload.wait()&lt;br /&gt;
    onramp = 1;&lt;br /&gt;
}&lt;br /&gt;
 &lt;br /&gt;
Procedure entry: sbarcato(int location)&lt;br /&gt;
{&lt;br /&gt;
    onramp = 0; onboard--;&lt;br /&gt;
    if (onboard == 0)&lt;br /&gt;
        empty.signal();&lt;br /&gt;
    else&lt;br /&gt;
        ok2unload.signal();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.2 (sbagliato) ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define N n // limite operazioni&lt;br /&gt;
semaphore mutex(1); // sezione critica&lt;br /&gt;
&lt;br /&gt;
class lim_semaphore()&lt;br /&gt;
{&lt;br /&gt;
    int value;&lt;br /&gt;
    semaphore plus;&lt;br /&gt;
    semaphore minus;&lt;br /&gt;
    &lt;br /&gt;
    P()&lt;br /&gt;
    {&lt;br /&gt;
        mutex.P();&lt;br /&gt;
        if(value &amp;lt; N)&lt;br /&gt;
        {&lt;br /&gt;
            if (value &amp;gt;= 0)&lt;br /&gt;
            {&lt;br /&gt;
                plus.P();&lt;br /&gt;
            }&lt;br /&gt;
            else&lt;br /&gt;
            {&lt;br /&gt;
                minus.V();&lt;br /&gt;
            }&lt;br /&gt;
            value--;&lt;br /&gt;
        }&lt;br /&gt;
        mutex.V();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    V()&lt;br /&gt;
    {&lt;br /&gt;
        mutex.P();&lt;br /&gt;
        if(value &amp;gt; -N)&lt;br /&gt;
        {&lt;br /&gt;
            if (value &amp;lt;= 0)&lt;br /&gt;
            {&lt;br /&gt;
                minus.P();&lt;br /&gt;
            } &lt;br /&gt;
            else&lt;br /&gt;
            {&lt;br /&gt;
                plus.V();&lt;br /&gt;
            }&lt;br /&gt;
            value++;&lt;br /&gt;
        }&lt;br /&gt;
        mutex.V();        &lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.2 ===&lt;br /&gt;
==== Soluzione &amp;quot;furba e facile&amp;quot; ====&lt;br /&gt;
* Visto dall'utente [[User:Acsor|Acsor]] ([[User talk:Acsor|talk]]) in data 18:53, 9 September 2020 (CEST). Ritengo sia: corretto (perché l'ho fatto pressappoco uguale). (Ritengo anche che possedere strumenti di analisi formale per verificare la correttezza di codice simile sarebbe di grande ausilio.)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
class bounded_semaphore {&lt;br /&gt;
    semaphore plus;&lt;br /&gt;
    semaphore minus;&lt;br /&gt;
    int value;   // serve per significato&lt;br /&gt;
    &lt;br /&gt;
    bounded_semaphore (int initval, unsigned maxval) {&lt;br /&gt;
        value = initval;&lt;br /&gt;
        plus = new semaphore(maxval + initval);&lt;br /&gt;
        minus = new semaphore(maxval - initval);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void P() {&lt;br /&gt;
        plus.P();&lt;br /&gt;
        value--;&lt;br /&gt;
        minus.V(); &lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void V() {&lt;br /&gt;
        minus.P();&lt;br /&gt;
        value++;&lt;br /&gt;
        plus.V();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Soluzione &amp;quot;schiacciasassi&amp;quot; ====&lt;br /&gt;
Controllato da [https://t.me/llibera LiberaL] in data 2023/05/12, perchè nel primo if della V() si fa value &amp;gt;= - maxval? non dovrebbe essere + maxval?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
class bounded_semaphore {&lt;br /&gt;
    semaphore mutex;&lt;br /&gt;
    queue&amp;lt;semaphore&amp;gt; okmin, okmax;&lt;br /&gt;
    int value;&lt;br /&gt;
    unsigned maxval;&lt;br /&gt;
&lt;br /&gt;
    bounded_semaphore (int initval, unsigned maxval) {&lt;br /&gt;
	value = initval;&lt;br /&gt;
        this.maxval = maxval;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void P() {&lt;br /&gt;
        mutex.P();&lt;br /&gt;
&lt;br /&gt;
        if (value &amp;lt;= -maxval)  {&lt;br /&gt;
            s=semaphore(0);&lt;br /&gt;
            okmin.enqueue(s);&lt;br /&gt;
            mutex.V();&lt;br /&gt;
            s.P();&lt;br /&gt;
        } else if (okmax.length() &amp;gt; 0) {&lt;br /&gt;
            s = okmax.dequeue()&lt;br /&gt;
            s.V();&lt;br /&gt;
            mutex.V();&lt;br /&gt;
        } else {&lt;br /&gt;
            value--;&lt;br /&gt;
            mutex.V();&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void V() {&lt;br /&gt;
        mutex.P();&lt;br /&gt;
&lt;br /&gt;
        if (value &amp;gt;= -maxval)  {  //qui...&lt;br /&gt;
            s=semaphore(0);&lt;br /&gt;
            okmax.enqueue(s);&lt;br /&gt;
            mutex.V();&lt;br /&gt;
            s.P();&lt;br /&gt;
        } else if (okmin.length() &amp;gt; 0) {&lt;br /&gt;
            s = okmin.dequeue()&lt;br /&gt;
            s.V();&lt;br /&gt;
            mutex.V();&lt;br /&gt;
        } else {&lt;br /&gt;
            value++;&lt;br /&gt;
            mutex.V();&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Esercizio g.1 ===&lt;br /&gt;
* Controllato dall'utente [[User:Acsor|Acsor]] ([[User talk:Acsor|talk]]), 23:17, 9 September 2020 (CEST). Ritengo sia: corretto&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
IC = 10,10,10 // Capitale iniziale&lt;br /&gt;
COH = 4,4,4   // Saldo in cassa&lt;br /&gt;
 &lt;br /&gt;
      MAX     ATT     RES    AVAIL&lt;br /&gt;
P1 | 6,6,6 | 1,1,1 | 5,5,5 | 4,4,4&lt;br /&gt;
P2 | 6,6,6 | 1,1,1 | 5,5,5 | 5,5,5&lt;br /&gt;
P3 | 9,9,9 | 4,4,4 | 5,5,5 | 6,6,6&lt;br /&gt;
 &amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Minimizzato&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
IC = 4,4,4&lt;br /&gt;
COH = 1,1,1&lt;br /&gt;
 &lt;br /&gt;
      MAX     ATT     RES  &lt;br /&gt;
P1 | 3,3,3 | 1,1,1 | 2,2,2&lt;br /&gt;
P2 | 3,3,3 | 1,1,1 | 2,2,2&lt;br /&gt;
P3 | 3,3,3 | 1,1,1 | 2,2,2&lt;br /&gt;
 &amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Esercizio g.2 (da controllare) ===&lt;br /&gt;
&lt;br /&gt;
* Visto e rimaneggiato in data 19:40, 10 September 2020 (CEST) dall'utente [[User:Acsor|Acsor]] ([[User talk:Acsor|talk]])&lt;br /&gt;
&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
&lt;br /&gt;
# Il calcolo del working set serve a determinare il numero di processi che possono essere mantenuti attivi sulla base del limite della memoria principale, più precisamente del suo numero di frame. Può essere svolto ad ogni page fault, ossia quando un processo tra quelli attivi richiede una pagina non presente in memoria, o prima di avviare un nuovo processo.&lt;br /&gt;
# La lunghezza massima di un file che può essere memorizzato su un file system di tipo FAT viene calcolata moltiplicando il massimo numero di cluster (dimensione dell'unità di allocazione) identificabili per la loro dimensione. Il massimo numero di cluster identificabili dipende da quanti bit sono allocati per numerarli, e per questa distinzione esistono varie versioni di FAT (FAT12, FAT16, FAT32).&lt;br /&gt;
## FAT32 memorizza la dimensione dei file in un intero unsigned da 32bit, e non può quindi gestire un file di dimensione superiore ai 2^32 bit = ~4GB.&lt;br /&gt;
## FAT16, allocando 16bit per identificare i cluster, può contarne al massimo 2^16 (65536). Prendendo quindi, ad esempio, un file system FAT16 con cluster da 32KB, possiamo avere file grandi al massimo 32KB*65536 = ~2GB.&lt;br /&gt;
## FAT12 di conseguenza può numerare al massimo 2^12 (4096) cluster, ma dato che il numero dei settori del disco viene memorizzato in un intero signed a 16bit, la massima dimensione del disco è 2^15 = 32MB. Ovviamente, non si può memorizzare un file di grandezza superiore alla dimensione dell'unità di memorizzazione stessa, e quindi anche i file in FAT12 possono avere dimensione massima di 32MB.&lt;br /&gt;
# Entrambi condividono l'intento di infettare host con codice malevolo, ma differiscono fondamentalmente nella modalità: i virus infettano programmi già esistenti mediante un ''virus dropper'', mentre i worm diffondono copie di se stessi, solitamente attraverso la rete.&lt;br /&gt;
# In vari casi sulla base della natura del sistema. Innanzitutto, in sistemi batch ciò avviene se non sono stati inseriti più processi per un certo lasso di tempo. In sistemi general-purpose (es. per PC o dispositivi mobili) tale condizione è verificabile se tutti i processi sono in attesa su una coda che non è quella dello scheduler (ad. es. di un semaforo o di una periferica di I/O); casi concreti sono pertanto il deadlock (di tutti i processi del sistema) o attesa generale di I/O. Infine sempre in sistemi general-purpose tale condizione può manifestarsi, stavolta in condizioni patologiche, se ogni processo è assegnato ad una propria CPU/core, lasciando pertanto la coda d'attesa vuota.&lt;br /&gt;
&lt;br /&gt;
= Esame 28/05/2018 =&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2018.05.28.tot.pdf 2018.05.28.tot.pdf]&lt;br /&gt;
=== Esercizio c.1 ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
Stack&amp;lt;int&amp;gt; entriesStack;&lt;br /&gt;
&lt;br /&gt;
int vid[MAX];&lt;br /&gt;
condition ok2esci[MAX]&lt;br /&gt;
int in = 0; &lt;br /&gt;
int out = -1;&lt;br /&gt;
&lt;br /&gt;
Procedure-entry: entra(int id) {&lt;br /&gt;
    if (in &amp;gt;= MAX)&lt;br /&gt;
        ok2entra.wait()&lt;br /&gt;
    vid[in++] = id;&lt;br /&gt;
    if (in &amp;lt; MAX)&lt;br /&gt;
        ok2entra.signal()&lt;br /&gt;
    else&lt;br /&gt;
        out = MAX - 1;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure-entry: esci(int id) {&lt;br /&gt;
    int i;&lt;br /&gt;
    for (i = 0; i &amp;lt; in; i++)&lt;br /&gt;
        if (vid[i] == id)&lt;br /&gt;
            break; //cerco l'indice di id nel vettore vid&lt;br /&gt;
&lt;br /&gt;
    if (i != out)&lt;br /&gt;
        ok2esci[i].wait();&lt;br /&gt;
&lt;br /&gt;
    if (out &amp;gt; 0) {&lt;br /&gt;
        out--;&lt;br /&gt;
        ok2esci[out].signal();&lt;br /&gt;
    } else {&lt;br /&gt;
        out--;&lt;br /&gt;
        in = 0; &lt;br /&gt;
        ok2entra.signal();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.1 (da controllare) ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
Monitor riempisvuota {&lt;br /&gt;
    Int MAXPROCESSI;&lt;br /&gt;
    Stack s;&lt;br /&gt;
    condition ok2enter;&lt;br /&gt;
    condition ok2exit;&lt;br /&gt;
 &lt;br /&gt;
    p.e void entra(getPid()){ &lt;br /&gt;
        if( s.size() &amp;gt;= MAXPROCESSI)&lt;br /&gt;
            ok2enter.wait();&lt;br /&gt;
        s.insert(getPid());&lt;br /&gt;
        if(s.size() &amp;gt; MAXPROCESSI)&lt;br /&gt;
            ok2exit.signal() &lt;br /&gt;
    }&lt;br /&gt;
 &lt;br /&gt;
    p.e void esci(getPid()){ &lt;br /&gt;
        if(s.size() &amp;gt; MAXPROCESSI &amp;amp;&amp;amp; s.top == getPid()) {&lt;br /&gt;
            s.pop();&lt;br /&gt;
            ok2entra.signal()&lt;br /&gt;
        }&lt;br /&gt;
        else&lt;br /&gt;
            ok2exit.wait();&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Esercizio c.2 (ERRATO) ===&lt;br /&gt;
&lt;br /&gt;
* Soluzione proposta è errata, non puoi riceve in modo greedy e printare subito il carattere [[User:Flecart|Flecart]] ([[User talk:Flecart|talk]]) 11:33, 18 January 2023 (CET)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
proc[x]: x='a',...,'z'&lt;br /&gt;
 while True:&lt;br /&gt;
  //c sarà il carattere stampato dal processo precedente&lt;br /&gt;
  (c, string) = arecv(*)&lt;br /&gt;
  if(string == wait){&lt;br /&gt;
    //mi metto in attesa di ricevere l'ACK da proc[x]&lt;br /&gt;
    m=arecv(x);&lt;br /&gt;
  }&lt;br /&gt;
  if (c == NONE){&lt;br /&gt;
    //significa che sei il primo a ricevere quella stringa&lt;br /&gt;
    print(x);&lt;br /&gt;
    if (len(string) &amp;gt; 1){&lt;br /&gt;
      //mando la wait a tutti, il primo che riceve qualcosa da stampare manda una wait a tutti&lt;br /&gt;
      asend(wait,*);&lt;br /&gt;
      int l = len(string);&lt;br /&gt;
      int i = 1;&lt;br /&gt;
      while(l != 0){&lt;br /&gt;
        asend(proc[string[i]], (x, string[i...]));&lt;br /&gt;
        //si mette in attesa di ricevere l'ACK dal processo dell'ultima lettera della parola&lt;br /&gt;
        m=areceive(proc[string[i]]);&lt;br /&gt;
        //rimando la wait al processo per ribloccarlo&lt;br /&gt;
        asend(wait, proc[string[i]])&lt;br /&gt;
        l--;&lt;br /&gt;
        i++;&lt;br /&gt;
      }&lt;br /&gt;
      //dopo aver finito la stampa della stringa sblocco tutti i processi&lt;br /&gt;
      asend(ACK, *);&lt;br /&gt;
    }&lt;br /&gt;
  }else{&lt;br /&gt;
    print(x);&lt;br /&gt;
    asend(ACK, x);&lt;br /&gt;
    //ricomincia il ciclo while, si rimette in attesa e il 'gestore gli rimanda la wait'&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.2  ===&lt;br /&gt;
[[User:Flecart|Flecart friend]] ([[User talk:Flecart|talk]]) cedo la proprità intellettuale di questa soluzione a flecart&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
process [x]: x='a'..'z'&lt;br /&gt;
  if(x=='a'){&lt;br /&gt;
    asend(&amp;lt;NULL,NULL&amp;gt;,'b');&lt;br /&gt;
    asend(&amp;lt;NULL,NULL&amp;gt;,'b');&lt;br /&gt;
  }&lt;br /&gt;
  While True:&lt;br /&gt;
    &amp;lt;c,string&amp;gt;=arecv(x-1+26%26);&lt;br /&gt;
    if(string==NULL):&lt;br /&gt;
      &amp;lt;c,string&amp;gt;=arecv(*);&lt;br /&gt;
      if(string!=NULL):&lt;br /&gt;
        &amp;lt;c,string&amp;gt;=arecv(x-1+26%26);&lt;br /&gt;
&lt;br /&gt;
    if(string!=NULL):&lt;br /&gt;
      if(string[0]==x):&lt;br /&gt;
        print(string[0]);&lt;br /&gt;
        if(string.len()&amp;gt;1):&lt;br /&gt;
          aasend(&amp;lt;NULL,string[1:]&amp;gt;,(x+1)%26);&lt;br /&gt;
        else:&lt;br /&gt;
          aasend(&amp;lt;NULL,NULL&amp;gt;,(x+1)%26);&lt;br /&gt;
          aasend(&amp;lt;NULL,NULL&amp;gt;,(x+1)%26);&lt;br /&gt;
      else:&lt;br /&gt;
          aasend(&amp;lt;NULL,string&amp;gt;,(x+1)%26);&lt;br /&gt;
    else:&lt;br /&gt;
      aasend(&amp;lt;NULL,NULL&amp;gt;,(x+1)%26);&lt;br /&gt;
      aasend(&amp;lt;NULL,NULL&amp;gt;,(x+1)%26);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Proposta c2 ===&lt;br /&gt;
* Proposto [[User:Flecart|Flecart]] ([[User talk:Flecart|talk]]) 11:31, 18 January 2023 (CET)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
proc[a]:&lt;br /&gt;
	bool occupied = false;&lt;br /&gt;
	queue&amp;lt;string&amp;gt; s;&lt;br /&gt;
	&lt;br /&gt;
	while True {&lt;br /&gt;
		(c, string) = arecv(*);&lt;br /&gt;
		&lt;br /&gt;
		if (c == NONE) {&lt;br /&gt;
			if (occupied) {&lt;br /&gt;
				s.enqueue(string);&lt;br /&gt;
			} else {&lt;br /&gt;
				if (string.len() &amp;lt; 1)&lt;br /&gt;
					continue;&lt;br /&gt;
			&lt;br /&gt;
				occupied = true;&lt;br /&gt;
				asend(string[0], (MIDDLE, string));&lt;br /&gt;
			}&lt;br /&gt;
		} else if (c == END) {&lt;br /&gt;
			if (s.size() &amp;gt; 0) {&lt;br /&gt;
				string ss = s.dequeue();&lt;br /&gt;
				asend(string[0], (MIDLLE, string));&lt;br /&gt;
			} else {&lt;br /&gt;
				occupied = false;&lt;br /&gt;
			}&lt;br /&gt;
		} else {&lt;br /&gt;
			print(x);&lt;br /&gt;
			if (len(string) &amp;gt; 1) &lt;br /&gt;
				asend(proc[string[0]], (MIDDLE, string[1:]));&lt;br /&gt;
			else:&lt;br /&gt;
				asend(proc[a], (END, &amp;quot;&amp;quot;));&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
		&lt;br /&gt;
proc[x]: x = 'b', ... 'z';&lt;br /&gt;
	while True {&lt;br /&gt;
		(c, string) = arecv(*);&lt;br /&gt;
		if (c == NONE) {&lt;br /&gt;
			asend(proc['a'], (NONE, string));&lt;br /&gt;
		} else {  // potrà essere solo MIDDLE&lt;br /&gt;
			print(x);&lt;br /&gt;
			if (len(string) &amp;gt; 1) &lt;br /&gt;
				asend(proc[string[0]], (MIDDLE, string[1:]));&lt;br /&gt;
			else:&lt;br /&gt;
				asend(proc[a], (END, &amp;quot;&amp;quot;));&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Esame 12/02/2018 =&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2018.02.12.tot.pdf 2018.02.12.tot.pdf]&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.1 (da controllare) ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
monitor bridge:&lt;br /&gt;
&lt;br /&gt;
    int ncar&lt;br /&gt;
    bool boat_on_0&lt;br /&gt;
    bool boat_on_1       // per semplicità, quando nel codice si trova boat_on_(direction) oppure isBoat(direction)(),&lt;br /&gt;
                         // si valuta il valore booleano di direction e lo si applica sotto forma di stringa al simbolo&lt;br /&gt;
                         // ad esso adiacente&lt;br /&gt;
    bool is_raised&lt;br /&gt;
    queue waiting_mean   // i valori possibili sono: boat0, boat1 oppure car&lt;br /&gt;
    condition ok2go&lt;br /&gt;
  &lt;br /&gt;
    entry car_enter(direction): &lt;br /&gt;
        if is_raised || ncar == MAXCAR:&lt;br /&gt;
            waiting_mean.enqueue(car)&lt;br /&gt;
            ok2go.wait()&lt;br /&gt;
        is_raised = false&lt;br /&gt;
        ++ncar&lt;br /&gt;
  &lt;br /&gt;
    entry car_exit(direction):&lt;br /&gt;
        --ncar&lt;br /&gt;
        if (waiting_mean.top().isBoat() &amp;amp;&amp;amp; ncar == 0) || waiting_mean.top().isCar():    // isBoat ritorna true se l'oggetto su cui&lt;br /&gt;
            waiting_mean.dequeue()                                                      // è invocata è boat0 oppure boat1&lt;br /&gt;
            ok2go.signal()&lt;br /&gt;
  &lt;br /&gt;
    entry boat_enter(direction):&lt;br /&gt;
        if !is_raised || boat_on_(direction):&lt;br /&gt;
            waiting_mean.enqueue(boat)&lt;br /&gt;
            ok2go.wait()&lt;br /&gt;
        if waiting_mean.top().isBoat(!direction)():&lt;br /&gt;
            waiting_mean.dequeue()&lt;br /&gt;
            ok2go.signal()&lt;br /&gt;
        is_raised = true&lt;br /&gt;
        boat_on_(direction) = true&lt;br /&gt;
  &lt;br /&gt;
    entry boat_exit(direction):&lt;br /&gt;
        boat_on_(direction) = false&lt;br /&gt;
        if !boat_on_(!direction):&lt;br /&gt;
            waiting_mean.dequeue()&lt;br /&gt;
            ok2go.signal()&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.1 ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
monitor bridge  {&lt;br /&gt;
  int carsOnBridge = 0;&lt;br /&gt;
  int shipping[2] = {0, 0}; //navi da entrambe le direzioni&lt;br /&gt;
  int status = NONE; //UP DOWN NONE&lt;br /&gt;
  int last2pass = 0;     //ultimo che ha passato il ponte&lt;br /&gt;
  int waitingC = 0;      //coda delle macchine che aspettano&lt;br /&gt;
  int waitingS[2] = {0,0};  //navi che stanno aspettando&lt;br /&gt;
   &lt;br /&gt;
  condition ok2ship[2]&lt;br /&gt;
  condition ok2drive&lt;br /&gt;
 &lt;br /&gt;
entry car_enter(int direction){&lt;br /&gt;
    if(carsOnBridge &amp;gt;= MAX || status == UP || waitingS[0] + waitingS[1] &amp;gt; 0 ){&lt;br /&gt;
        waitingC++;ok2drive.wait;waitingC--;}&lt;br /&gt;
    status = DOWN;&lt;br /&gt;
    carsOnBridge++&lt;br /&gt;
    if (carsOnBridge &amp;lt; MAX)&lt;br /&gt;
       ok2drive.signal();     //vanno tutte le MAX car che stanno aspettando&lt;br /&gt;
} &lt;br /&gt;
entry car_exit(int direction){&lt;br /&gt;
    carsOnBridge--&lt;br /&gt;
    if (waitingS[0] + waitingS[1] == 0)&lt;br /&gt;
    ok2drive.signal();&lt;br /&gt;
    if(carsOnBridge == 0){&lt;br /&gt;
        ok2ship[0].signal(); ok2ship[1].signal();&lt;br /&gt;
    }&lt;br /&gt;
    if(carsOnBridge + waitingS[0] + waitingS[1] == 0) &lt;br /&gt;
    status = NONE&lt;br /&gt;
}&lt;br /&gt;
 &lt;br /&gt;
entry ship_enter(int direction){&lt;br /&gt;
    if (bridge = DOWN || shipping[direction] != 0 || waitingC &amp;gt; 0)&lt;br /&gt;
    {&lt;br /&gt;
        waitingS[i]++; ok2ship[i].wait(); waitingS[i]--; &lt;br /&gt;
    }&lt;br /&gt;
    isBridgeUp = false;&lt;br /&gt;
    shipping[i] = 1;&lt;br /&gt;
 &lt;br /&gt;
entry ship_exit(int direction){&lt;br /&gt;
      shipping[i] = 0;&lt;br /&gt;
      if (waitingC == 0)&lt;br /&gt;
          ok2ship[i].signal()&lt;br /&gt;
      else if(shipping[1-i] == 0)&lt;br /&gt;
          ok2drive.signal();&lt;br /&gt;
      if(carsOnBridge + waitingS[0] + waitingS[1] == 0) &lt;br /&gt;
      status = NONE&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.1 (da controllare) ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
monitor bridge {&lt;br /&gt;
&lt;br /&gt;
  UP=0;&lt;br /&gt;
  DOWN=1;&lt;br /&gt;
  bridgeis = DOWN;&lt;br /&gt;
&lt;br /&gt;
  bool carAreExiting = false;&lt;br /&gt;
&lt;br /&gt;
  condition ok2drive;&lt;br /&gt;
  condition ok2barca[2];&lt;br /&gt;
&lt;br /&gt;
  waitingCar = 0;&lt;br /&gt;
  carOnBridge = 0;&lt;br /&gt;
&lt;br /&gt;
  boatWaiting[2] = {0,0};&lt;br /&gt;
  boatIsPassing[2] = {false,false}&lt;br /&gt;
&lt;br /&gt;
  entry car_enter(direction) {&lt;br /&gt;
&lt;br /&gt;
    if (bridgeis == DOWN)&lt;br /&gt;
      if(carOnBridge == MAXCAR)&lt;br /&gt;
        waitingCar++;&lt;br /&gt;
        ok2drive.wait();&lt;br /&gt;
        waitingCar--;&lt;br /&gt;
      else if (carAreExiting)&lt;br /&gt;
        waitingCar++;&lt;br /&gt;
        ok2drive.wait();&lt;br /&gt;
        waitingCar--;&lt;br /&gt;
    else &lt;br /&gt;
      if (boatIsPassing[0] || boatIsPassing[1])&lt;br /&gt;
        waitingCar++;&lt;br /&gt;
        ok2drive.wait();&lt;br /&gt;
        waitingCar--;&lt;br /&gt;
        bridgeis = DOWN;&lt;br /&gt;
&lt;br /&gt;
    carOnBridge++;&lt;br /&gt;
    carAreExiting = false;&lt;br /&gt;
    if(carOnBridge &amp;lt; MAXCAR &amp;amp;&amp;amp; !carAreExiting) &lt;br /&gt;
      ok2drive.signal();&lt;br /&gt;
      &lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  entry car_exit(direction) {&lt;br /&gt;
&lt;br /&gt;
    carOnBridge--;&lt;br /&gt;
    carAreExiting = true;&lt;br /&gt;
&lt;br /&gt;
    if(carOnBridge == 0)&lt;br /&gt;
      carAreExiting = false;&lt;br /&gt;
      if(boatWaiting[0] &amp;gt; 0)&lt;br /&gt;
        bridgeis = UP;&lt;br /&gt;
        ok2barca[0].signal();&lt;br /&gt;
      else if (boatWaiting[1] &amp;gt; 0)&lt;br /&gt;
        bridgeis = UP;&lt;br /&gt;
        ok2barca[1].signal();&lt;br /&gt;
      else &lt;br /&gt;
        ok2drive.signal();&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  entry boat_enter(direction) {&lt;br /&gt;
&lt;br /&gt;
    if (bridgeis == UP)&lt;br /&gt;
    | if (boatIsPassing[direction] == true)&lt;br /&gt;
    | |  boatWaiting[direction]++;&lt;br /&gt;
    | |  ok2barca.wait();&lt;br /&gt;
    | |  boatWaiting[direction]--;&lt;br /&gt;
    else &lt;br /&gt;
    | if (carOnBridge &amp;gt; 0)&lt;br /&gt;
    | | boatWaiting[direction]++;&lt;br /&gt;
    | | ok2barca.wait();&lt;br /&gt;
    | | boatWaiting[direction]--;&lt;br /&gt;
    | | bridgeis = UP;&lt;br /&gt;
&lt;br /&gt;
    boatIsPassing[direction] = true;&lt;br /&gt;
&lt;br /&gt;
    if(boatIsPassing[1-direction] == false &amp;amp;&amp;amp; boatWaiting[1-direction] &amp;gt; 0)&lt;br /&gt;
      ok2barca[1-direction].signal();&lt;br /&gt;
    &lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  entry boat_exit(direction) {&lt;br /&gt;
&lt;br /&gt;
    boatIsPassing[direction] = false;&lt;br /&gt;
&lt;br /&gt;
    if (boatIsPassing[1-direction] == false)&lt;br /&gt;
      if (waitingCar &amp;gt; 0)&lt;br /&gt;
        bridgeis = DOWN;&lt;br /&gt;
        ok2drive.signal();&lt;br /&gt;
    else&lt;br /&gt;
        if (waitingCar == 0)&lt;br /&gt;
          ok2barca[direction].signal();&lt;br /&gt;
          &lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.1 (sbagliato) ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
monitor bridge&lt;br /&gt;
  condition ok2passCar;&lt;br /&gt;
  condition ok2passBoat;&lt;br /&gt;
  condition ok2up;&lt;br /&gt;
  condition ok2down;&lt;br /&gt;
  int carOnBridge[2] = 0; //2 sensi di marcia&lt;br /&gt;
  int boatUnderBridge[2] = 0;&lt;br /&gt;
  boolean bridge_down = false; //vuol dire che il ponte parte alzato, true ponte abbassato&lt;br /&gt;
  &lt;br /&gt;
  procedure entry car_enter(direction){&lt;br /&gt;
      if(bridge_down &amp;amp;&amp;amp; carOnBridge[direction] &amp;lt; MAXCAR){&lt;br /&gt;
        carOnBridge[direction]++;&lt;br /&gt;
        ok2passCar.signal();&lt;br /&gt;
      }else if (bridge_down &amp;amp;&amp;amp; boatUnderBridge[0] == 0 &amp;amp;&amp;amp; boatUnderBridge[1] == 0){&lt;br /&gt;
        //se non ci sono navi in transito e arriva una macchina abbassa ponte&lt;br /&gt;
        ok2down.signal();&lt;br /&gt;
        ok2passCar.signal();&lt;br /&gt;
        ok2passBoat.wait();&lt;br /&gt;
      }else{&lt;br /&gt;
        ok2passCar.wait();&lt;br /&gt;
      }&lt;br /&gt;
  }     &lt;br /&gt;
        &lt;br /&gt;
  procedure entry car_exit(direction){&lt;br /&gt;
      carOnBridge[direction]--;&lt;br /&gt;
      if(carOnBridge[0] == 0 &amp;amp;&amp;amp; carOnBridge[1] == 0){&lt;br /&gt;
        bridge_down = false;&lt;br /&gt;
        ok2up.signal();&lt;br /&gt;
      }else{&lt;br /&gt;
        ok2up.wait();&lt;br /&gt;
      }&lt;br /&gt;
  }&lt;br /&gt;
      &lt;br /&gt;
  procedure entry boat_enter(direction){&lt;br /&gt;
      if(!bridge_down &amp;amp;&amp;amp; boatUnderBridge[direction] &amp;lt; 1){&lt;br /&gt;
        boatUnderBridge[direction]++;&lt;br /&gt;
        ok2passBoat.signal();&lt;br /&gt;
      }else if(!bridge_down &amp;amp;&amp;amp; carOnBridge[0] == 0 &amp;amp;&amp;amp; carOnBridge[1] == 0){&lt;br /&gt;
        ok2up.signal();&lt;br /&gt;
        ok2passBoat.signal();&lt;br /&gt;
        ok2passCar.wait();&lt;br /&gt;
      }else {&lt;br /&gt;
        ok2passBoat.wait();&lt;br /&gt;
      }&lt;br /&gt;
  }&lt;br /&gt;
      &lt;br /&gt;
  procedure entry boat_exit(direction){  &lt;br /&gt;
      boatUnderBridge[direction]--;&lt;br /&gt;
      if(boatUnderBridge[0] == 0 &amp;amp;&amp;amp; boatUnderBridge[1] == 0){&lt;br /&gt;
        bridge_down = true;&lt;br /&gt;
        ok2down.signal();&lt;br /&gt;
      }else{&lt;br /&gt;
        ok2down.wait();&lt;br /&gt;
      }&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.1 2o (sbagliato) ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define car 1&lt;br /&gt;
#define ship 2 &lt;br /&gt;
#define fromDX 1&lt;br /&gt;
#define fromSX 0&lt;br /&gt;
&lt;br /&gt;
monitor bridge  {&lt;br /&gt;
  int carsOnBridge = 0;&lt;br /&gt;
  int shippingDX = 0; //nave che sta passando dal lato destro&lt;br /&gt;
  int shippingSX = 0; //nave che sta passando dal lato sinistro&lt;br /&gt;
  bool isBridgeUp = false;&lt;br /&gt;
  int last2pass = 0;     //ultimo che ha passato il ponte&lt;br /&gt;
  int waitingS = 0;  //navi che stanno aspettando&lt;br /&gt;
  int waitingC = 0 ; //auto che stanno aspettando&lt;br /&gt;
  &lt;br /&gt;
  condition ok2ship&lt;br /&gt;
  condition ok2drive&lt;br /&gt;
&lt;br /&gt;
entry car_enter(int direction){&lt;br /&gt;
    //un auto si ferma se il numero di auto sul ponte è massimo&lt;br /&gt;
    //e se l'ultima a passare è stata un auto mentre ci sono navi in attesa&lt;br /&gt;
    if(carsOnBridge == MAX || isBridgeUp || (last2pass==car &amp;amp;&amp;amp; waitingS &amp;gt; 0) ){&lt;br /&gt;
        waitingC++;&lt;br /&gt;
        ok2drive.wait;&lt;br /&gt;
    }&lt;br /&gt;
    carsOnBridge++;&lt;br /&gt;
    waitingC--;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
entry car_exit(int direction){&lt;br /&gt;
    carsOnBridge--;&lt;br /&gt;
    last2pass = car;&lt;br /&gt;
    if(carsOnBridge == 0 &amp;amp;&amp;amp; waitingS&amp;gt;0){&lt;br /&gt;
        isBrigdeUp = true;&lt;br /&gt;
        ok2ship.signal;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
entry ship_enter(int direction){&lt;br /&gt;
    //se la barca viene da destra&lt;br /&gt;
    if(direction == fromDX){&lt;br /&gt;
        //si ferma anche quando c'è una nave che sta già attraversando nella sua stessa direzione&lt;br /&gt;
        if (isBridgeup == false || shippingDX || (last2pass==ship &amp;amp;&amp;amp; waitingC &amp;gt; 0) ){&lt;br /&gt;
            waitingS++;&lt;br /&gt;
            ok2ship.wait;&lt;br /&gt;
        }&lt;br /&gt;
        if (waitingS &amp;gt; 0)&lt;br /&gt;
            waitingS--;&lt;br /&gt;
        shippingDX = 1;&lt;br /&gt;
        }&lt;br /&gt;
    //se la barca viene da sinistra&lt;br /&gt;
    else if(direction == fromSX){&lt;br /&gt;
        if (isBridgeup == false || shippingSX || ( (last2pass==ship &amp;amp;&amp;amp; waitingC &amp;gt; 0))){&lt;br /&gt;
        waitingS++;&lt;br /&gt;
        ok2ship.wait;&lt;br /&gt;
        }&lt;br /&gt;
        if (waitingS &amp;gt; 0)&lt;br /&gt;
            waitingS--;        &lt;br /&gt;
        shippingSX = 1;&lt;br /&gt;
    &lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
entry ship_exit(int direction){&lt;br /&gt;
        if(direction == fromDX)&lt;br /&gt;
            shippingDX = 0;&lt;br /&gt;
        else if (direction == fromSX)&lt;br /&gt;
            shippingSX = 0;&lt;br /&gt;
        last2pass = ship;&lt;br /&gt;
        if(shippingDX == 0 &amp;amp;&amp;amp; shippingSX == 0 &amp;amp;&amp;amp; waitingC)&lt;br /&gt;
            isBrigdeUp == false;&lt;br /&gt;
            ok2drive.signal;&lt;br /&gt;
        else if(shippingDX == 0 &amp;amp;&amp;amp; shippingSX == 0 &amp;amp;&amp;amp; waitingS &amp;gt; 0)&lt;br /&gt;
            ok2ship.signal;    &lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.2 (sbagliato) ===&lt;br /&gt;
&lt;br /&gt;
# (Ri)Controllato dall'utente [[User:Acsor|Acsor]] ([[User talk:Acsor|talk]]) in data 26/08/2020&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
list printed_msg;  # questa è una variabile condivisa che ai fini dell'esercizio non si può utilizzare (message passing)&lt;br /&gt;
&lt;br /&gt;
process server[i]:&lt;br /&gt;
  while true:&lt;br /&gt;
    &amp;lt;msg, pid&amp;gt; = arecv(*)&lt;br /&gt;
&lt;br /&gt;
    if printed_msg.length == 0 or &amp;lt;msg, pid&amp;gt; is not in printed_msg:&lt;br /&gt;
      printed_msg.append(&amp;lt;msg,id&amp;gt;)&lt;br /&gt;
      print(msg)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.2 (da controllare) ===&lt;br /&gt;
Nello svolgimento seguente, receiver incapsula l'ambiente privato del processo; _peers rappresenta il vettore di processi &amp;quot;fratelli&amp;quot; ai quali può essere chiesto di stampare un messaggio, mentre _printed contiene l'hash di tutti i messaggi stampati dal processo locale. Si suppone che istanze della classe receiver possano essere passate come parametro ad areceive() ed asend() (non implementate).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
class receiver:&lt;br /&gt;
    def __init__(self, peers):&lt;br /&gt;
        &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
        :param peers: list of processes this process communicates with.&lt;br /&gt;
        &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
        self._peers = tuple(peers)&lt;br /&gt;
        self._printed = list()&lt;br /&gt;
    &lt;br /&gt;
    def run(self):&lt;br /&gt;
        while True:&lt;br /&gt;
            process, message = areceive(ANY)&lt;br /&gt;
&lt;br /&gt;
            if process in self._peers:&lt;br /&gt;
                self._reply_query(process, message)&lt;br /&gt;
            else:&lt;br /&gt;
                self._print(process, message)&lt;br /&gt;
&lt;br /&gt;
    def _print(self, sender, message):&lt;br /&gt;
        h = hash(message.text)&lt;br /&gt;
&lt;br /&gt;
        if h not in self._printed and not self._printed_from_peers(message):&lt;br /&gt;
            self._printed.append(h)&lt;br /&gt;
            print(message.text)&lt;br /&gt;
&lt;br /&gt;
    def _reply_query(self, sender, h):&lt;br /&gt;
        &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
        Invoked when the current process receive a &amp;quot;query&amp;quot; from a peer process.&lt;br /&gt;
        `h` contains the hash of a message which may or may have not been&lt;br /&gt;
        sent from this process; if it was sent, the reply is `Yes`, otherwise `No`.&lt;br /&gt;
        &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
        reply = &amp;quot;Yes&amp;quot; if int(h) in self._printed else &amp;quot;No&amp;quot;&lt;br /&gt;
        asend(sender, reply)&lt;br /&gt;
&lt;br /&gt;
    def _printed_from_peers(self, message):&lt;br /&gt;
        &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
        :return: `True` if this message has already been printed from any of the&lt;br /&gt;
        peer processes, `False` otherwise.&lt;br /&gt;
        &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
        h = hash(message)&lt;br /&gt;
&lt;br /&gt;
        for p in self._peers:&lt;br /&gt;
            asend(p, str(h))&lt;br /&gt;
&lt;br /&gt;
        for p in self._peers:&lt;br /&gt;
            _, reply = areceive(p)&lt;br /&gt;
&lt;br /&gt;
            if reply.text == &amp;quot;Yes&amp;quot;:&lt;br /&gt;
                return True&lt;br /&gt;
            else if reply.text != &amp;quot;No&amp;quot;:&lt;br /&gt;
                # If the response is neither &amp;quot;Yes&amp;quot; nor &amp;quot;No&amp;quot;, then we have got a query&lt;br /&gt;
                self._reply_query(p, reply)&lt;br /&gt;
&lt;br /&gt;
        return False&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Esercizio g.1 (da controllare) ===&lt;br /&gt;
Sulla base dei valori in entrata, è possibile costruire le matrici Allocation (q.tà di risorse allocate per processo e per tipo), Need (q.tà di risorse che ogni processo potrebbe ancora chiedere) e il vettore Available (num. di risorse correntemente disponibili).&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;float: left&amp;quot;&lt;br /&gt;
! colspan=3 | Allocation&lt;br /&gt;
|-&lt;br /&gt;
   !   !! A !! B&lt;br /&gt;
|-&lt;br /&gt;
   | p1 || 4 || 5&lt;br /&gt;
|-&lt;br /&gt;
   | p2 || 3 || 3&lt;br /&gt;
|-&lt;br /&gt;
   | p3 || 2 || 4&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;float: left; margin-left: 1em&amp;quot;&lt;br /&gt;
! colspan=3 | Need&lt;br /&gt;
|-&lt;br /&gt;
   !    !! A !! B&lt;br /&gt;
|-&lt;br /&gt;
   | p1 || 6 || 8&lt;br /&gt;
|-&lt;br /&gt;
   | p2 || 6 || 3&lt;br /&gt;
|-&lt;br /&gt;
   | p3 || 6 || 8&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;float: left; margin-left: 1em&amp;quot;&lt;br /&gt;
! colspan=2 | Available&lt;br /&gt;
|-&lt;br /&gt;
   ! A !! B&lt;br /&gt;
|-&lt;br /&gt;
   | x || y&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nel caso delle risorse di tipo A, deve aversi x &amp;gt;= 6 in quanto un processo dovrà essere selezionato come primo nella permutazione dell'algoritmo del banchiere multivaluta, e tutti quelli correnti hanno lo stesso valore Need(i)(1); per ciò che riguarda le risorse di tipo B, possiamo ragionare per esaustione&lt;br /&gt;
&lt;br /&gt;
* Se il primo processo della permutazione è p1, allora y &amp;gt;= 8 (con questo valore posso soddisfare la richiesta di p1 e in seguito tutte le altre)&lt;br /&gt;
* Se il primo processo della permutazione è p2, allora y &amp;gt;= 5: con questo valore è possibile soddisfare la richiesta di p2; una volta che esso avrà finito, restituirà 3 unità della risorsa B, che permetteranno di soddisfare sia le richieste di A sia quelle di C&lt;br /&gt;
* Se il primo processo della permutazione è p3, allora y &amp;gt;= 8 (ragionamento analogo come per p1)&lt;br /&gt;
&lt;br /&gt;
Volendo scegliere il minimo, y &amp;gt;= 5, ed in conclusione (x, y) &amp;gt;= (6, 5).&lt;br /&gt;
&lt;br /&gt;
''Svolgimento basato in parte sull'approccio di Operating System Concepts di Silberschatz. et al, 9th edition, cap. 7.''&lt;br /&gt;
&lt;br /&gt;
=== Esercizio g.2 (da controllare) ===&lt;br /&gt;
# Può accadere che il sistema torni in uno stato di safety o che invece porti a deadlock. Diversamente uno stato di safety non può portare direttamente ad uno stato di deadlock, ma solo ad uno di non-safety.&lt;br /&gt;
# Selezionare uno o più tra i processi attivi e sospenderli, salvando il loro stato su memoria secondaria operando delle operazioni di swap-out, finché l'insieme dei frame nella memoria centrale non è in grado di soddisfare tutti i processi rimasti attivi.&lt;br /&gt;
# La scelta è determinata perlopiù dal fattore costo. Con un sistema RAID 1 è possibile ripristinare un disco guasto molto brevemente, in quanto le operazioni coinvolte prevedono una semplice ricopiatura dal disco di backup; con un sistema RAID 5 il ripristino del disco guasto deve coinvolgere tutti i dischi dell'intero array, e ciò può richiedere anche ore per dischi di grandi dimensioni. D'altra parte RAID 1 è più costoso (con n dischi, posso memorizzare tanta informazione quanto potrei con n / 2 dischi) rispetto a RAID 5 dove, tra gli n dischi, complessivamente soltanto uno è destinato alle informazioni di ridondanza.&lt;br /&gt;
# ''Completare.''&lt;/div&gt;</summary>
		<author><name>LiberaL</name></author>
	</entry>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=Prove_scritte_2018&amp;diff=2976</id>
		<title>Prove scritte 2018</title>
		<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php?title=Prove_scritte_2018&amp;diff=2976"/>
		<updated>2023-05-12T14:48:18Z</updated>

		<summary type="html">&lt;p&gt;LiberaL: /* Soluzione &amp;quot;schiacciasassi&amp;quot; */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Esame 19/09/2018 =&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2018.09.19.tot.pdf Testo dell'esame].&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.2 (da controllare) ===&lt;br /&gt;
&lt;br /&gt;
* Controllato dall'utente ? in data ?&lt;br /&gt;
* ...&lt;br /&gt;
&lt;br /&gt;
Nello pseudocodice seguente, il termine this fa riferimento al processo corrente, mentre ANY ad uno qualunque.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
stack&amp;lt;message&amp;gt; messages;&lt;br /&gt;
&lt;br /&gt;
void lifo_send(string m, process dest) {&lt;br /&gt;
	do {&lt;br /&gt;
		asend(m, dest);&lt;br /&gt;
	} while (areceive(dest).text != &amp;quot;ACK&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
message lifo_receive(process source) {&lt;br /&gt;
	if (source != ANY) {&lt;br /&gt;
		message m = areceive(source);&lt;br /&gt;
&lt;br /&gt;
		asend(&amp;quot;ACK&amp;quot;, source);&lt;br /&gt;
&lt;br /&gt;
		return m;&lt;br /&gt;
	} else {&lt;br /&gt;
		message m;&lt;br /&gt;
&lt;br /&gt;
		asend(&amp;quot;END&amp;quot;, this);&lt;br /&gt;
		m = areceive(ANY);&lt;br /&gt;
&lt;br /&gt;
		while (m.text != &amp;quot;END&amp;quot; || m.sender != this) {&lt;br /&gt;
			messages.push(m);&lt;br /&gt;
			asend(&amp;quot;ACK&amp;quot;, m.sender);&lt;br /&gt;
&lt;br /&gt;
			m = areceive(ANY);&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
                /* Bisogna tenere conto dei casi in cui lifo_receive() viene invocata quando nessun&lt;br /&gt;
                 * messaggio è stato ancora spedito da altri processi. In tal caso si attende il&lt;br /&gt;
                 * il primo e lo si restituisce.&lt;br /&gt;
                 */&lt;br /&gt;
		if (messages.empty()) {&lt;br /&gt;
			m = areceive(ANY);&lt;br /&gt;
			asend(&amp;quot;ACK&amp;quot;, m.sender);&lt;br /&gt;
&lt;br /&gt;
			return m;&lt;br /&gt;
		} else {&lt;br /&gt;
			return messages.pop();&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Esame 17/07/2018 =&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2018.07.17.tot.pdf 2018.07.17.tot.pdf]&lt;br /&gt;
== Esercizio c.1 ==&lt;br /&gt;
A Bruxelles c'è un locale chiamato Delirium Café. Alla vigilia del FOSDEM tutti gli anni gli sviluppatori europei di&lt;br /&gt;
software libero si ritrovano a bere birra (il locale è nel guinnes dei primati con più di duemila tipi di birra). Il prossimo appuntamento è&lt;br /&gt;
fissato per il 1 febbraio 2019 ore 20. Numerosi sono i tipi di birra alla spina. I baristi (tanti) prendono gli ordini (es. mezza pinta, 1 o 2&lt;br /&gt;
pinte) e riempiono i bicchieri. Quando un fusto e' vuoto avvertono i magazzinieri che prendono un nuovo fusto che contiene più di&lt;br /&gt;
cento pinte e lo sostituiscono, a questo punto il barista può completare il riempimento del bicchiere.&lt;br /&gt;
La vita di un barista del Delirium è:&lt;br /&gt;
 while True:&lt;br /&gt;
   (type, quantity) = get_order()&lt;br /&gt;
   delirium.pour(type, quantity)&lt;br /&gt;
La vita di un Magazziniere è:&lt;br /&gt;
 while True:&lt;br /&gt;
   type = delirium.isempty()&lt;br /&gt;
   capacity = change_keg(type)&lt;br /&gt;
   delirium.loaded(type, capacity)&lt;br /&gt;
&lt;br /&gt;
Attenzione: se il fusto (keg) è quasi vuoto il barista dovrà riempire parzialmente il bicchiere, occorrerà attivare il magazziniere che&lt;br /&gt;
cambierà il fusto e poi il barista riempirà il bicchiere fino alla quantità richiesta dal cliente. Mentre un barista sta attendendo il&lt;br /&gt;
cambiamento di un fusto altri baristi potrebbero ricevere ordini per lo stesso tipo di birra: gestire opportunamente questo caso.&lt;br /&gt;
Scrivere il monitor Delirium.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Proposta di soluzione 1 === &lt;br /&gt;
* ERRORE: Secondo me c'è un leggero errore nella parte di load, nel caso in cui la nuova pinta non riesca a soddisfare completamente la richiesta ossia quando vale availableBeer[t] &amp;lt;= requests[t].head(), allora non lo risveglio nemmeno, invece dovrei risvegliare il pour, fargli versare quanto può, e richiedere una altra pinta, perché questo era un requisito del problema. [[User:Flecart|Flecart]] ([[User talk:Flecart|talk]]) 12:00, 15 January 2023 (CET)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
/* Monitor Delirum: */&lt;br /&gt;
&lt;br /&gt;
// Condition: Ok2Load;&lt;br /&gt;
// Condition: Ok2Pour[]; // Un elemento per Type&lt;br /&gt;
int availableBeer[]; // Un elemento per Type &lt;br /&gt;
Queue requests[]; // Un elemento per Type&lt;br /&gt;
Queue pendingRequests;&lt;br /&gt;
&lt;br /&gt;
Procedure entry: void Pour(Type t, Quantity c)&lt;br /&gt;
{&lt;br /&gt;
    if (c &amp;gt; availableBeer[t]) // Richiesta maggiore della birra disponibile&lt;br /&gt;
    {&lt;br /&gt;
        c -= availableBeer[t];&lt;br /&gt;
        availableBeer[t] = 0;              &lt;br /&gt;
        requests[t].Enqueue(c);&lt;br /&gt;
        if (requests[t].Length == 1) // Risveglio un magazziniere solo se è la prima richiesta di questo tipo di birra&lt;br /&gt;
        {&lt;br /&gt;
            pendingRequests.Enqueue(t);&lt;br /&gt;
            Ok2Load().Signal();&lt;br /&gt;
        }&lt;br /&gt;
        Ok2Pour[t].Wait();&lt;br /&gt;
        requests[t].Dequeue(); // Quando ho ottenuto la birra che voglio, elimino la mia richiesta&lt;br /&gt;
    }&lt;br /&gt;
    availableBeer[t] -= c;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: Type isEmpty()&lt;br /&gt;
{&lt;br /&gt;
    if (pendingRequests.Length == 0)&lt;br /&gt;
    {&lt;br /&gt;
        Ok2Load.Wait();&lt;br /&gt;
    }&lt;br /&gt;
    return pendingRequests.Dequeue();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: Loaded(Type t, Capacity c)&lt;br /&gt;
{&lt;br /&gt;
    availableBeer[t] += c;&lt;br /&gt;
    while (requests[t].Length &amp;gt; 0 &amp;amp;&amp;amp; availableBeer[t] &amp;gt; requests[t].head())&lt;br /&gt;
    {&lt;br /&gt;
        Ok2Pour[t].Signal();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (requests[t].Length &amp;gt; 0) // serve per evitare che a causa di un magazziniere lento si accodino cosi tante richieste che mentre si sta caricando si svuota subito il fusto&lt;br /&gt;
    {&lt;br /&gt;
        pendingRequests.Enqueue(t);&lt;br /&gt;
        Ok2Load.Signal();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Proposta di soluzione 2 ===&lt;br /&gt;
* Proposto da [[User:Flecart|Flecart]] ([[User talk:Flecart|talk]]) 13:41, 15 January 2023 (CET)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
extern int MAX_TYPE;&lt;br /&gt;
class Delirium {&lt;br /&gt;
    int keg[MAX_TYPE];      // qnty fusto attuale&lt;br /&gt;
    int orders[MAX_TYPE];   // qnty richiesta&lt;br /&gt;
    bool worked[MAX_TYPE];  // 1 se magazziniere sta lavorando su questo.&lt;br /&gt;
&lt;br /&gt;
    condition type_wait[MAX_TYPE];&lt;br /&gt;
    int num_wait[MAX_TYPE];&lt;br /&gt;
&lt;br /&gt;
    queue&amp;lt;int&amp;gt; empty_type;&lt;br /&gt;
    condition is_empty;&lt;br /&gt;
&lt;br /&gt;
    entry pour(type, quantity) {&lt;br /&gt;
        while (keg[type] &amp;lt; quantity) {&lt;br /&gt;
            quantity -= keg[type];&lt;br /&gt;
            keg[type] = 0;&lt;br /&gt;
            if (!empty_type.find(type) &amp;amp;&amp;amp; !worked[type]) {&lt;br /&gt;
                empty_type.enqueue(type);&lt;br /&gt;
                is_empty.signal();&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            num_wait[type]++;&lt;br /&gt;
            type_wait[type].wait();&lt;br /&gt;
            num_wait[type]--;&lt;br /&gt;
        }&lt;br /&gt;
        keg[type] -= quantity;&lt;br /&gt;
        quantity = 0;  // questo è inutile, ma concettualmente è corretto, l'ordine è completato.&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    entry loaded(type, capacity) {&lt;br /&gt;
        keg[type] += capacity;&lt;br /&gt;
        worked[type] = false;&lt;br /&gt;
&lt;br /&gt;
        for (int i = num_wait[type]; i &amp;gt; 0; i--) {&lt;br /&gt;
            type_wait[type].signal();&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // si suppone che un singolo tipo di fusto è lavorabile da un solo magazziniere alla volta.&lt;br /&gt;
    // worked impedisce di avere nella coda un fusto su cuisi sta già lavorando.&lt;br /&gt;
    entry isempty() {&lt;br /&gt;
        if (empty_type.size() &amp;lt;= 0) {&lt;br /&gt;
            is_emtpy.wait();&lt;br /&gt;
        }&lt;br /&gt;
        int type = emtpy_type.dequeue();&lt;br /&gt;
        worked[type] = true;&lt;br /&gt;
        return type;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Esercizio c.2 ==&lt;br /&gt;
&lt;br /&gt;
=== Proposta di soluzione 1 ===&lt;br /&gt;
* Visto e corretto dall'utente [[User:Acsor|Acsor]] in data 23/08/2020&lt;br /&gt;
* Visto e corretto dall'utente ? in data ?&lt;br /&gt;
* Visto, ritenuto corretto [[User:Flecart|Flecart]] ([[User talk:Flecart|talk]]) 09:27, 15 January 2023 (CET)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
class LIFOBuffer {&lt;br /&gt;
	stack&amp;lt;T&amp;gt; s;&lt;br /&gt;
	semaphore mutex(1); // mutua esclusione&lt;br /&gt;
	semaphore ok2consume(0);&lt;br /&gt;
&lt;br /&gt;
	void push (T value) {&lt;br /&gt;
		mutex.P();&lt;br /&gt;
		s.push(value);&lt;br /&gt;
                // (1)&lt;br /&gt;
		mutex.V()&lt;br /&gt;
&lt;br /&gt;
		ok2consume.V()  // Curiosità: che succede se spostiamo quest'istruzione in (1)? Edit: funziona lo stesso, solo che aggiorni il valore del semaforo prima di uscire dalla mutex.&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	T pop () {&lt;br /&gt;
		T value;&lt;br /&gt;
&lt;br /&gt;
		ok2consume.P();&lt;br /&gt;
		mutex.P();&lt;br /&gt;
		value = s.pop();&lt;br /&gt;
		mutex.V();&lt;br /&gt;
&lt;br /&gt;
		return value;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Proposta di soluzione 2 ===&lt;br /&gt;
Proposto da [[User:Flecart|Flecart]] ([[User talk:Flecart|talk]]) 09:27, 15 January 2023 (CET)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
class lifobuf {&lt;br /&gt;
	semaphore mutex(1);&lt;br /&gt;
	stack&amp;lt;int&amp;gt; values;	// empty initialized&lt;br /&gt;
	stack&amp;lt;semaphore&amp;gt; waiting;	&lt;br /&gt;
&lt;br /&gt;
	push(int value) {&lt;br /&gt;
		mutex.P();&lt;br /&gt;
		values.push(value);&lt;br /&gt;
		if (waiting.size() &amp;gt; 0) {&lt;br /&gt;
			semaphore s = waiting.pop();&lt;br /&gt;
			s.V();&lt;br /&gt;
			return;&lt;br /&gt;
		}&lt;br /&gt;
			&lt;br /&gt;
		mutex.V();	&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	pop() {&lt;br /&gt;
		int ret_val;&lt;br /&gt;
		mutex.P();&lt;br /&gt;
		if (values.size() &amp;lt;= 0) {&lt;br /&gt;
			semaphore s = new semaphore(0);&lt;br /&gt;
			waiting.push(s);&lt;br /&gt;
			mutex.V();&lt;br /&gt;
			s.P();&lt;br /&gt;
			free(s);&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		ret_val = values.pop();&lt;br /&gt;
		mutex.V();	&lt;br /&gt;
&lt;br /&gt;
		return ret_val;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Esercizio g.1 ==&lt;br /&gt;
Possiamo notare subito che il sistema ha due processori ed un dispositivo di I/O.&lt;br /&gt;
'''A''' e '''B''' partono insieme al tempo 0.&amp;lt;br&amp;gt;&lt;br /&gt;
'''C''' parte tra il tempo 0 ed il tempo 2 (non possiamo sapere di preciso quando perchè entrambe le CPU sono occupate).&amp;lt;br&amp;gt;&lt;br /&gt;
'''D''' parte tra il tempo 0 ed il tempo 3.&amp;lt;br&amp;gt;&lt;br /&gt;
A questo punto possiamo supporre che tutti e 4 i processi partano in sequenza ('''A''', '''B''', '''C''', '''D''') nello stesso momento, e ognuno prende la prima CPU libera che trova.&amp;lt;br&amp;gt;&lt;br /&gt;
'''A''' lavora per 3ms, poi scade il time slice.&amp;lt;br&amp;gt;&lt;br /&gt;
Nel frattempo '''B''' lavora per 2ms, poi richiede I/O per 4ms.&amp;lt;br&amp;gt;&lt;br /&gt;
La CPU su cui lavora '''B''' quindi si libera, e si manda in esecuzione il processo '''C'''.&amp;lt;br&amp;gt;&lt;br /&gt;
Scaduto il time slice per '''A''', si da il controllo ad un nuovo processo. '''B''' è occupato con I/O, '''C''' sta già lavorando, quindi è il turno di '''D'''.&amp;lt;br&amp;gt;&lt;br /&gt;
'''C''' lavora per 3ms, poi richiede I/O per 3ms, che però è occupato da '''B''', quindi si mette in coda per utilizzarlo.&amp;lt;br&amp;gt;&lt;br /&gt;
La CPU su cui lavorava '''C''' si libera ed il controllo torna ad '''A''', che doveva lavorare ancora per 2ms prima di chiedere il controllo di I/O, quindi lavora e si mette in coda dietro a '''C'''.&amp;lt;br&amp;gt;&lt;br /&gt;
Tornando a '''D''', questo lavora per 3ms prima che scada il time slice. Anche '''B''' ha finito il lavoro e ha bisogno di una CPU.&amp;lt;br&amp;gt;&lt;br /&gt;
In questo momento sia '''D''' che '''B''' sono nella coda dei processi in stato ready, ma dal diagramma possiamo notare che il controllo torna a '''D'''.&amp;lt;br&amp;gt;&lt;br /&gt;
La CPU ha scelto a caso un processo tra i due, perchè arrivati a questo punto possiamo supporre che lo scheduler sia Round-Robin.&amp;lt;br&amp;gt;&lt;br /&gt;
'''B''' prende possesso della prima CPU che si libera, ovvero quella occupata da '''A''', poi lavora per 2ms e termina il suo lavoro.&amp;lt;br&amp;gt;&lt;br /&gt;
Nel momento in cui '''B''' termina il lavoro, scade anche il time slice per '''D''', e '''C''' termina di usare I/O.&amp;lt;br&amp;gt;&lt;br /&gt;
Abbiamo due processi ('''C''' e '''D''') in coda ready. Ma abbiamo anche due CPU libere, perchè '''A''' è in coda per I/O e ci entra appena '''C''' finisce di usarlo.&amp;lt;br&amp;gt;&lt;br /&gt;
Lo scheduler sceglie di mandare '''C''' sul primo processore e '''D''' sul secondo.&amp;lt;br&amp;gt;&lt;br /&gt;
'''A''' nel frattempo, lavora per 4ms con I/O.&amp;lt;br&amp;gt;&lt;br /&gt;
'''C''' lavora per 3ms, poi termina il suo lavoro.&amp;lt;br&amp;gt;&lt;br /&gt;
'''D''' lavora per 3ms, poi scade il time slice. Ci sono due processori liberi, quindi '''D''' riparte subito in esecuzione.&amp;lt;br&amp;gt;&lt;br /&gt;
'''D''' doveva lavorare ancora per 1ms prima di aver bisogno di I/O, quindi finisce e si mette in coda.&amp;lt;br&amp;gt;&lt;br /&gt;
Ma nello stesso momento '''A''' termina di usare I/O, si prende un processore libero e lavora per i suoi ultimi 2ms.&amp;lt;br&amp;gt;&lt;br /&gt;
'''D''' lavora per 1ms con I/O, poi prende il secondo processore libero e lavora per 1ms prima di terminare il suo lavoro.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Il time slice è di 3ms, lo scheduler è di tipo Round-Robin.&amp;lt;br&amp;gt;&lt;br /&gt;
Il dispositivo di I/O è FIFO. L'ordine con cui partono i processi è quello alfabetico.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
A(){&lt;br /&gt;
    compute_a1(); // 5ms&lt;br /&gt;
    io_a(); // 4ms&lt;br /&gt;
    compute_a2(); // 2ms&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
B(){&lt;br /&gt;
    compute_b(); // 2ms&lt;br /&gt;
    io_b(); // 4ms&lt;br /&gt;
    compute_b(); // 2ms&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
C(){&lt;br /&gt;
    compute_c(); // 3ms&lt;br /&gt;
    io_c(); // 3ms&lt;br /&gt;
    compute_c(); // 3ms&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
D(){&lt;br /&gt;
    compute_d1(); // 10ms&lt;br /&gt;
    io_d(); // 1ms&lt;br /&gt;
    compute_d2(); // 1ms&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Lo scheduler potrebbe anche essere a priorità:&amp;lt;br&amp;gt;&lt;br /&gt;
Priorità '''B''' &amp;lt; priorità '''D''' &amp;lt; priorità '''C'''&amp;lt;br&amp;gt;&lt;br /&gt;
Priorità '''A''' = ?&amp;lt;br&amp;gt;&lt;br /&gt;
'''B''' fatto partire prima di '''C''' e '''D'''.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Esercizio g.2 (da controllare) ==&lt;br /&gt;
# In sistemi dove dispositivi di archiviazione o supporti hardware per la memoria virtuale (e dunque per la paginazione, spesso utilizzata per realizzare il supporto di memoria virtuale) non sono presenti (es. sistemi embedded). ''(In sistemi real-time la memoria virtuale è praticabile? Annotare.)''&lt;br /&gt;
# Perchè ad esempio sulle chiavette USB quasi mai abbiamo il problema di dover utilizzare file di dimensione maggiore ai 4GB. Non utilizza il journaling, che richiede molteplici scritture per ogni azione ed in dispositivi portatili può ridurre di molto la durata. Non supporta i permessi sui file, e questo è un vantaggio per le chiavette USB, pensate per trasferire dati tra PC diversi.&lt;br /&gt;
# Per fornire parallelismo e ridondanza. Non è necessario fare backup dei dati sul disco, nel senso di mantenere una copia identica di dati già memorizzati altrove, in quanto diversi sistemi di codici permettono il rilevamento e/o la correzione di errori.&lt;br /&gt;
# Se in un grafo di Holt multirisorsa esiste un ciclo tra più processi e risorse, ciò non significa che allo stesso tempo non siano coinvolti processi con archi esclusivamente entranti. Ogni processo appartenente a questa categoria non è in attesa di risorse, e può dunque procedere con i suoi calcoli; quando avrà terminato rilascerà le risorse precedentemente allocategli, eventualmente sbloccando uno dei processi coinvolti nel ciclo.&lt;br /&gt;
&lt;br /&gt;
= Esame 21/06/2018 =&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2018.06.21.tot.pdf 2018.06.21.tot.pdf]&lt;br /&gt;
=== Esercizio c.1 (sbagliato) ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
/* Monitor tmon */&lt;br /&gt;
&lt;br /&gt;
define MAX n;&lt;br /&gt;
define TERRAFERMA 1;&lt;br /&gt;
define ISOLA 2;&lt;br /&gt;
&lt;br /&gt;
semaphore ok2unload;&lt;br /&gt;
semaphore ok2load;&lt;br /&gt;
semaphore ok2ship;&lt;br /&gt;
semaphore mutex(1); // la rampa è zona critica --&amp;gt; mutua esclusione&lt;br /&gt;
&lt;br /&gt;
stack ferry;&lt;br /&gt;
int current_port = 0;&lt;br /&gt;
&lt;br /&gt;
Procedure entry: al_porto(int location)&lt;br /&gt;
{&lt;br /&gt;
    current_port = location; // traghetto arriva a destinazione&lt;br /&gt;
    ok2unload.signal(); // da il via per far sbarcare le macchine&lt;br /&gt;
    ok2ship.wait(); // si ferma&lt;br /&gt;
    current_port = 0; // traghetto sta viaggiando tra i due porti&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: imbarca(int location)&lt;br /&gt;
{&lt;br /&gt;
    mutex.wait(); // prende possesso della rampa&lt;br /&gt;
    ferry.push(1); // sale sul traghetto&lt;br /&gt;
    mutex.signal(); // libera la rampa&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: imbarcato(int location)&lt;br /&gt;
{&lt;br /&gt;
    if(ferry.lenght() == MAX) // se il traghetto è pieno da il via per farlo salpare&lt;br /&gt;
    {&lt;br /&gt;
        ok2load.wait();&lt;br /&gt;
        ok2ship.signal();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: sbarca(int location)&lt;br /&gt;
{&lt;br /&gt;
    mutex.wait(); // prende possesso della rampa&lt;br /&gt;
    ferry.pop(); // scende dal traghetto&lt;br /&gt;
    mutex.signal(); // libera la rampa&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: sbarcato(int location)&lt;br /&gt;
{&lt;br /&gt;
    if(ferry.lenght() == 0) // se il traghetto è vuoto da il via per far imbarcare le macchine&lt;br /&gt;
    {&lt;br /&gt;
        ok2unload.wait();&lt;br /&gt;
        ok2load.signal();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.1 ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
/* Monitor tmon */&lt;br /&gt;
 &lt;br /&gt;
#define MAX n&lt;br /&gt;
#define NONE 0&lt;br /&gt;
#define TERRAFERMA 1&lt;br /&gt;
#define ISOLA 2&lt;br /&gt;
 &lt;br /&gt;
condition ok2unload;&lt;br /&gt;
condition ok2load[2];&lt;br /&gt;
condition ok2ship;&lt;br /&gt;
condition empty;&lt;br /&gt;
 &lt;br /&gt;
int onboard = 0;&lt;br /&gt;
int onramp = 0;&lt;br /&gt;
int current_port = NONE;&lt;br /&gt;
&lt;br /&gt;
Procedure entry: al_porto(int location)&lt;br /&gt;
{&lt;br /&gt;
    //arrivando&lt;br /&gt;
    current_port = location;&lt;br /&gt;
    ok2unload.signal();&lt;br /&gt;
    if (onboard &amp;gt; 0)&lt;br /&gt;
        empty.wait()&lt;br /&gt;
    ok2load[location].signal()&lt;br /&gt;
    if (onboard &amp;lt; MAX)&lt;br /&gt;
        ok2ship.wait()&lt;br /&gt;
    //partendo&lt;br /&gt;
    current_port = NONE;&lt;br /&gt;
}&lt;br /&gt;
 &lt;br /&gt;
Procedure entry: imbarca(int location)&lt;br /&gt;
{&lt;br /&gt;
    if (current_port != location || onramp &amp;gt; 0 || onboard &amp;gt;= MAX)&lt;br /&gt;
        ok2load[location].wait()&lt;br /&gt;
    onramp = 1;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: imbarcato(int location)&lt;br /&gt;
{&lt;br /&gt;
    onramp = 0; onboard++;&lt;br /&gt;
    if (onboard &amp;lt; MAX)&lt;br /&gt;
        ok2load[location].signal();&lt;br /&gt;
    else&lt;br /&gt;
        ok2ship.signal();&lt;br /&gt;
}&lt;br /&gt;
 &lt;br /&gt;
Procedure entry: sbarca(int location)&lt;br /&gt;
{&lt;br /&gt;
    if (current_port != location || onramp &amp;gt; 0)&lt;br /&gt;
        ok2unload.wait()&lt;br /&gt;
    onramp = 1;&lt;br /&gt;
}&lt;br /&gt;
 &lt;br /&gt;
Procedure entry: sbarcato(int location)&lt;br /&gt;
{&lt;br /&gt;
    onramp = 0; onboard--;&lt;br /&gt;
    if (onboard == 0)&lt;br /&gt;
        empty.signal();&lt;br /&gt;
    else&lt;br /&gt;
        ok2unload.signal();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.2 (sbagliato) ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define N n // limite operazioni&lt;br /&gt;
semaphore mutex(1); // sezione critica&lt;br /&gt;
&lt;br /&gt;
class lim_semaphore()&lt;br /&gt;
{&lt;br /&gt;
    int value;&lt;br /&gt;
    semaphore plus;&lt;br /&gt;
    semaphore minus;&lt;br /&gt;
    &lt;br /&gt;
    P()&lt;br /&gt;
    {&lt;br /&gt;
        mutex.P();&lt;br /&gt;
        if(value &amp;lt; N)&lt;br /&gt;
        {&lt;br /&gt;
            if (value &amp;gt;= 0)&lt;br /&gt;
            {&lt;br /&gt;
                plus.P();&lt;br /&gt;
            }&lt;br /&gt;
            else&lt;br /&gt;
            {&lt;br /&gt;
                minus.V();&lt;br /&gt;
            }&lt;br /&gt;
            value--;&lt;br /&gt;
        }&lt;br /&gt;
        mutex.V();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    V()&lt;br /&gt;
    {&lt;br /&gt;
        mutex.P();&lt;br /&gt;
        if(value &amp;gt; -N)&lt;br /&gt;
        {&lt;br /&gt;
            if (value &amp;lt;= 0)&lt;br /&gt;
            {&lt;br /&gt;
                minus.P();&lt;br /&gt;
            } &lt;br /&gt;
            else&lt;br /&gt;
            {&lt;br /&gt;
                plus.V();&lt;br /&gt;
            }&lt;br /&gt;
            value++;&lt;br /&gt;
        }&lt;br /&gt;
        mutex.V();        &lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.2 ===&lt;br /&gt;
==== Soluzione &amp;quot;furba e facile&amp;quot; ====&lt;br /&gt;
* Visto dall'utente [[User:Acsor|Acsor]] ([[User talk:Acsor|talk]]) in data 18:53, 9 September 2020 (CEST). Ritengo sia: corretto (perché l'ho fatto pressappoco uguale). (Ritengo anche che possedere strumenti di analisi formale per verificare la correttezza di codice simile sarebbe di grande ausilio.)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
class bounded_semaphore {&lt;br /&gt;
    semaphore plus;&lt;br /&gt;
    semaphore minus;&lt;br /&gt;
    int value;   // serve per significato&lt;br /&gt;
    &lt;br /&gt;
    bounded_semaphore (int initval, unsigned maxval) {&lt;br /&gt;
        value = initval;&lt;br /&gt;
        plus = new semaphore(maxval + initval);&lt;br /&gt;
        minus = new semaphore(maxval - initval);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void P() {&lt;br /&gt;
        plus.P();&lt;br /&gt;
        value--;&lt;br /&gt;
        minus.V(); &lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void V() {&lt;br /&gt;
        minus.P();&lt;br /&gt;
        value++;&lt;br /&gt;
        plus.V();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Soluzione &amp;quot;schiacciasassi&amp;quot; ====&lt;br /&gt;
Controllato da [https://t.me/llibera User:LiberaL] in data 2023/05/12, perchè nel primo if della V() si fa value &amp;gt;= - maxval? non dovrebbe essere + maxval?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
class bounded_semaphore {&lt;br /&gt;
    semaphore mutex;&lt;br /&gt;
    queue&amp;lt;semaphore&amp;gt; okmin, okmax;&lt;br /&gt;
    int value;&lt;br /&gt;
    unsigned maxval;&lt;br /&gt;
&lt;br /&gt;
    bounded_semaphore (int initval, unsigned maxval) {&lt;br /&gt;
	value = initval;&lt;br /&gt;
        this.maxval = maxval;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void P() {&lt;br /&gt;
        mutex.P();&lt;br /&gt;
&lt;br /&gt;
        if (value &amp;lt;= -maxval)  {&lt;br /&gt;
            s=semaphore(0);&lt;br /&gt;
            okmin.enqueue(s);&lt;br /&gt;
            mutex.V();&lt;br /&gt;
            s.P();&lt;br /&gt;
        } else if (okmax.length() &amp;gt; 0) {&lt;br /&gt;
            s = okmax.dequeue()&lt;br /&gt;
            s.V();&lt;br /&gt;
            mutex.V();&lt;br /&gt;
        } else {&lt;br /&gt;
            value--;&lt;br /&gt;
            mutex.V();&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void V() {&lt;br /&gt;
        mutex.P();&lt;br /&gt;
&lt;br /&gt;
        if (value &amp;gt;= -maxval)  {  //qui...&lt;br /&gt;
            s=semaphore(0);&lt;br /&gt;
            okmax.enqueue(s);&lt;br /&gt;
            mutex.V();&lt;br /&gt;
            s.P();&lt;br /&gt;
        } else if (okmin.length() &amp;gt; 0) {&lt;br /&gt;
            s = okmin.dequeue()&lt;br /&gt;
            s.V();&lt;br /&gt;
            mutex.V();&lt;br /&gt;
        } else {&lt;br /&gt;
            value++;&lt;br /&gt;
            mutex.V();&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Esercizio g.1 ===&lt;br /&gt;
* Controllato dall'utente [[User:Acsor|Acsor]] ([[User talk:Acsor|talk]]), 23:17, 9 September 2020 (CEST). Ritengo sia: corretto&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
IC = 10,10,10 // Capitale iniziale&lt;br /&gt;
COH = 4,4,4   // Saldo in cassa&lt;br /&gt;
 &lt;br /&gt;
      MAX     ATT     RES    AVAIL&lt;br /&gt;
P1 | 6,6,6 | 1,1,1 | 5,5,5 | 4,4,4&lt;br /&gt;
P2 | 6,6,6 | 1,1,1 | 5,5,5 | 5,5,5&lt;br /&gt;
P3 | 9,9,9 | 4,4,4 | 5,5,5 | 6,6,6&lt;br /&gt;
 &amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Minimizzato&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
IC = 4,4,4&lt;br /&gt;
COH = 1,1,1&lt;br /&gt;
 &lt;br /&gt;
      MAX     ATT     RES  &lt;br /&gt;
P1 | 3,3,3 | 1,1,1 | 2,2,2&lt;br /&gt;
P2 | 3,3,3 | 1,1,1 | 2,2,2&lt;br /&gt;
P3 | 3,3,3 | 1,1,1 | 2,2,2&lt;br /&gt;
 &amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Esercizio g.2 (da controllare) ===&lt;br /&gt;
&lt;br /&gt;
* Visto e rimaneggiato in data 19:40, 10 September 2020 (CEST) dall'utente [[User:Acsor|Acsor]] ([[User talk:Acsor|talk]])&lt;br /&gt;
&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
&lt;br /&gt;
# Il calcolo del working set serve a determinare il numero di processi che possono essere mantenuti attivi sulla base del limite della memoria principale, più precisamente del suo numero di frame. Può essere svolto ad ogni page fault, ossia quando un processo tra quelli attivi richiede una pagina non presente in memoria, o prima di avviare un nuovo processo.&lt;br /&gt;
# La lunghezza massima di un file che può essere memorizzato su un file system di tipo FAT viene calcolata moltiplicando il massimo numero di cluster (dimensione dell'unità di allocazione) identificabili per la loro dimensione. Il massimo numero di cluster identificabili dipende da quanti bit sono allocati per numerarli, e per questa distinzione esistono varie versioni di FAT (FAT12, FAT16, FAT32).&lt;br /&gt;
## FAT32 memorizza la dimensione dei file in un intero unsigned da 32bit, e non può quindi gestire un file di dimensione superiore ai 2^32 bit = ~4GB.&lt;br /&gt;
## FAT16, allocando 16bit per identificare i cluster, può contarne al massimo 2^16 (65536). Prendendo quindi, ad esempio, un file system FAT16 con cluster da 32KB, possiamo avere file grandi al massimo 32KB*65536 = ~2GB.&lt;br /&gt;
## FAT12 di conseguenza può numerare al massimo 2^12 (4096) cluster, ma dato che il numero dei settori del disco viene memorizzato in un intero signed a 16bit, la massima dimensione del disco è 2^15 = 32MB. Ovviamente, non si può memorizzare un file di grandezza superiore alla dimensione dell'unità di memorizzazione stessa, e quindi anche i file in FAT12 possono avere dimensione massima di 32MB.&lt;br /&gt;
# Entrambi condividono l'intento di infettare host con codice malevolo, ma differiscono fondamentalmente nella modalità: i virus infettano programmi già esistenti mediante un ''virus dropper'', mentre i worm diffondono copie di se stessi, solitamente attraverso la rete.&lt;br /&gt;
# In vari casi sulla base della natura del sistema. Innanzitutto, in sistemi batch ciò avviene se non sono stati inseriti più processi per un certo lasso di tempo. In sistemi general-purpose (es. per PC o dispositivi mobili) tale condizione è verificabile se tutti i processi sono in attesa su una coda che non è quella dello scheduler (ad. es. di un semaforo o di una periferica di I/O); casi concreti sono pertanto il deadlock (di tutti i processi del sistema) o attesa generale di I/O. Infine sempre in sistemi general-purpose tale condizione può manifestarsi, stavolta in condizioni patologiche, se ogni processo è assegnato ad una propria CPU/core, lasciando pertanto la coda d'attesa vuota.&lt;br /&gt;
&lt;br /&gt;
= Esame 28/05/2018 =&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2018.05.28.tot.pdf 2018.05.28.tot.pdf]&lt;br /&gt;
=== Esercizio c.1 ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
Stack&amp;lt;int&amp;gt; entriesStack;&lt;br /&gt;
&lt;br /&gt;
int vid[MAX];&lt;br /&gt;
condition ok2esci[MAX]&lt;br /&gt;
int in = 0; &lt;br /&gt;
int out = -1;&lt;br /&gt;
&lt;br /&gt;
Procedure-entry: entra(int id) {&lt;br /&gt;
    if (in &amp;gt;= MAX)&lt;br /&gt;
        ok2entra.wait()&lt;br /&gt;
    vid[in++] = id;&lt;br /&gt;
    if (in &amp;lt; MAX)&lt;br /&gt;
        ok2entra.signal()&lt;br /&gt;
    else&lt;br /&gt;
        out = MAX - 1;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure-entry: esci(int id) {&lt;br /&gt;
    int i;&lt;br /&gt;
    for (i = 0; i &amp;lt; in; i++)&lt;br /&gt;
        if (vid[i] == id)&lt;br /&gt;
            break; //cerco l'indice di id nel vettore vid&lt;br /&gt;
&lt;br /&gt;
    if (i != out)&lt;br /&gt;
        ok2esci[i].wait();&lt;br /&gt;
&lt;br /&gt;
    if (out &amp;gt; 0) {&lt;br /&gt;
        out--;&lt;br /&gt;
        ok2esci[out].signal();&lt;br /&gt;
    } else {&lt;br /&gt;
        out--;&lt;br /&gt;
        in = 0; &lt;br /&gt;
        ok2entra.signal();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.1 (da controllare) ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
Monitor riempisvuota {&lt;br /&gt;
    Int MAXPROCESSI;&lt;br /&gt;
    Stack s;&lt;br /&gt;
    condition ok2enter;&lt;br /&gt;
    condition ok2exit;&lt;br /&gt;
 &lt;br /&gt;
    p.e void entra(getPid()){ &lt;br /&gt;
        if( s.size() &amp;gt;= MAXPROCESSI)&lt;br /&gt;
            ok2enter.wait();&lt;br /&gt;
        s.insert(getPid());&lt;br /&gt;
        if(s.size() &amp;gt; MAXPROCESSI)&lt;br /&gt;
            ok2exit.signal() &lt;br /&gt;
    }&lt;br /&gt;
 &lt;br /&gt;
    p.e void esci(getPid()){ &lt;br /&gt;
        if(s.size() &amp;gt; MAXPROCESSI &amp;amp;&amp;amp; s.top == getPid()) {&lt;br /&gt;
            s.pop();&lt;br /&gt;
            ok2entra.signal()&lt;br /&gt;
        }&lt;br /&gt;
        else&lt;br /&gt;
            ok2exit.wait();&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Esercizio c.2 (ERRATO) ===&lt;br /&gt;
&lt;br /&gt;
* Soluzione proposta è errata, non puoi riceve in modo greedy e printare subito il carattere [[User:Flecart|Flecart]] ([[User talk:Flecart|talk]]) 11:33, 18 January 2023 (CET)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
proc[x]: x='a',...,'z'&lt;br /&gt;
 while True:&lt;br /&gt;
  //c sarà il carattere stampato dal processo precedente&lt;br /&gt;
  (c, string) = arecv(*)&lt;br /&gt;
  if(string == wait){&lt;br /&gt;
    //mi metto in attesa di ricevere l'ACK da proc[x]&lt;br /&gt;
    m=arecv(x);&lt;br /&gt;
  }&lt;br /&gt;
  if (c == NONE){&lt;br /&gt;
    //significa che sei il primo a ricevere quella stringa&lt;br /&gt;
    print(x);&lt;br /&gt;
    if (len(string) &amp;gt; 1){&lt;br /&gt;
      //mando la wait a tutti, il primo che riceve qualcosa da stampare manda una wait a tutti&lt;br /&gt;
      asend(wait,*);&lt;br /&gt;
      int l = len(string);&lt;br /&gt;
      int i = 1;&lt;br /&gt;
      while(l != 0){&lt;br /&gt;
        asend(proc[string[i]], (x, string[i...]));&lt;br /&gt;
        //si mette in attesa di ricevere l'ACK dal processo dell'ultima lettera della parola&lt;br /&gt;
        m=areceive(proc[string[i]]);&lt;br /&gt;
        //rimando la wait al processo per ribloccarlo&lt;br /&gt;
        asend(wait, proc[string[i]])&lt;br /&gt;
        l--;&lt;br /&gt;
        i++;&lt;br /&gt;
      }&lt;br /&gt;
      //dopo aver finito la stampa della stringa sblocco tutti i processi&lt;br /&gt;
      asend(ACK, *);&lt;br /&gt;
    }&lt;br /&gt;
  }else{&lt;br /&gt;
    print(x);&lt;br /&gt;
    asend(ACK, x);&lt;br /&gt;
    //ricomincia il ciclo while, si rimette in attesa e il 'gestore gli rimanda la wait'&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.2  ===&lt;br /&gt;
[[User:Flecart|Flecart friend]] ([[User talk:Flecart|talk]]) cedo la proprità intellettuale di questa soluzione a flecart&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
process [x]: x='a'..'z'&lt;br /&gt;
  if(x=='a'){&lt;br /&gt;
    asend(&amp;lt;NULL,NULL&amp;gt;,'b');&lt;br /&gt;
    asend(&amp;lt;NULL,NULL&amp;gt;,'b');&lt;br /&gt;
  }&lt;br /&gt;
  While True:&lt;br /&gt;
    &amp;lt;c,string&amp;gt;=arecv(x-1+26%26);&lt;br /&gt;
    if(string==NULL):&lt;br /&gt;
      &amp;lt;c,string&amp;gt;=arecv(*);&lt;br /&gt;
      if(string!=NULL):&lt;br /&gt;
        &amp;lt;c,string&amp;gt;=arecv(x-1+26%26);&lt;br /&gt;
&lt;br /&gt;
    if(string!=NULL):&lt;br /&gt;
      if(string[0]==x):&lt;br /&gt;
        print(string[0]);&lt;br /&gt;
        if(string.len()&amp;gt;1):&lt;br /&gt;
          aasend(&amp;lt;NULL,string[1:]&amp;gt;,(x+1)%26);&lt;br /&gt;
        else:&lt;br /&gt;
          aasend(&amp;lt;NULL,NULL&amp;gt;,(x+1)%26);&lt;br /&gt;
          aasend(&amp;lt;NULL,NULL&amp;gt;,(x+1)%26);&lt;br /&gt;
      else:&lt;br /&gt;
          aasend(&amp;lt;NULL,string&amp;gt;,(x+1)%26);&lt;br /&gt;
    else:&lt;br /&gt;
      aasend(&amp;lt;NULL,NULL&amp;gt;,(x+1)%26);&lt;br /&gt;
      aasend(&amp;lt;NULL,NULL&amp;gt;,(x+1)%26);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Proposta c2 ===&lt;br /&gt;
* Proposto [[User:Flecart|Flecart]] ([[User talk:Flecart|talk]]) 11:31, 18 January 2023 (CET)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
proc[a]:&lt;br /&gt;
	bool occupied = false;&lt;br /&gt;
	queue&amp;lt;string&amp;gt; s;&lt;br /&gt;
	&lt;br /&gt;
	while True {&lt;br /&gt;
		(c, string) = arecv(*);&lt;br /&gt;
		&lt;br /&gt;
		if (c == NONE) {&lt;br /&gt;
			if (occupied) {&lt;br /&gt;
				s.enqueue(string);&lt;br /&gt;
			} else {&lt;br /&gt;
				if (string.len() &amp;lt; 1)&lt;br /&gt;
					continue;&lt;br /&gt;
			&lt;br /&gt;
				occupied = true;&lt;br /&gt;
				asend(string[0], (MIDDLE, string));&lt;br /&gt;
			}&lt;br /&gt;
		} else if (c == END) {&lt;br /&gt;
			if (s.size() &amp;gt; 0) {&lt;br /&gt;
				string ss = s.dequeue();&lt;br /&gt;
				asend(string[0], (MIDLLE, string));&lt;br /&gt;
			} else {&lt;br /&gt;
				occupied = false;&lt;br /&gt;
			}&lt;br /&gt;
		} else {&lt;br /&gt;
			print(x);&lt;br /&gt;
			if (len(string) &amp;gt; 1) &lt;br /&gt;
				asend(proc[string[0]], (MIDDLE, string[1:]));&lt;br /&gt;
			else:&lt;br /&gt;
				asend(proc[a], (END, &amp;quot;&amp;quot;));&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
		&lt;br /&gt;
proc[x]: x = 'b', ... 'z';&lt;br /&gt;
	while True {&lt;br /&gt;
		(c, string) = arecv(*);&lt;br /&gt;
		if (c == NONE) {&lt;br /&gt;
			asend(proc['a'], (NONE, string));&lt;br /&gt;
		} else {  // potrà essere solo MIDDLE&lt;br /&gt;
			print(x);&lt;br /&gt;
			if (len(string) &amp;gt; 1) &lt;br /&gt;
				asend(proc[string[0]], (MIDDLE, string[1:]));&lt;br /&gt;
			else:&lt;br /&gt;
				asend(proc[a], (END, &amp;quot;&amp;quot;));&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Esame 12/02/2018 =&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2018.02.12.tot.pdf 2018.02.12.tot.pdf]&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.1 (da controllare) ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
monitor bridge:&lt;br /&gt;
&lt;br /&gt;
    int ncar&lt;br /&gt;
    bool boat_on_0&lt;br /&gt;
    bool boat_on_1       // per semplicità, quando nel codice si trova boat_on_(direction) oppure isBoat(direction)(),&lt;br /&gt;
                         // si valuta il valore booleano di direction e lo si applica sotto forma di stringa al simbolo&lt;br /&gt;
                         // ad esso adiacente&lt;br /&gt;
    bool is_raised&lt;br /&gt;
    queue waiting_mean   // i valori possibili sono: boat0, boat1 oppure car&lt;br /&gt;
    condition ok2go&lt;br /&gt;
  &lt;br /&gt;
    entry car_enter(direction): &lt;br /&gt;
        if is_raised || ncar == MAXCAR:&lt;br /&gt;
            waiting_mean.enqueue(car)&lt;br /&gt;
            ok2go.wait()&lt;br /&gt;
        is_raised = false&lt;br /&gt;
        ++ncar&lt;br /&gt;
  &lt;br /&gt;
    entry car_exit(direction):&lt;br /&gt;
        --ncar&lt;br /&gt;
        if (waiting_mean.top().isBoat() &amp;amp;&amp;amp; ncar == 0) || waiting_mean.top().isCar():    // isBoat ritorna true se l'oggetto su cui&lt;br /&gt;
            waiting_mean.dequeue()                                                      // è invocata è boat0 oppure boat1&lt;br /&gt;
            ok2go.signal()&lt;br /&gt;
  &lt;br /&gt;
    entry boat_enter(direction):&lt;br /&gt;
        if !is_raised || boat_on_(direction):&lt;br /&gt;
            waiting_mean.enqueue(boat)&lt;br /&gt;
            ok2go.wait()&lt;br /&gt;
        if waiting_mean.top().isBoat(!direction)():&lt;br /&gt;
            waiting_mean.dequeue()&lt;br /&gt;
            ok2go.signal()&lt;br /&gt;
        is_raised = true&lt;br /&gt;
        boat_on_(direction) = true&lt;br /&gt;
  &lt;br /&gt;
    entry boat_exit(direction):&lt;br /&gt;
        boat_on_(direction) = false&lt;br /&gt;
        if !boat_on_(!direction):&lt;br /&gt;
            waiting_mean.dequeue()&lt;br /&gt;
            ok2go.signal()&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.1 ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
monitor bridge  {&lt;br /&gt;
  int carsOnBridge = 0;&lt;br /&gt;
  int shipping[2] = {0, 0}; //navi da entrambe le direzioni&lt;br /&gt;
  int status = NONE; //UP DOWN NONE&lt;br /&gt;
  int last2pass = 0;     //ultimo che ha passato il ponte&lt;br /&gt;
  int waitingC = 0;      //coda delle macchine che aspettano&lt;br /&gt;
  int waitingS[2] = {0,0};  //navi che stanno aspettando&lt;br /&gt;
   &lt;br /&gt;
  condition ok2ship[2]&lt;br /&gt;
  condition ok2drive&lt;br /&gt;
 &lt;br /&gt;
entry car_enter(int direction){&lt;br /&gt;
    if(carsOnBridge &amp;gt;= MAX || status == UP || waitingS[0] + waitingS[1] &amp;gt; 0 ){&lt;br /&gt;
        waitingC++;ok2drive.wait;waitingC--;}&lt;br /&gt;
    status = DOWN;&lt;br /&gt;
    carsOnBridge++&lt;br /&gt;
    if (carsOnBridge &amp;lt; MAX)&lt;br /&gt;
       ok2drive.signal();     //vanno tutte le MAX car che stanno aspettando&lt;br /&gt;
} &lt;br /&gt;
entry car_exit(int direction){&lt;br /&gt;
    carsOnBridge--&lt;br /&gt;
    if (waitingS[0] + waitingS[1] == 0)&lt;br /&gt;
    ok2drive.signal();&lt;br /&gt;
    if(carsOnBridge == 0){&lt;br /&gt;
        ok2ship[0].signal(); ok2ship[1].signal();&lt;br /&gt;
    }&lt;br /&gt;
    if(carsOnBridge + waitingS[0] + waitingS[1] == 0) &lt;br /&gt;
    status = NONE&lt;br /&gt;
}&lt;br /&gt;
 &lt;br /&gt;
entry ship_enter(int direction){&lt;br /&gt;
    if (bridge = DOWN || shipping[direction] != 0 || waitingC &amp;gt; 0)&lt;br /&gt;
    {&lt;br /&gt;
        waitingS[i]++; ok2ship[i].wait(); waitingS[i]--; &lt;br /&gt;
    }&lt;br /&gt;
    isBridgeUp = false;&lt;br /&gt;
    shipping[i] = 1;&lt;br /&gt;
 &lt;br /&gt;
entry ship_exit(int direction){&lt;br /&gt;
      shipping[i] = 0;&lt;br /&gt;
      if (waitingC == 0)&lt;br /&gt;
          ok2ship[i].signal()&lt;br /&gt;
      else if(shipping[1-i] == 0)&lt;br /&gt;
          ok2drive.signal();&lt;br /&gt;
      if(carsOnBridge + waitingS[0] + waitingS[1] == 0) &lt;br /&gt;
      status = NONE&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.1 (da controllare) ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
monitor bridge {&lt;br /&gt;
&lt;br /&gt;
  UP=0;&lt;br /&gt;
  DOWN=1;&lt;br /&gt;
  bridgeis = DOWN;&lt;br /&gt;
&lt;br /&gt;
  bool carAreExiting = false;&lt;br /&gt;
&lt;br /&gt;
  condition ok2drive;&lt;br /&gt;
  condition ok2barca[2];&lt;br /&gt;
&lt;br /&gt;
  waitingCar = 0;&lt;br /&gt;
  carOnBridge = 0;&lt;br /&gt;
&lt;br /&gt;
  boatWaiting[2] = {0,0};&lt;br /&gt;
  boatIsPassing[2] = {false,false}&lt;br /&gt;
&lt;br /&gt;
  entry car_enter(direction) {&lt;br /&gt;
&lt;br /&gt;
    if (bridgeis == DOWN)&lt;br /&gt;
      if(carOnBridge == MAXCAR)&lt;br /&gt;
        waitingCar++;&lt;br /&gt;
        ok2drive.wait();&lt;br /&gt;
        waitingCar--;&lt;br /&gt;
      else if (carAreExiting)&lt;br /&gt;
        waitingCar++;&lt;br /&gt;
        ok2drive.wait();&lt;br /&gt;
        waitingCar--;&lt;br /&gt;
    else &lt;br /&gt;
      if (boatIsPassing[0] || boatIsPassing[1])&lt;br /&gt;
        waitingCar++;&lt;br /&gt;
        ok2drive.wait();&lt;br /&gt;
        waitingCar--;&lt;br /&gt;
        bridgeis = DOWN;&lt;br /&gt;
&lt;br /&gt;
    carOnBridge++;&lt;br /&gt;
    carAreExiting = false;&lt;br /&gt;
    if(carOnBridge &amp;lt; MAXCAR &amp;amp;&amp;amp; !carAreExiting) &lt;br /&gt;
      ok2drive.signal();&lt;br /&gt;
      &lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  entry car_exit(direction) {&lt;br /&gt;
&lt;br /&gt;
    carOnBridge--;&lt;br /&gt;
    carAreExiting = true;&lt;br /&gt;
&lt;br /&gt;
    if(carOnBridge == 0)&lt;br /&gt;
      carAreExiting = false;&lt;br /&gt;
      if(boatWaiting[0] &amp;gt; 0)&lt;br /&gt;
        bridgeis = UP;&lt;br /&gt;
        ok2barca[0].signal();&lt;br /&gt;
      else if (boatWaiting[1] &amp;gt; 0)&lt;br /&gt;
        bridgeis = UP;&lt;br /&gt;
        ok2barca[1].signal();&lt;br /&gt;
      else &lt;br /&gt;
        ok2drive.signal();&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  entry boat_enter(direction) {&lt;br /&gt;
&lt;br /&gt;
    if (bridgeis == UP)&lt;br /&gt;
    | if (boatIsPassing[direction] == true)&lt;br /&gt;
    | |  boatWaiting[direction]++;&lt;br /&gt;
    | |  ok2barca.wait();&lt;br /&gt;
    | |  boatWaiting[direction]--;&lt;br /&gt;
    else &lt;br /&gt;
    | if (carOnBridge &amp;gt; 0)&lt;br /&gt;
    | | boatWaiting[direction]++;&lt;br /&gt;
    | | ok2barca.wait();&lt;br /&gt;
    | | boatWaiting[direction]--;&lt;br /&gt;
    | | bridgeis = UP;&lt;br /&gt;
&lt;br /&gt;
    boatIsPassing[direction] = true;&lt;br /&gt;
&lt;br /&gt;
    if(boatIsPassing[1-direction] == false &amp;amp;&amp;amp; boatWaiting[1-direction] &amp;gt; 0)&lt;br /&gt;
      ok2barca[1-direction].signal();&lt;br /&gt;
    &lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  entry boat_exit(direction) {&lt;br /&gt;
&lt;br /&gt;
    boatIsPassing[direction] = false;&lt;br /&gt;
&lt;br /&gt;
    if (boatIsPassing[1-direction] == false)&lt;br /&gt;
      if (waitingCar &amp;gt; 0)&lt;br /&gt;
        bridgeis = DOWN;&lt;br /&gt;
        ok2drive.signal();&lt;br /&gt;
    else&lt;br /&gt;
        if (waitingCar == 0)&lt;br /&gt;
          ok2barca[direction].signal();&lt;br /&gt;
          &lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.1 (sbagliato) ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
monitor bridge&lt;br /&gt;
  condition ok2passCar;&lt;br /&gt;
  condition ok2passBoat;&lt;br /&gt;
  condition ok2up;&lt;br /&gt;
  condition ok2down;&lt;br /&gt;
  int carOnBridge[2] = 0; //2 sensi di marcia&lt;br /&gt;
  int boatUnderBridge[2] = 0;&lt;br /&gt;
  boolean bridge_down = false; //vuol dire che il ponte parte alzato, true ponte abbassato&lt;br /&gt;
  &lt;br /&gt;
  procedure entry car_enter(direction){&lt;br /&gt;
      if(bridge_down &amp;amp;&amp;amp; carOnBridge[direction] &amp;lt; MAXCAR){&lt;br /&gt;
        carOnBridge[direction]++;&lt;br /&gt;
        ok2passCar.signal();&lt;br /&gt;
      }else if (bridge_down &amp;amp;&amp;amp; boatUnderBridge[0] == 0 &amp;amp;&amp;amp; boatUnderBridge[1] == 0){&lt;br /&gt;
        //se non ci sono navi in transito e arriva una macchina abbassa ponte&lt;br /&gt;
        ok2down.signal();&lt;br /&gt;
        ok2passCar.signal();&lt;br /&gt;
        ok2passBoat.wait();&lt;br /&gt;
      }else{&lt;br /&gt;
        ok2passCar.wait();&lt;br /&gt;
      }&lt;br /&gt;
  }     &lt;br /&gt;
        &lt;br /&gt;
  procedure entry car_exit(direction){&lt;br /&gt;
      carOnBridge[direction]--;&lt;br /&gt;
      if(carOnBridge[0] == 0 &amp;amp;&amp;amp; carOnBridge[1] == 0){&lt;br /&gt;
        bridge_down = false;&lt;br /&gt;
        ok2up.signal();&lt;br /&gt;
      }else{&lt;br /&gt;
        ok2up.wait();&lt;br /&gt;
      }&lt;br /&gt;
  }&lt;br /&gt;
      &lt;br /&gt;
  procedure entry boat_enter(direction){&lt;br /&gt;
      if(!bridge_down &amp;amp;&amp;amp; boatUnderBridge[direction] &amp;lt; 1){&lt;br /&gt;
        boatUnderBridge[direction]++;&lt;br /&gt;
        ok2passBoat.signal();&lt;br /&gt;
      }else if(!bridge_down &amp;amp;&amp;amp; carOnBridge[0] == 0 &amp;amp;&amp;amp; carOnBridge[1] == 0){&lt;br /&gt;
        ok2up.signal();&lt;br /&gt;
        ok2passBoat.signal();&lt;br /&gt;
        ok2passCar.wait();&lt;br /&gt;
      }else {&lt;br /&gt;
        ok2passBoat.wait();&lt;br /&gt;
      }&lt;br /&gt;
  }&lt;br /&gt;
      &lt;br /&gt;
  procedure entry boat_exit(direction){  &lt;br /&gt;
      boatUnderBridge[direction]--;&lt;br /&gt;
      if(boatUnderBridge[0] == 0 &amp;amp;&amp;amp; boatUnderBridge[1] == 0){&lt;br /&gt;
        bridge_down = true;&lt;br /&gt;
        ok2down.signal();&lt;br /&gt;
      }else{&lt;br /&gt;
        ok2down.wait();&lt;br /&gt;
      }&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.1 2o (sbagliato) ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define car 1&lt;br /&gt;
#define ship 2 &lt;br /&gt;
#define fromDX 1&lt;br /&gt;
#define fromSX 0&lt;br /&gt;
&lt;br /&gt;
monitor bridge  {&lt;br /&gt;
  int carsOnBridge = 0;&lt;br /&gt;
  int shippingDX = 0; //nave che sta passando dal lato destro&lt;br /&gt;
  int shippingSX = 0; //nave che sta passando dal lato sinistro&lt;br /&gt;
  bool isBridgeUp = false;&lt;br /&gt;
  int last2pass = 0;     //ultimo che ha passato il ponte&lt;br /&gt;
  int waitingS = 0;  //navi che stanno aspettando&lt;br /&gt;
  int waitingC = 0 ; //auto che stanno aspettando&lt;br /&gt;
  &lt;br /&gt;
  condition ok2ship&lt;br /&gt;
  condition ok2drive&lt;br /&gt;
&lt;br /&gt;
entry car_enter(int direction){&lt;br /&gt;
    //un auto si ferma se il numero di auto sul ponte è massimo&lt;br /&gt;
    //e se l'ultima a passare è stata un auto mentre ci sono navi in attesa&lt;br /&gt;
    if(carsOnBridge == MAX || isBridgeUp || (last2pass==car &amp;amp;&amp;amp; waitingS &amp;gt; 0) ){&lt;br /&gt;
        waitingC++;&lt;br /&gt;
        ok2drive.wait;&lt;br /&gt;
    }&lt;br /&gt;
    carsOnBridge++;&lt;br /&gt;
    waitingC--;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
entry car_exit(int direction){&lt;br /&gt;
    carsOnBridge--;&lt;br /&gt;
    last2pass = car;&lt;br /&gt;
    if(carsOnBridge == 0 &amp;amp;&amp;amp; waitingS&amp;gt;0){&lt;br /&gt;
        isBrigdeUp = true;&lt;br /&gt;
        ok2ship.signal;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
entry ship_enter(int direction){&lt;br /&gt;
    //se la barca viene da destra&lt;br /&gt;
    if(direction == fromDX){&lt;br /&gt;
        //si ferma anche quando c'è una nave che sta già attraversando nella sua stessa direzione&lt;br /&gt;
        if (isBridgeup == false || shippingDX || (last2pass==ship &amp;amp;&amp;amp; waitingC &amp;gt; 0) ){&lt;br /&gt;
            waitingS++;&lt;br /&gt;
            ok2ship.wait;&lt;br /&gt;
        }&lt;br /&gt;
        if (waitingS &amp;gt; 0)&lt;br /&gt;
            waitingS--;&lt;br /&gt;
        shippingDX = 1;&lt;br /&gt;
        }&lt;br /&gt;
    //se la barca viene da sinistra&lt;br /&gt;
    else if(direction == fromSX){&lt;br /&gt;
        if (isBridgeup == false || shippingSX || ( (last2pass==ship &amp;amp;&amp;amp; waitingC &amp;gt; 0))){&lt;br /&gt;
        waitingS++;&lt;br /&gt;
        ok2ship.wait;&lt;br /&gt;
        }&lt;br /&gt;
        if (waitingS &amp;gt; 0)&lt;br /&gt;
            waitingS--;        &lt;br /&gt;
        shippingSX = 1;&lt;br /&gt;
    &lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
entry ship_exit(int direction){&lt;br /&gt;
        if(direction == fromDX)&lt;br /&gt;
            shippingDX = 0;&lt;br /&gt;
        else if (direction == fromSX)&lt;br /&gt;
            shippingSX = 0;&lt;br /&gt;
        last2pass = ship;&lt;br /&gt;
        if(shippingDX == 0 &amp;amp;&amp;amp; shippingSX == 0 &amp;amp;&amp;amp; waitingC)&lt;br /&gt;
            isBrigdeUp == false;&lt;br /&gt;
            ok2drive.signal;&lt;br /&gt;
        else if(shippingDX == 0 &amp;amp;&amp;amp; shippingSX == 0 &amp;amp;&amp;amp; waitingS &amp;gt; 0)&lt;br /&gt;
            ok2ship.signal;    &lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.2 (sbagliato) ===&lt;br /&gt;
&lt;br /&gt;
# (Ri)Controllato dall'utente [[User:Acsor|Acsor]] ([[User talk:Acsor|talk]]) in data 26/08/2020&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
list printed_msg;  # questa è una variabile condivisa che ai fini dell'esercizio non si può utilizzare (message passing)&lt;br /&gt;
&lt;br /&gt;
process server[i]:&lt;br /&gt;
  while true:&lt;br /&gt;
    &amp;lt;msg, pid&amp;gt; = arecv(*)&lt;br /&gt;
&lt;br /&gt;
    if printed_msg.length == 0 or &amp;lt;msg, pid&amp;gt; is not in printed_msg:&lt;br /&gt;
      printed_msg.append(&amp;lt;msg,id&amp;gt;)&lt;br /&gt;
      print(msg)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.2 (da controllare) ===&lt;br /&gt;
Nello svolgimento seguente, receiver incapsula l'ambiente privato del processo; _peers rappresenta il vettore di processi &amp;quot;fratelli&amp;quot; ai quali può essere chiesto di stampare un messaggio, mentre _printed contiene l'hash di tutti i messaggi stampati dal processo locale. Si suppone che istanze della classe receiver possano essere passate come parametro ad areceive() ed asend() (non implementate).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
class receiver:&lt;br /&gt;
    def __init__(self, peers):&lt;br /&gt;
        &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
        :param peers: list of processes this process communicates with.&lt;br /&gt;
        &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
        self._peers = tuple(peers)&lt;br /&gt;
        self._printed = list()&lt;br /&gt;
    &lt;br /&gt;
    def run(self):&lt;br /&gt;
        while True:&lt;br /&gt;
            process, message = areceive(ANY)&lt;br /&gt;
&lt;br /&gt;
            if process in self._peers:&lt;br /&gt;
                self._reply_query(process, message)&lt;br /&gt;
            else:&lt;br /&gt;
                self._print(process, message)&lt;br /&gt;
&lt;br /&gt;
    def _print(self, sender, message):&lt;br /&gt;
        h = hash(message.text)&lt;br /&gt;
&lt;br /&gt;
        if h not in self._printed and not self._printed_from_peers(message):&lt;br /&gt;
            self._printed.append(h)&lt;br /&gt;
            print(message.text)&lt;br /&gt;
&lt;br /&gt;
    def _reply_query(self, sender, h):&lt;br /&gt;
        &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
        Invoked when the current process receive a &amp;quot;query&amp;quot; from a peer process.&lt;br /&gt;
        `h` contains the hash of a message which may or may have not been&lt;br /&gt;
        sent from this process; if it was sent, the reply is `Yes`, otherwise `No`.&lt;br /&gt;
        &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
        reply = &amp;quot;Yes&amp;quot; if int(h) in self._printed else &amp;quot;No&amp;quot;&lt;br /&gt;
        asend(sender, reply)&lt;br /&gt;
&lt;br /&gt;
    def _printed_from_peers(self, message):&lt;br /&gt;
        &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
        :return: `True` if this message has already been printed from any of the&lt;br /&gt;
        peer processes, `False` otherwise.&lt;br /&gt;
        &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
        h = hash(message)&lt;br /&gt;
&lt;br /&gt;
        for p in self._peers:&lt;br /&gt;
            asend(p, str(h))&lt;br /&gt;
&lt;br /&gt;
        for p in self._peers:&lt;br /&gt;
            _, reply = areceive(p)&lt;br /&gt;
&lt;br /&gt;
            if reply.text == &amp;quot;Yes&amp;quot;:&lt;br /&gt;
                return True&lt;br /&gt;
            else if reply.text != &amp;quot;No&amp;quot;:&lt;br /&gt;
                # If the response is neither &amp;quot;Yes&amp;quot; nor &amp;quot;No&amp;quot;, then we have got a query&lt;br /&gt;
                self._reply_query(p, reply)&lt;br /&gt;
&lt;br /&gt;
        return False&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Esercizio g.1 (da controllare) ===&lt;br /&gt;
Sulla base dei valori in entrata, è possibile costruire le matrici Allocation (q.tà di risorse allocate per processo e per tipo), Need (q.tà di risorse che ogni processo potrebbe ancora chiedere) e il vettore Available (num. di risorse correntemente disponibili).&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;float: left&amp;quot;&lt;br /&gt;
! colspan=3 | Allocation&lt;br /&gt;
|-&lt;br /&gt;
   !   !! A !! B&lt;br /&gt;
|-&lt;br /&gt;
   | p1 || 4 || 5&lt;br /&gt;
|-&lt;br /&gt;
   | p2 || 3 || 3&lt;br /&gt;
|-&lt;br /&gt;
   | p3 || 2 || 4&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;float: left; margin-left: 1em&amp;quot;&lt;br /&gt;
! colspan=3 | Need&lt;br /&gt;
|-&lt;br /&gt;
   !    !! A !! B&lt;br /&gt;
|-&lt;br /&gt;
   | p1 || 6 || 8&lt;br /&gt;
|-&lt;br /&gt;
   | p2 || 6 || 3&lt;br /&gt;
|-&lt;br /&gt;
   | p3 || 6 || 8&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;float: left; margin-left: 1em&amp;quot;&lt;br /&gt;
! colspan=2 | Available&lt;br /&gt;
|-&lt;br /&gt;
   ! A !! B&lt;br /&gt;
|-&lt;br /&gt;
   | x || y&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nel caso delle risorse di tipo A, deve aversi x &amp;gt;= 6 in quanto un processo dovrà essere selezionato come primo nella permutazione dell'algoritmo del banchiere multivaluta, e tutti quelli correnti hanno lo stesso valore Need(i)(1); per ciò che riguarda le risorse di tipo B, possiamo ragionare per esaustione&lt;br /&gt;
&lt;br /&gt;
* Se il primo processo della permutazione è p1, allora y &amp;gt;= 8 (con questo valore posso soddisfare la richiesta di p1 e in seguito tutte le altre)&lt;br /&gt;
* Se il primo processo della permutazione è p2, allora y &amp;gt;= 5: con questo valore è possibile soddisfare la richiesta di p2; una volta che esso avrà finito, restituirà 3 unità della risorsa B, che permetteranno di soddisfare sia le richieste di A sia quelle di C&lt;br /&gt;
* Se il primo processo della permutazione è p3, allora y &amp;gt;= 8 (ragionamento analogo come per p1)&lt;br /&gt;
&lt;br /&gt;
Volendo scegliere il minimo, y &amp;gt;= 5, ed in conclusione (x, y) &amp;gt;= (6, 5).&lt;br /&gt;
&lt;br /&gt;
''Svolgimento basato in parte sull'approccio di Operating System Concepts di Silberschatz. et al, 9th edition, cap. 7.''&lt;br /&gt;
&lt;br /&gt;
=== Esercizio g.2 (da controllare) ===&lt;br /&gt;
# Può accadere che il sistema torni in uno stato di safety o che invece porti a deadlock. Diversamente uno stato di safety non può portare direttamente ad uno stato di deadlock, ma solo ad uno di non-safety.&lt;br /&gt;
# Selezionare uno o più tra i processi attivi e sospenderli, salvando il loro stato su memoria secondaria operando delle operazioni di swap-out, finché l'insieme dei frame nella memoria centrale non è in grado di soddisfare tutti i processi rimasti attivi.&lt;br /&gt;
# La scelta è determinata perlopiù dal fattore costo. Con un sistema RAID 1 è possibile ripristinare un disco guasto molto brevemente, in quanto le operazioni coinvolte prevedono una semplice ricopiatura dal disco di backup; con un sistema RAID 5 il ripristino del disco guasto deve coinvolgere tutti i dischi dell'intero array, e ciò può richiedere anche ore per dischi di grandi dimensioni. D'altra parte RAID 1 è più costoso (con n dischi, posso memorizzare tanta informazione quanto potrei con n / 2 dischi) rispetto a RAID 5 dove, tra gli n dischi, complessivamente soltanto uno è destinato alle informazioni di ridondanza.&lt;br /&gt;
# ''Completare.''&lt;/div&gt;</summary>
		<author><name>LiberaL</name></author>
	</entry>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=Prove_scritte_2018&amp;diff=2975</id>
		<title>Prove scritte 2018</title>
		<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php?title=Prove_scritte_2018&amp;diff=2975"/>
		<updated>2023-05-12T14:45:21Z</updated>

		<summary type="html">&lt;p&gt;LiberaL: /* Soluzione &amp;quot;schiacciasassi&amp;quot; */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Esame 19/09/2018 =&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2018.09.19.tot.pdf Testo dell'esame].&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.2 (da controllare) ===&lt;br /&gt;
&lt;br /&gt;
* Controllato dall'utente ? in data ?&lt;br /&gt;
* ...&lt;br /&gt;
&lt;br /&gt;
Nello pseudocodice seguente, il termine this fa riferimento al processo corrente, mentre ANY ad uno qualunque.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
stack&amp;lt;message&amp;gt; messages;&lt;br /&gt;
&lt;br /&gt;
void lifo_send(string m, process dest) {&lt;br /&gt;
	do {&lt;br /&gt;
		asend(m, dest);&lt;br /&gt;
	} while (areceive(dest).text != &amp;quot;ACK&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
message lifo_receive(process source) {&lt;br /&gt;
	if (source != ANY) {&lt;br /&gt;
		message m = areceive(source);&lt;br /&gt;
&lt;br /&gt;
		asend(&amp;quot;ACK&amp;quot;, source);&lt;br /&gt;
&lt;br /&gt;
		return m;&lt;br /&gt;
	} else {&lt;br /&gt;
		message m;&lt;br /&gt;
&lt;br /&gt;
		asend(&amp;quot;END&amp;quot;, this);&lt;br /&gt;
		m = areceive(ANY);&lt;br /&gt;
&lt;br /&gt;
		while (m.text != &amp;quot;END&amp;quot; || m.sender != this) {&lt;br /&gt;
			messages.push(m);&lt;br /&gt;
			asend(&amp;quot;ACK&amp;quot;, m.sender);&lt;br /&gt;
&lt;br /&gt;
			m = areceive(ANY);&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
                /* Bisogna tenere conto dei casi in cui lifo_receive() viene invocata quando nessun&lt;br /&gt;
                 * messaggio è stato ancora spedito da altri processi. In tal caso si attende il&lt;br /&gt;
                 * il primo e lo si restituisce.&lt;br /&gt;
                 */&lt;br /&gt;
		if (messages.empty()) {&lt;br /&gt;
			m = areceive(ANY);&lt;br /&gt;
			asend(&amp;quot;ACK&amp;quot;, m.sender);&lt;br /&gt;
&lt;br /&gt;
			return m;&lt;br /&gt;
		} else {&lt;br /&gt;
			return messages.pop();&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Esame 17/07/2018 =&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2018.07.17.tot.pdf 2018.07.17.tot.pdf]&lt;br /&gt;
== Esercizio c.1 ==&lt;br /&gt;
A Bruxelles c'è un locale chiamato Delirium Café. Alla vigilia del FOSDEM tutti gli anni gli sviluppatori europei di&lt;br /&gt;
software libero si ritrovano a bere birra (il locale è nel guinnes dei primati con più di duemila tipi di birra). Il prossimo appuntamento è&lt;br /&gt;
fissato per il 1 febbraio 2019 ore 20. Numerosi sono i tipi di birra alla spina. I baristi (tanti) prendono gli ordini (es. mezza pinta, 1 o 2&lt;br /&gt;
pinte) e riempiono i bicchieri. Quando un fusto e' vuoto avvertono i magazzinieri che prendono un nuovo fusto che contiene più di&lt;br /&gt;
cento pinte e lo sostituiscono, a questo punto il barista può completare il riempimento del bicchiere.&lt;br /&gt;
La vita di un barista del Delirium è:&lt;br /&gt;
 while True:&lt;br /&gt;
   (type, quantity) = get_order()&lt;br /&gt;
   delirium.pour(type, quantity)&lt;br /&gt;
La vita di un Magazziniere è:&lt;br /&gt;
 while True:&lt;br /&gt;
   type = delirium.isempty()&lt;br /&gt;
   capacity = change_keg(type)&lt;br /&gt;
   delirium.loaded(type, capacity)&lt;br /&gt;
&lt;br /&gt;
Attenzione: se il fusto (keg) è quasi vuoto il barista dovrà riempire parzialmente il bicchiere, occorrerà attivare il magazziniere che&lt;br /&gt;
cambierà il fusto e poi il barista riempirà il bicchiere fino alla quantità richiesta dal cliente. Mentre un barista sta attendendo il&lt;br /&gt;
cambiamento di un fusto altri baristi potrebbero ricevere ordini per lo stesso tipo di birra: gestire opportunamente questo caso.&lt;br /&gt;
Scrivere il monitor Delirium.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Proposta di soluzione 1 === &lt;br /&gt;
* ERRORE: Secondo me c'è un leggero errore nella parte di load, nel caso in cui la nuova pinta non riesca a soddisfare completamente la richiesta ossia quando vale availableBeer[t] &amp;lt;= requests[t].head(), allora non lo risveglio nemmeno, invece dovrei risvegliare il pour, fargli versare quanto può, e richiedere una altra pinta, perché questo era un requisito del problema. [[User:Flecart|Flecart]] ([[User talk:Flecart|talk]]) 12:00, 15 January 2023 (CET)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
/* Monitor Delirum: */&lt;br /&gt;
&lt;br /&gt;
// Condition: Ok2Load;&lt;br /&gt;
// Condition: Ok2Pour[]; // Un elemento per Type&lt;br /&gt;
int availableBeer[]; // Un elemento per Type &lt;br /&gt;
Queue requests[]; // Un elemento per Type&lt;br /&gt;
Queue pendingRequests;&lt;br /&gt;
&lt;br /&gt;
Procedure entry: void Pour(Type t, Quantity c)&lt;br /&gt;
{&lt;br /&gt;
    if (c &amp;gt; availableBeer[t]) // Richiesta maggiore della birra disponibile&lt;br /&gt;
    {&lt;br /&gt;
        c -= availableBeer[t];&lt;br /&gt;
        availableBeer[t] = 0;              &lt;br /&gt;
        requests[t].Enqueue(c);&lt;br /&gt;
        if (requests[t].Length == 1) // Risveglio un magazziniere solo se è la prima richiesta di questo tipo di birra&lt;br /&gt;
        {&lt;br /&gt;
            pendingRequests.Enqueue(t);&lt;br /&gt;
            Ok2Load().Signal();&lt;br /&gt;
        }&lt;br /&gt;
        Ok2Pour[t].Wait();&lt;br /&gt;
        requests[t].Dequeue(); // Quando ho ottenuto la birra che voglio, elimino la mia richiesta&lt;br /&gt;
    }&lt;br /&gt;
    availableBeer[t] -= c;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: Type isEmpty()&lt;br /&gt;
{&lt;br /&gt;
    if (pendingRequests.Length == 0)&lt;br /&gt;
    {&lt;br /&gt;
        Ok2Load.Wait();&lt;br /&gt;
    }&lt;br /&gt;
    return pendingRequests.Dequeue();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: Loaded(Type t, Capacity c)&lt;br /&gt;
{&lt;br /&gt;
    availableBeer[t] += c;&lt;br /&gt;
    while (requests[t].Length &amp;gt; 0 &amp;amp;&amp;amp; availableBeer[t] &amp;gt; requests[t].head())&lt;br /&gt;
    {&lt;br /&gt;
        Ok2Pour[t].Signal();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (requests[t].Length &amp;gt; 0) // serve per evitare che a causa di un magazziniere lento si accodino cosi tante richieste che mentre si sta caricando si svuota subito il fusto&lt;br /&gt;
    {&lt;br /&gt;
        pendingRequests.Enqueue(t);&lt;br /&gt;
        Ok2Load.Signal();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Proposta di soluzione 2 ===&lt;br /&gt;
* Proposto da [[User:Flecart|Flecart]] ([[User talk:Flecart|talk]]) 13:41, 15 January 2023 (CET)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
extern int MAX_TYPE;&lt;br /&gt;
class Delirium {&lt;br /&gt;
    int keg[MAX_TYPE];      // qnty fusto attuale&lt;br /&gt;
    int orders[MAX_TYPE];   // qnty richiesta&lt;br /&gt;
    bool worked[MAX_TYPE];  // 1 se magazziniere sta lavorando su questo.&lt;br /&gt;
&lt;br /&gt;
    condition type_wait[MAX_TYPE];&lt;br /&gt;
    int num_wait[MAX_TYPE];&lt;br /&gt;
&lt;br /&gt;
    queue&amp;lt;int&amp;gt; empty_type;&lt;br /&gt;
    condition is_empty;&lt;br /&gt;
&lt;br /&gt;
    entry pour(type, quantity) {&lt;br /&gt;
        while (keg[type] &amp;lt; quantity) {&lt;br /&gt;
            quantity -= keg[type];&lt;br /&gt;
            keg[type] = 0;&lt;br /&gt;
            if (!empty_type.find(type) &amp;amp;&amp;amp; !worked[type]) {&lt;br /&gt;
                empty_type.enqueue(type);&lt;br /&gt;
                is_empty.signal();&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            num_wait[type]++;&lt;br /&gt;
            type_wait[type].wait();&lt;br /&gt;
            num_wait[type]--;&lt;br /&gt;
        }&lt;br /&gt;
        keg[type] -= quantity;&lt;br /&gt;
        quantity = 0;  // questo è inutile, ma concettualmente è corretto, l'ordine è completato.&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    entry loaded(type, capacity) {&lt;br /&gt;
        keg[type] += capacity;&lt;br /&gt;
        worked[type] = false;&lt;br /&gt;
&lt;br /&gt;
        for (int i = num_wait[type]; i &amp;gt; 0; i--) {&lt;br /&gt;
            type_wait[type].signal();&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // si suppone che un singolo tipo di fusto è lavorabile da un solo magazziniere alla volta.&lt;br /&gt;
    // worked impedisce di avere nella coda un fusto su cuisi sta già lavorando.&lt;br /&gt;
    entry isempty() {&lt;br /&gt;
        if (empty_type.size() &amp;lt;= 0) {&lt;br /&gt;
            is_emtpy.wait();&lt;br /&gt;
        }&lt;br /&gt;
        int type = emtpy_type.dequeue();&lt;br /&gt;
        worked[type] = true;&lt;br /&gt;
        return type;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Esercizio c.2 ==&lt;br /&gt;
&lt;br /&gt;
=== Proposta di soluzione 1 ===&lt;br /&gt;
* Visto e corretto dall'utente [[User:Acsor|Acsor]] in data 23/08/2020&lt;br /&gt;
* Visto e corretto dall'utente ? in data ?&lt;br /&gt;
* Visto, ritenuto corretto [[User:Flecart|Flecart]] ([[User talk:Flecart|talk]]) 09:27, 15 January 2023 (CET)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
class LIFOBuffer {&lt;br /&gt;
	stack&amp;lt;T&amp;gt; s;&lt;br /&gt;
	semaphore mutex(1); // mutua esclusione&lt;br /&gt;
	semaphore ok2consume(0);&lt;br /&gt;
&lt;br /&gt;
	void push (T value) {&lt;br /&gt;
		mutex.P();&lt;br /&gt;
		s.push(value);&lt;br /&gt;
                // (1)&lt;br /&gt;
		mutex.V()&lt;br /&gt;
&lt;br /&gt;
		ok2consume.V()  // Curiosità: che succede se spostiamo quest'istruzione in (1)? Edit: funziona lo stesso, solo che aggiorni il valore del semaforo prima di uscire dalla mutex.&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	T pop () {&lt;br /&gt;
		T value;&lt;br /&gt;
&lt;br /&gt;
		ok2consume.P();&lt;br /&gt;
		mutex.P();&lt;br /&gt;
		value = s.pop();&lt;br /&gt;
		mutex.V();&lt;br /&gt;
&lt;br /&gt;
		return value;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Proposta di soluzione 2 ===&lt;br /&gt;
Proposto da [[User:Flecart|Flecart]] ([[User talk:Flecart|talk]]) 09:27, 15 January 2023 (CET)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
class lifobuf {&lt;br /&gt;
	semaphore mutex(1);&lt;br /&gt;
	stack&amp;lt;int&amp;gt; values;	// empty initialized&lt;br /&gt;
	stack&amp;lt;semaphore&amp;gt; waiting;	&lt;br /&gt;
&lt;br /&gt;
	push(int value) {&lt;br /&gt;
		mutex.P();&lt;br /&gt;
		values.push(value);&lt;br /&gt;
		if (waiting.size() &amp;gt; 0) {&lt;br /&gt;
			semaphore s = waiting.pop();&lt;br /&gt;
			s.V();&lt;br /&gt;
			return;&lt;br /&gt;
		}&lt;br /&gt;
			&lt;br /&gt;
		mutex.V();	&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	pop() {&lt;br /&gt;
		int ret_val;&lt;br /&gt;
		mutex.P();&lt;br /&gt;
		if (values.size() &amp;lt;= 0) {&lt;br /&gt;
			semaphore s = new semaphore(0);&lt;br /&gt;
			waiting.push(s);&lt;br /&gt;
			mutex.V();&lt;br /&gt;
			s.P();&lt;br /&gt;
			free(s);&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		ret_val = values.pop();&lt;br /&gt;
		mutex.V();	&lt;br /&gt;
&lt;br /&gt;
		return ret_val;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Esercizio g.1 ==&lt;br /&gt;
Possiamo notare subito che il sistema ha due processori ed un dispositivo di I/O.&lt;br /&gt;
'''A''' e '''B''' partono insieme al tempo 0.&amp;lt;br&amp;gt;&lt;br /&gt;
'''C''' parte tra il tempo 0 ed il tempo 2 (non possiamo sapere di preciso quando perchè entrambe le CPU sono occupate).&amp;lt;br&amp;gt;&lt;br /&gt;
'''D''' parte tra il tempo 0 ed il tempo 3.&amp;lt;br&amp;gt;&lt;br /&gt;
A questo punto possiamo supporre che tutti e 4 i processi partano in sequenza ('''A''', '''B''', '''C''', '''D''') nello stesso momento, e ognuno prende la prima CPU libera che trova.&amp;lt;br&amp;gt;&lt;br /&gt;
'''A''' lavora per 3ms, poi scade il time slice.&amp;lt;br&amp;gt;&lt;br /&gt;
Nel frattempo '''B''' lavora per 2ms, poi richiede I/O per 4ms.&amp;lt;br&amp;gt;&lt;br /&gt;
La CPU su cui lavora '''B''' quindi si libera, e si manda in esecuzione il processo '''C'''.&amp;lt;br&amp;gt;&lt;br /&gt;
Scaduto il time slice per '''A''', si da il controllo ad un nuovo processo. '''B''' è occupato con I/O, '''C''' sta già lavorando, quindi è il turno di '''D'''.&amp;lt;br&amp;gt;&lt;br /&gt;
'''C''' lavora per 3ms, poi richiede I/O per 3ms, che però è occupato da '''B''', quindi si mette in coda per utilizzarlo.&amp;lt;br&amp;gt;&lt;br /&gt;
La CPU su cui lavorava '''C''' si libera ed il controllo torna ad '''A''', che doveva lavorare ancora per 2ms prima di chiedere il controllo di I/O, quindi lavora e si mette in coda dietro a '''C'''.&amp;lt;br&amp;gt;&lt;br /&gt;
Tornando a '''D''', questo lavora per 3ms prima che scada il time slice. Anche '''B''' ha finito il lavoro e ha bisogno di una CPU.&amp;lt;br&amp;gt;&lt;br /&gt;
In questo momento sia '''D''' che '''B''' sono nella coda dei processi in stato ready, ma dal diagramma possiamo notare che il controllo torna a '''D'''.&amp;lt;br&amp;gt;&lt;br /&gt;
La CPU ha scelto a caso un processo tra i due, perchè arrivati a questo punto possiamo supporre che lo scheduler sia Round-Robin.&amp;lt;br&amp;gt;&lt;br /&gt;
'''B''' prende possesso della prima CPU che si libera, ovvero quella occupata da '''A''', poi lavora per 2ms e termina il suo lavoro.&amp;lt;br&amp;gt;&lt;br /&gt;
Nel momento in cui '''B''' termina il lavoro, scade anche il time slice per '''D''', e '''C''' termina di usare I/O.&amp;lt;br&amp;gt;&lt;br /&gt;
Abbiamo due processi ('''C''' e '''D''') in coda ready. Ma abbiamo anche due CPU libere, perchè '''A''' è in coda per I/O e ci entra appena '''C''' finisce di usarlo.&amp;lt;br&amp;gt;&lt;br /&gt;
Lo scheduler sceglie di mandare '''C''' sul primo processore e '''D''' sul secondo.&amp;lt;br&amp;gt;&lt;br /&gt;
'''A''' nel frattempo, lavora per 4ms con I/O.&amp;lt;br&amp;gt;&lt;br /&gt;
'''C''' lavora per 3ms, poi termina il suo lavoro.&amp;lt;br&amp;gt;&lt;br /&gt;
'''D''' lavora per 3ms, poi scade il time slice. Ci sono due processori liberi, quindi '''D''' riparte subito in esecuzione.&amp;lt;br&amp;gt;&lt;br /&gt;
'''D''' doveva lavorare ancora per 1ms prima di aver bisogno di I/O, quindi finisce e si mette in coda.&amp;lt;br&amp;gt;&lt;br /&gt;
Ma nello stesso momento '''A''' termina di usare I/O, si prende un processore libero e lavora per i suoi ultimi 2ms.&amp;lt;br&amp;gt;&lt;br /&gt;
'''D''' lavora per 1ms con I/O, poi prende il secondo processore libero e lavora per 1ms prima di terminare il suo lavoro.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Il time slice è di 3ms, lo scheduler è di tipo Round-Robin.&amp;lt;br&amp;gt;&lt;br /&gt;
Il dispositivo di I/O è FIFO. L'ordine con cui partono i processi è quello alfabetico.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
A(){&lt;br /&gt;
    compute_a1(); // 5ms&lt;br /&gt;
    io_a(); // 4ms&lt;br /&gt;
    compute_a2(); // 2ms&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
B(){&lt;br /&gt;
    compute_b(); // 2ms&lt;br /&gt;
    io_b(); // 4ms&lt;br /&gt;
    compute_b(); // 2ms&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
C(){&lt;br /&gt;
    compute_c(); // 3ms&lt;br /&gt;
    io_c(); // 3ms&lt;br /&gt;
    compute_c(); // 3ms&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
D(){&lt;br /&gt;
    compute_d1(); // 10ms&lt;br /&gt;
    io_d(); // 1ms&lt;br /&gt;
    compute_d2(); // 1ms&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Lo scheduler potrebbe anche essere a priorità:&amp;lt;br&amp;gt;&lt;br /&gt;
Priorità '''B''' &amp;lt; priorità '''D''' &amp;lt; priorità '''C'''&amp;lt;br&amp;gt;&lt;br /&gt;
Priorità '''A''' = ?&amp;lt;br&amp;gt;&lt;br /&gt;
'''B''' fatto partire prima di '''C''' e '''D'''.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Esercizio g.2 (da controllare) ==&lt;br /&gt;
# In sistemi dove dispositivi di archiviazione o supporti hardware per la memoria virtuale (e dunque per la paginazione, spesso utilizzata per realizzare il supporto di memoria virtuale) non sono presenti (es. sistemi embedded). ''(In sistemi real-time la memoria virtuale è praticabile? Annotare.)''&lt;br /&gt;
# Perchè ad esempio sulle chiavette USB quasi mai abbiamo il problema di dover utilizzare file di dimensione maggiore ai 4GB. Non utilizza il journaling, che richiede molteplici scritture per ogni azione ed in dispositivi portatili può ridurre di molto la durata. Non supporta i permessi sui file, e questo è un vantaggio per le chiavette USB, pensate per trasferire dati tra PC diversi.&lt;br /&gt;
# Per fornire parallelismo e ridondanza. Non è necessario fare backup dei dati sul disco, nel senso di mantenere una copia identica di dati già memorizzati altrove, in quanto diversi sistemi di codici permettono il rilevamento e/o la correzione di errori.&lt;br /&gt;
# Se in un grafo di Holt multirisorsa esiste un ciclo tra più processi e risorse, ciò non significa che allo stesso tempo non siano coinvolti processi con archi esclusivamente entranti. Ogni processo appartenente a questa categoria non è in attesa di risorse, e può dunque procedere con i suoi calcoli; quando avrà terminato rilascerà le risorse precedentemente allocategli, eventualmente sbloccando uno dei processi coinvolti nel ciclo.&lt;br /&gt;
&lt;br /&gt;
= Esame 21/06/2018 =&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2018.06.21.tot.pdf 2018.06.21.tot.pdf]&lt;br /&gt;
=== Esercizio c.1 (sbagliato) ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
/* Monitor tmon */&lt;br /&gt;
&lt;br /&gt;
define MAX n;&lt;br /&gt;
define TERRAFERMA 1;&lt;br /&gt;
define ISOLA 2;&lt;br /&gt;
&lt;br /&gt;
semaphore ok2unload;&lt;br /&gt;
semaphore ok2load;&lt;br /&gt;
semaphore ok2ship;&lt;br /&gt;
semaphore mutex(1); // la rampa è zona critica --&amp;gt; mutua esclusione&lt;br /&gt;
&lt;br /&gt;
stack ferry;&lt;br /&gt;
int current_port = 0;&lt;br /&gt;
&lt;br /&gt;
Procedure entry: al_porto(int location)&lt;br /&gt;
{&lt;br /&gt;
    current_port = location; // traghetto arriva a destinazione&lt;br /&gt;
    ok2unload.signal(); // da il via per far sbarcare le macchine&lt;br /&gt;
    ok2ship.wait(); // si ferma&lt;br /&gt;
    current_port = 0; // traghetto sta viaggiando tra i due porti&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: imbarca(int location)&lt;br /&gt;
{&lt;br /&gt;
    mutex.wait(); // prende possesso della rampa&lt;br /&gt;
    ferry.push(1); // sale sul traghetto&lt;br /&gt;
    mutex.signal(); // libera la rampa&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: imbarcato(int location)&lt;br /&gt;
{&lt;br /&gt;
    if(ferry.lenght() == MAX) // se il traghetto è pieno da il via per farlo salpare&lt;br /&gt;
    {&lt;br /&gt;
        ok2load.wait();&lt;br /&gt;
        ok2ship.signal();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: sbarca(int location)&lt;br /&gt;
{&lt;br /&gt;
    mutex.wait(); // prende possesso della rampa&lt;br /&gt;
    ferry.pop(); // scende dal traghetto&lt;br /&gt;
    mutex.signal(); // libera la rampa&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: sbarcato(int location)&lt;br /&gt;
{&lt;br /&gt;
    if(ferry.lenght() == 0) // se il traghetto è vuoto da il via per far imbarcare le macchine&lt;br /&gt;
    {&lt;br /&gt;
        ok2unload.wait();&lt;br /&gt;
        ok2load.signal();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.1 ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
/* Monitor tmon */&lt;br /&gt;
 &lt;br /&gt;
#define MAX n&lt;br /&gt;
#define NONE 0&lt;br /&gt;
#define TERRAFERMA 1&lt;br /&gt;
#define ISOLA 2&lt;br /&gt;
 &lt;br /&gt;
condition ok2unload;&lt;br /&gt;
condition ok2load[2];&lt;br /&gt;
condition ok2ship;&lt;br /&gt;
condition empty;&lt;br /&gt;
 &lt;br /&gt;
int onboard = 0;&lt;br /&gt;
int onramp = 0;&lt;br /&gt;
int current_port = NONE;&lt;br /&gt;
&lt;br /&gt;
Procedure entry: al_porto(int location)&lt;br /&gt;
{&lt;br /&gt;
    //arrivando&lt;br /&gt;
    current_port = location;&lt;br /&gt;
    ok2unload.signal();&lt;br /&gt;
    if (onboard &amp;gt; 0)&lt;br /&gt;
        empty.wait()&lt;br /&gt;
    ok2load[location].signal()&lt;br /&gt;
    if (onboard &amp;lt; MAX)&lt;br /&gt;
        ok2ship.wait()&lt;br /&gt;
    //partendo&lt;br /&gt;
    current_port = NONE;&lt;br /&gt;
}&lt;br /&gt;
 &lt;br /&gt;
Procedure entry: imbarca(int location)&lt;br /&gt;
{&lt;br /&gt;
    if (current_port != location || onramp &amp;gt; 0 || onboard &amp;gt;= MAX)&lt;br /&gt;
        ok2load[location].wait()&lt;br /&gt;
    onramp = 1;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: imbarcato(int location)&lt;br /&gt;
{&lt;br /&gt;
    onramp = 0; onboard++;&lt;br /&gt;
    if (onboard &amp;lt; MAX)&lt;br /&gt;
        ok2load[location].signal();&lt;br /&gt;
    else&lt;br /&gt;
        ok2ship.signal();&lt;br /&gt;
}&lt;br /&gt;
 &lt;br /&gt;
Procedure entry: sbarca(int location)&lt;br /&gt;
{&lt;br /&gt;
    if (current_port != location || onramp &amp;gt; 0)&lt;br /&gt;
        ok2unload.wait()&lt;br /&gt;
    onramp = 1;&lt;br /&gt;
}&lt;br /&gt;
 &lt;br /&gt;
Procedure entry: sbarcato(int location)&lt;br /&gt;
{&lt;br /&gt;
    onramp = 0; onboard--;&lt;br /&gt;
    if (onboard == 0)&lt;br /&gt;
        empty.signal();&lt;br /&gt;
    else&lt;br /&gt;
        ok2unload.signal();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.2 (sbagliato) ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define N n // limite operazioni&lt;br /&gt;
semaphore mutex(1); // sezione critica&lt;br /&gt;
&lt;br /&gt;
class lim_semaphore()&lt;br /&gt;
{&lt;br /&gt;
    int value;&lt;br /&gt;
    semaphore plus;&lt;br /&gt;
    semaphore minus;&lt;br /&gt;
    &lt;br /&gt;
    P()&lt;br /&gt;
    {&lt;br /&gt;
        mutex.P();&lt;br /&gt;
        if(value &amp;lt; N)&lt;br /&gt;
        {&lt;br /&gt;
            if (value &amp;gt;= 0)&lt;br /&gt;
            {&lt;br /&gt;
                plus.P();&lt;br /&gt;
            }&lt;br /&gt;
            else&lt;br /&gt;
            {&lt;br /&gt;
                minus.V();&lt;br /&gt;
            }&lt;br /&gt;
            value--;&lt;br /&gt;
        }&lt;br /&gt;
        mutex.V();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    V()&lt;br /&gt;
    {&lt;br /&gt;
        mutex.P();&lt;br /&gt;
        if(value &amp;gt; -N)&lt;br /&gt;
        {&lt;br /&gt;
            if (value &amp;lt;= 0)&lt;br /&gt;
            {&lt;br /&gt;
                minus.P();&lt;br /&gt;
            } &lt;br /&gt;
            else&lt;br /&gt;
            {&lt;br /&gt;
                plus.V();&lt;br /&gt;
            }&lt;br /&gt;
            value++;&lt;br /&gt;
        }&lt;br /&gt;
        mutex.V();        &lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.2 ===&lt;br /&gt;
==== Soluzione &amp;quot;furba e facile&amp;quot; ====&lt;br /&gt;
* Visto dall'utente [[User:Acsor|Acsor]] ([[User talk:Acsor|talk]]) in data 18:53, 9 September 2020 (CEST). Ritengo sia: corretto (perché l'ho fatto pressappoco uguale). (Ritengo anche che possedere strumenti di analisi formale per verificare la correttezza di codice simile sarebbe di grande ausilio.)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
class bounded_semaphore {&lt;br /&gt;
    semaphore plus;&lt;br /&gt;
    semaphore minus;&lt;br /&gt;
    int value;   // serve per significato&lt;br /&gt;
    &lt;br /&gt;
    bounded_semaphore (int initval, unsigned maxval) {&lt;br /&gt;
        value = initval;&lt;br /&gt;
        plus = new semaphore(maxval + initval);&lt;br /&gt;
        minus = new semaphore(maxval - initval);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void P() {&lt;br /&gt;
        plus.P();&lt;br /&gt;
        value--;&lt;br /&gt;
        minus.V(); &lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void V() {&lt;br /&gt;
        minus.P();&lt;br /&gt;
        value++;&lt;br /&gt;
        plus.V();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Soluzione &amp;quot;schiacciasassi&amp;quot; ====&lt;br /&gt;
Controllato da [[https://t.me/llibera|LiberaL]] in data 2023/05/12, perchè nel primo if della V() si fa value &amp;gt;= - maxval? non dovrebbe essere + maxval?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
class bounded_semaphore {&lt;br /&gt;
    semaphore mutex;&lt;br /&gt;
    queue&amp;lt;semaphore&amp;gt; okmin, okmax;&lt;br /&gt;
    int value;&lt;br /&gt;
    unsigned maxval;&lt;br /&gt;
&lt;br /&gt;
    bounded_semaphore (int initval, unsigned maxval) {&lt;br /&gt;
	value = initval;&lt;br /&gt;
        this.maxval = maxval;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void P() {&lt;br /&gt;
        mutex.P();&lt;br /&gt;
&lt;br /&gt;
        if (value &amp;lt;= -maxval)  {&lt;br /&gt;
            s=semaphore(0);&lt;br /&gt;
            okmin.enqueue(s);&lt;br /&gt;
            mutex.V();&lt;br /&gt;
            s.P();&lt;br /&gt;
        } else if (okmax.length() &amp;gt; 0) {&lt;br /&gt;
            s = okmax.dequeue()&lt;br /&gt;
            s.V();&lt;br /&gt;
            mutex.V();&lt;br /&gt;
        } else {&lt;br /&gt;
            value--;&lt;br /&gt;
            mutex.V();&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void V() {&lt;br /&gt;
        mutex.P();&lt;br /&gt;
&lt;br /&gt;
        if (value &amp;gt;= -maxval)  {  //qui...&lt;br /&gt;
            s=semaphore(0);&lt;br /&gt;
            okmax.enqueue(s);&lt;br /&gt;
            mutex.V();&lt;br /&gt;
            s.P();&lt;br /&gt;
        } else if (okmin.length() &amp;gt; 0) {&lt;br /&gt;
            s = okmin.dequeue()&lt;br /&gt;
            s.V();&lt;br /&gt;
            mutex.V();&lt;br /&gt;
        } else {&lt;br /&gt;
            value++;&lt;br /&gt;
            mutex.V();&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Esercizio g.1 ===&lt;br /&gt;
* Controllato dall'utente [[User:Acsor|Acsor]] ([[User talk:Acsor|talk]]), 23:17, 9 September 2020 (CEST). Ritengo sia: corretto&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
IC = 10,10,10 // Capitale iniziale&lt;br /&gt;
COH = 4,4,4   // Saldo in cassa&lt;br /&gt;
 &lt;br /&gt;
      MAX     ATT     RES    AVAIL&lt;br /&gt;
P1 | 6,6,6 | 1,1,1 | 5,5,5 | 4,4,4&lt;br /&gt;
P2 | 6,6,6 | 1,1,1 | 5,5,5 | 5,5,5&lt;br /&gt;
P3 | 9,9,9 | 4,4,4 | 5,5,5 | 6,6,6&lt;br /&gt;
 &amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Minimizzato&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
IC = 4,4,4&lt;br /&gt;
COH = 1,1,1&lt;br /&gt;
 &lt;br /&gt;
      MAX     ATT     RES  &lt;br /&gt;
P1 | 3,3,3 | 1,1,1 | 2,2,2&lt;br /&gt;
P2 | 3,3,3 | 1,1,1 | 2,2,2&lt;br /&gt;
P3 | 3,3,3 | 1,1,1 | 2,2,2&lt;br /&gt;
 &amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Esercizio g.2 (da controllare) ===&lt;br /&gt;
&lt;br /&gt;
* Visto e rimaneggiato in data 19:40, 10 September 2020 (CEST) dall'utente [[User:Acsor|Acsor]] ([[User talk:Acsor|talk]])&lt;br /&gt;
&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
&lt;br /&gt;
# Il calcolo del working set serve a determinare il numero di processi che possono essere mantenuti attivi sulla base del limite della memoria principale, più precisamente del suo numero di frame. Può essere svolto ad ogni page fault, ossia quando un processo tra quelli attivi richiede una pagina non presente in memoria, o prima di avviare un nuovo processo.&lt;br /&gt;
# La lunghezza massima di un file che può essere memorizzato su un file system di tipo FAT viene calcolata moltiplicando il massimo numero di cluster (dimensione dell'unità di allocazione) identificabili per la loro dimensione. Il massimo numero di cluster identificabili dipende da quanti bit sono allocati per numerarli, e per questa distinzione esistono varie versioni di FAT (FAT12, FAT16, FAT32).&lt;br /&gt;
## FAT32 memorizza la dimensione dei file in un intero unsigned da 32bit, e non può quindi gestire un file di dimensione superiore ai 2^32 bit = ~4GB.&lt;br /&gt;
## FAT16, allocando 16bit per identificare i cluster, può contarne al massimo 2^16 (65536). Prendendo quindi, ad esempio, un file system FAT16 con cluster da 32KB, possiamo avere file grandi al massimo 32KB*65536 = ~2GB.&lt;br /&gt;
## FAT12 di conseguenza può numerare al massimo 2^12 (4096) cluster, ma dato che il numero dei settori del disco viene memorizzato in un intero signed a 16bit, la massima dimensione del disco è 2^15 = 32MB. Ovviamente, non si può memorizzare un file di grandezza superiore alla dimensione dell'unità di memorizzazione stessa, e quindi anche i file in FAT12 possono avere dimensione massima di 32MB.&lt;br /&gt;
# Entrambi condividono l'intento di infettare host con codice malevolo, ma differiscono fondamentalmente nella modalità: i virus infettano programmi già esistenti mediante un ''virus dropper'', mentre i worm diffondono copie di se stessi, solitamente attraverso la rete.&lt;br /&gt;
# In vari casi sulla base della natura del sistema. Innanzitutto, in sistemi batch ciò avviene se non sono stati inseriti più processi per un certo lasso di tempo. In sistemi general-purpose (es. per PC o dispositivi mobili) tale condizione è verificabile se tutti i processi sono in attesa su una coda che non è quella dello scheduler (ad. es. di un semaforo o di una periferica di I/O); casi concreti sono pertanto il deadlock (di tutti i processi del sistema) o attesa generale di I/O. Infine sempre in sistemi general-purpose tale condizione può manifestarsi, stavolta in condizioni patologiche, se ogni processo è assegnato ad una propria CPU/core, lasciando pertanto la coda d'attesa vuota.&lt;br /&gt;
&lt;br /&gt;
= Esame 28/05/2018 =&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2018.05.28.tot.pdf 2018.05.28.tot.pdf]&lt;br /&gt;
=== Esercizio c.1 ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
Stack&amp;lt;int&amp;gt; entriesStack;&lt;br /&gt;
&lt;br /&gt;
int vid[MAX];&lt;br /&gt;
condition ok2esci[MAX]&lt;br /&gt;
int in = 0; &lt;br /&gt;
int out = -1;&lt;br /&gt;
&lt;br /&gt;
Procedure-entry: entra(int id) {&lt;br /&gt;
    if (in &amp;gt;= MAX)&lt;br /&gt;
        ok2entra.wait()&lt;br /&gt;
    vid[in++] = id;&lt;br /&gt;
    if (in &amp;lt; MAX)&lt;br /&gt;
        ok2entra.signal()&lt;br /&gt;
    else&lt;br /&gt;
        out = MAX - 1;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure-entry: esci(int id) {&lt;br /&gt;
    int i;&lt;br /&gt;
    for (i = 0; i &amp;lt; in; i++)&lt;br /&gt;
        if (vid[i] == id)&lt;br /&gt;
            break; //cerco l'indice di id nel vettore vid&lt;br /&gt;
&lt;br /&gt;
    if (i != out)&lt;br /&gt;
        ok2esci[i].wait();&lt;br /&gt;
&lt;br /&gt;
    if (out &amp;gt; 0) {&lt;br /&gt;
        out--;&lt;br /&gt;
        ok2esci[out].signal();&lt;br /&gt;
    } else {&lt;br /&gt;
        out--;&lt;br /&gt;
        in = 0; &lt;br /&gt;
        ok2entra.signal();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.1 (da controllare) ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
Monitor riempisvuota {&lt;br /&gt;
    Int MAXPROCESSI;&lt;br /&gt;
    Stack s;&lt;br /&gt;
    condition ok2enter;&lt;br /&gt;
    condition ok2exit;&lt;br /&gt;
 &lt;br /&gt;
    p.e void entra(getPid()){ &lt;br /&gt;
        if( s.size() &amp;gt;= MAXPROCESSI)&lt;br /&gt;
            ok2enter.wait();&lt;br /&gt;
        s.insert(getPid());&lt;br /&gt;
        if(s.size() &amp;gt; MAXPROCESSI)&lt;br /&gt;
            ok2exit.signal() &lt;br /&gt;
    }&lt;br /&gt;
 &lt;br /&gt;
    p.e void esci(getPid()){ &lt;br /&gt;
        if(s.size() &amp;gt; MAXPROCESSI &amp;amp;&amp;amp; s.top == getPid()) {&lt;br /&gt;
            s.pop();&lt;br /&gt;
            ok2entra.signal()&lt;br /&gt;
        }&lt;br /&gt;
        else&lt;br /&gt;
            ok2exit.wait();&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Esercizio c.2 (ERRATO) ===&lt;br /&gt;
&lt;br /&gt;
* Soluzione proposta è errata, non puoi riceve in modo greedy e printare subito il carattere [[User:Flecart|Flecart]] ([[User talk:Flecart|talk]]) 11:33, 18 January 2023 (CET)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
proc[x]: x='a',...,'z'&lt;br /&gt;
 while True:&lt;br /&gt;
  //c sarà il carattere stampato dal processo precedente&lt;br /&gt;
  (c, string) = arecv(*)&lt;br /&gt;
  if(string == wait){&lt;br /&gt;
    //mi metto in attesa di ricevere l'ACK da proc[x]&lt;br /&gt;
    m=arecv(x);&lt;br /&gt;
  }&lt;br /&gt;
  if (c == NONE){&lt;br /&gt;
    //significa che sei il primo a ricevere quella stringa&lt;br /&gt;
    print(x);&lt;br /&gt;
    if (len(string) &amp;gt; 1){&lt;br /&gt;
      //mando la wait a tutti, il primo che riceve qualcosa da stampare manda una wait a tutti&lt;br /&gt;
      asend(wait,*);&lt;br /&gt;
      int l = len(string);&lt;br /&gt;
      int i = 1;&lt;br /&gt;
      while(l != 0){&lt;br /&gt;
        asend(proc[string[i]], (x, string[i...]));&lt;br /&gt;
        //si mette in attesa di ricevere l'ACK dal processo dell'ultima lettera della parola&lt;br /&gt;
        m=areceive(proc[string[i]]);&lt;br /&gt;
        //rimando la wait al processo per ribloccarlo&lt;br /&gt;
        asend(wait, proc[string[i]])&lt;br /&gt;
        l--;&lt;br /&gt;
        i++;&lt;br /&gt;
      }&lt;br /&gt;
      //dopo aver finito la stampa della stringa sblocco tutti i processi&lt;br /&gt;
      asend(ACK, *);&lt;br /&gt;
    }&lt;br /&gt;
  }else{&lt;br /&gt;
    print(x);&lt;br /&gt;
    asend(ACK, x);&lt;br /&gt;
    //ricomincia il ciclo while, si rimette in attesa e il 'gestore gli rimanda la wait'&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.2  ===&lt;br /&gt;
[[User:Flecart|Flecart friend]] ([[User talk:Flecart|talk]]) cedo la proprità intellettuale di questa soluzione a flecart&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
process [x]: x='a'..'z'&lt;br /&gt;
  if(x=='a'){&lt;br /&gt;
    asend(&amp;lt;NULL,NULL&amp;gt;,'b');&lt;br /&gt;
    asend(&amp;lt;NULL,NULL&amp;gt;,'b');&lt;br /&gt;
  }&lt;br /&gt;
  While True:&lt;br /&gt;
    &amp;lt;c,string&amp;gt;=arecv(x-1+26%26);&lt;br /&gt;
    if(string==NULL):&lt;br /&gt;
      &amp;lt;c,string&amp;gt;=arecv(*);&lt;br /&gt;
      if(string!=NULL):&lt;br /&gt;
        &amp;lt;c,string&amp;gt;=arecv(x-1+26%26);&lt;br /&gt;
&lt;br /&gt;
    if(string!=NULL):&lt;br /&gt;
      if(string[0]==x):&lt;br /&gt;
        print(string[0]);&lt;br /&gt;
        if(string.len()&amp;gt;1):&lt;br /&gt;
          aasend(&amp;lt;NULL,string[1:]&amp;gt;,(x+1)%26);&lt;br /&gt;
        else:&lt;br /&gt;
          aasend(&amp;lt;NULL,NULL&amp;gt;,(x+1)%26);&lt;br /&gt;
          aasend(&amp;lt;NULL,NULL&amp;gt;,(x+1)%26);&lt;br /&gt;
      else:&lt;br /&gt;
          aasend(&amp;lt;NULL,string&amp;gt;,(x+1)%26);&lt;br /&gt;
    else:&lt;br /&gt;
      aasend(&amp;lt;NULL,NULL&amp;gt;,(x+1)%26);&lt;br /&gt;
      aasend(&amp;lt;NULL,NULL&amp;gt;,(x+1)%26);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Proposta c2 ===&lt;br /&gt;
* Proposto [[User:Flecart|Flecart]] ([[User talk:Flecart|talk]]) 11:31, 18 January 2023 (CET)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
proc[a]:&lt;br /&gt;
	bool occupied = false;&lt;br /&gt;
	queue&amp;lt;string&amp;gt; s;&lt;br /&gt;
	&lt;br /&gt;
	while True {&lt;br /&gt;
		(c, string) = arecv(*);&lt;br /&gt;
		&lt;br /&gt;
		if (c == NONE) {&lt;br /&gt;
			if (occupied) {&lt;br /&gt;
				s.enqueue(string);&lt;br /&gt;
			} else {&lt;br /&gt;
				if (string.len() &amp;lt; 1)&lt;br /&gt;
					continue;&lt;br /&gt;
			&lt;br /&gt;
				occupied = true;&lt;br /&gt;
				asend(string[0], (MIDDLE, string));&lt;br /&gt;
			}&lt;br /&gt;
		} else if (c == END) {&lt;br /&gt;
			if (s.size() &amp;gt; 0) {&lt;br /&gt;
				string ss = s.dequeue();&lt;br /&gt;
				asend(string[0], (MIDLLE, string));&lt;br /&gt;
			} else {&lt;br /&gt;
				occupied = false;&lt;br /&gt;
			}&lt;br /&gt;
		} else {&lt;br /&gt;
			print(x);&lt;br /&gt;
			if (len(string) &amp;gt; 1) &lt;br /&gt;
				asend(proc[string[0]], (MIDDLE, string[1:]));&lt;br /&gt;
			else:&lt;br /&gt;
				asend(proc[a], (END, &amp;quot;&amp;quot;));&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
		&lt;br /&gt;
proc[x]: x = 'b', ... 'z';&lt;br /&gt;
	while True {&lt;br /&gt;
		(c, string) = arecv(*);&lt;br /&gt;
		if (c == NONE) {&lt;br /&gt;
			asend(proc['a'], (NONE, string));&lt;br /&gt;
		} else {  // potrà essere solo MIDDLE&lt;br /&gt;
			print(x);&lt;br /&gt;
			if (len(string) &amp;gt; 1) &lt;br /&gt;
				asend(proc[string[0]], (MIDDLE, string[1:]));&lt;br /&gt;
			else:&lt;br /&gt;
				asend(proc[a], (END, &amp;quot;&amp;quot;));&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Esame 12/02/2018 =&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2018.02.12.tot.pdf 2018.02.12.tot.pdf]&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.1 (da controllare) ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
monitor bridge:&lt;br /&gt;
&lt;br /&gt;
    int ncar&lt;br /&gt;
    bool boat_on_0&lt;br /&gt;
    bool boat_on_1       // per semplicità, quando nel codice si trova boat_on_(direction) oppure isBoat(direction)(),&lt;br /&gt;
                         // si valuta il valore booleano di direction e lo si applica sotto forma di stringa al simbolo&lt;br /&gt;
                         // ad esso adiacente&lt;br /&gt;
    bool is_raised&lt;br /&gt;
    queue waiting_mean   // i valori possibili sono: boat0, boat1 oppure car&lt;br /&gt;
    condition ok2go&lt;br /&gt;
  &lt;br /&gt;
    entry car_enter(direction): &lt;br /&gt;
        if is_raised || ncar == MAXCAR:&lt;br /&gt;
            waiting_mean.enqueue(car)&lt;br /&gt;
            ok2go.wait()&lt;br /&gt;
        is_raised = false&lt;br /&gt;
        ++ncar&lt;br /&gt;
  &lt;br /&gt;
    entry car_exit(direction):&lt;br /&gt;
        --ncar&lt;br /&gt;
        if (waiting_mean.top().isBoat() &amp;amp;&amp;amp; ncar == 0) || waiting_mean.top().isCar():    // isBoat ritorna true se l'oggetto su cui&lt;br /&gt;
            waiting_mean.dequeue()                                                      // è invocata è boat0 oppure boat1&lt;br /&gt;
            ok2go.signal()&lt;br /&gt;
  &lt;br /&gt;
    entry boat_enter(direction):&lt;br /&gt;
        if !is_raised || boat_on_(direction):&lt;br /&gt;
            waiting_mean.enqueue(boat)&lt;br /&gt;
            ok2go.wait()&lt;br /&gt;
        if waiting_mean.top().isBoat(!direction)():&lt;br /&gt;
            waiting_mean.dequeue()&lt;br /&gt;
            ok2go.signal()&lt;br /&gt;
        is_raised = true&lt;br /&gt;
        boat_on_(direction) = true&lt;br /&gt;
  &lt;br /&gt;
    entry boat_exit(direction):&lt;br /&gt;
        boat_on_(direction) = false&lt;br /&gt;
        if !boat_on_(!direction):&lt;br /&gt;
            waiting_mean.dequeue()&lt;br /&gt;
            ok2go.signal()&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.1 ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
monitor bridge  {&lt;br /&gt;
  int carsOnBridge = 0;&lt;br /&gt;
  int shipping[2] = {0, 0}; //navi da entrambe le direzioni&lt;br /&gt;
  int status = NONE; //UP DOWN NONE&lt;br /&gt;
  int last2pass = 0;     //ultimo che ha passato il ponte&lt;br /&gt;
  int waitingC = 0;      //coda delle macchine che aspettano&lt;br /&gt;
  int waitingS[2] = {0,0};  //navi che stanno aspettando&lt;br /&gt;
   &lt;br /&gt;
  condition ok2ship[2]&lt;br /&gt;
  condition ok2drive&lt;br /&gt;
 &lt;br /&gt;
entry car_enter(int direction){&lt;br /&gt;
    if(carsOnBridge &amp;gt;= MAX || status == UP || waitingS[0] + waitingS[1] &amp;gt; 0 ){&lt;br /&gt;
        waitingC++;ok2drive.wait;waitingC--;}&lt;br /&gt;
    status = DOWN;&lt;br /&gt;
    carsOnBridge++&lt;br /&gt;
    if (carsOnBridge &amp;lt; MAX)&lt;br /&gt;
       ok2drive.signal();     //vanno tutte le MAX car che stanno aspettando&lt;br /&gt;
} &lt;br /&gt;
entry car_exit(int direction){&lt;br /&gt;
    carsOnBridge--&lt;br /&gt;
    if (waitingS[0] + waitingS[1] == 0)&lt;br /&gt;
    ok2drive.signal();&lt;br /&gt;
    if(carsOnBridge == 0){&lt;br /&gt;
        ok2ship[0].signal(); ok2ship[1].signal();&lt;br /&gt;
    }&lt;br /&gt;
    if(carsOnBridge + waitingS[0] + waitingS[1] == 0) &lt;br /&gt;
    status = NONE&lt;br /&gt;
}&lt;br /&gt;
 &lt;br /&gt;
entry ship_enter(int direction){&lt;br /&gt;
    if (bridge = DOWN || shipping[direction] != 0 || waitingC &amp;gt; 0)&lt;br /&gt;
    {&lt;br /&gt;
        waitingS[i]++; ok2ship[i].wait(); waitingS[i]--; &lt;br /&gt;
    }&lt;br /&gt;
    isBridgeUp = false;&lt;br /&gt;
    shipping[i] = 1;&lt;br /&gt;
 &lt;br /&gt;
entry ship_exit(int direction){&lt;br /&gt;
      shipping[i] = 0;&lt;br /&gt;
      if (waitingC == 0)&lt;br /&gt;
          ok2ship[i].signal()&lt;br /&gt;
      else if(shipping[1-i] == 0)&lt;br /&gt;
          ok2drive.signal();&lt;br /&gt;
      if(carsOnBridge + waitingS[0] + waitingS[1] == 0) &lt;br /&gt;
      status = NONE&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.1 (da controllare) ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
monitor bridge {&lt;br /&gt;
&lt;br /&gt;
  UP=0;&lt;br /&gt;
  DOWN=1;&lt;br /&gt;
  bridgeis = DOWN;&lt;br /&gt;
&lt;br /&gt;
  bool carAreExiting = false;&lt;br /&gt;
&lt;br /&gt;
  condition ok2drive;&lt;br /&gt;
  condition ok2barca[2];&lt;br /&gt;
&lt;br /&gt;
  waitingCar = 0;&lt;br /&gt;
  carOnBridge = 0;&lt;br /&gt;
&lt;br /&gt;
  boatWaiting[2] = {0,0};&lt;br /&gt;
  boatIsPassing[2] = {false,false}&lt;br /&gt;
&lt;br /&gt;
  entry car_enter(direction) {&lt;br /&gt;
&lt;br /&gt;
    if (bridgeis == DOWN)&lt;br /&gt;
      if(carOnBridge == MAXCAR)&lt;br /&gt;
        waitingCar++;&lt;br /&gt;
        ok2drive.wait();&lt;br /&gt;
        waitingCar--;&lt;br /&gt;
      else if (carAreExiting)&lt;br /&gt;
        waitingCar++;&lt;br /&gt;
        ok2drive.wait();&lt;br /&gt;
        waitingCar--;&lt;br /&gt;
    else &lt;br /&gt;
      if (boatIsPassing[0] || boatIsPassing[1])&lt;br /&gt;
        waitingCar++;&lt;br /&gt;
        ok2drive.wait();&lt;br /&gt;
        waitingCar--;&lt;br /&gt;
        bridgeis = DOWN;&lt;br /&gt;
&lt;br /&gt;
    carOnBridge++;&lt;br /&gt;
    carAreExiting = false;&lt;br /&gt;
    if(carOnBridge &amp;lt; MAXCAR &amp;amp;&amp;amp; !carAreExiting) &lt;br /&gt;
      ok2drive.signal();&lt;br /&gt;
      &lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  entry car_exit(direction) {&lt;br /&gt;
&lt;br /&gt;
    carOnBridge--;&lt;br /&gt;
    carAreExiting = true;&lt;br /&gt;
&lt;br /&gt;
    if(carOnBridge == 0)&lt;br /&gt;
      carAreExiting = false;&lt;br /&gt;
      if(boatWaiting[0] &amp;gt; 0)&lt;br /&gt;
        bridgeis = UP;&lt;br /&gt;
        ok2barca[0].signal();&lt;br /&gt;
      else if (boatWaiting[1] &amp;gt; 0)&lt;br /&gt;
        bridgeis = UP;&lt;br /&gt;
        ok2barca[1].signal();&lt;br /&gt;
      else &lt;br /&gt;
        ok2drive.signal();&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  entry boat_enter(direction) {&lt;br /&gt;
&lt;br /&gt;
    if (bridgeis == UP)&lt;br /&gt;
    | if (boatIsPassing[direction] == true)&lt;br /&gt;
    | |  boatWaiting[direction]++;&lt;br /&gt;
    | |  ok2barca.wait();&lt;br /&gt;
    | |  boatWaiting[direction]--;&lt;br /&gt;
    else &lt;br /&gt;
    | if (carOnBridge &amp;gt; 0)&lt;br /&gt;
    | | boatWaiting[direction]++;&lt;br /&gt;
    | | ok2barca.wait();&lt;br /&gt;
    | | boatWaiting[direction]--;&lt;br /&gt;
    | | bridgeis = UP;&lt;br /&gt;
&lt;br /&gt;
    boatIsPassing[direction] = true;&lt;br /&gt;
&lt;br /&gt;
    if(boatIsPassing[1-direction] == false &amp;amp;&amp;amp; boatWaiting[1-direction] &amp;gt; 0)&lt;br /&gt;
      ok2barca[1-direction].signal();&lt;br /&gt;
    &lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  entry boat_exit(direction) {&lt;br /&gt;
&lt;br /&gt;
    boatIsPassing[direction] = false;&lt;br /&gt;
&lt;br /&gt;
    if (boatIsPassing[1-direction] == false)&lt;br /&gt;
      if (waitingCar &amp;gt; 0)&lt;br /&gt;
        bridgeis = DOWN;&lt;br /&gt;
        ok2drive.signal();&lt;br /&gt;
    else&lt;br /&gt;
        if (waitingCar == 0)&lt;br /&gt;
          ok2barca[direction].signal();&lt;br /&gt;
          &lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.1 (sbagliato) ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
monitor bridge&lt;br /&gt;
  condition ok2passCar;&lt;br /&gt;
  condition ok2passBoat;&lt;br /&gt;
  condition ok2up;&lt;br /&gt;
  condition ok2down;&lt;br /&gt;
  int carOnBridge[2] = 0; //2 sensi di marcia&lt;br /&gt;
  int boatUnderBridge[2] = 0;&lt;br /&gt;
  boolean bridge_down = false; //vuol dire che il ponte parte alzato, true ponte abbassato&lt;br /&gt;
  &lt;br /&gt;
  procedure entry car_enter(direction){&lt;br /&gt;
      if(bridge_down &amp;amp;&amp;amp; carOnBridge[direction] &amp;lt; MAXCAR){&lt;br /&gt;
        carOnBridge[direction]++;&lt;br /&gt;
        ok2passCar.signal();&lt;br /&gt;
      }else if (bridge_down &amp;amp;&amp;amp; boatUnderBridge[0] == 0 &amp;amp;&amp;amp; boatUnderBridge[1] == 0){&lt;br /&gt;
        //se non ci sono navi in transito e arriva una macchina abbassa ponte&lt;br /&gt;
        ok2down.signal();&lt;br /&gt;
        ok2passCar.signal();&lt;br /&gt;
        ok2passBoat.wait();&lt;br /&gt;
      }else{&lt;br /&gt;
        ok2passCar.wait();&lt;br /&gt;
      }&lt;br /&gt;
  }     &lt;br /&gt;
        &lt;br /&gt;
  procedure entry car_exit(direction){&lt;br /&gt;
      carOnBridge[direction]--;&lt;br /&gt;
      if(carOnBridge[0] == 0 &amp;amp;&amp;amp; carOnBridge[1] == 0){&lt;br /&gt;
        bridge_down = false;&lt;br /&gt;
        ok2up.signal();&lt;br /&gt;
      }else{&lt;br /&gt;
        ok2up.wait();&lt;br /&gt;
      }&lt;br /&gt;
  }&lt;br /&gt;
      &lt;br /&gt;
  procedure entry boat_enter(direction){&lt;br /&gt;
      if(!bridge_down &amp;amp;&amp;amp; boatUnderBridge[direction] &amp;lt; 1){&lt;br /&gt;
        boatUnderBridge[direction]++;&lt;br /&gt;
        ok2passBoat.signal();&lt;br /&gt;
      }else if(!bridge_down &amp;amp;&amp;amp; carOnBridge[0] == 0 &amp;amp;&amp;amp; carOnBridge[1] == 0){&lt;br /&gt;
        ok2up.signal();&lt;br /&gt;
        ok2passBoat.signal();&lt;br /&gt;
        ok2passCar.wait();&lt;br /&gt;
      }else {&lt;br /&gt;
        ok2passBoat.wait();&lt;br /&gt;
      }&lt;br /&gt;
  }&lt;br /&gt;
      &lt;br /&gt;
  procedure entry boat_exit(direction){  &lt;br /&gt;
      boatUnderBridge[direction]--;&lt;br /&gt;
      if(boatUnderBridge[0] == 0 &amp;amp;&amp;amp; boatUnderBridge[1] == 0){&lt;br /&gt;
        bridge_down = true;&lt;br /&gt;
        ok2down.signal();&lt;br /&gt;
      }else{&lt;br /&gt;
        ok2down.wait();&lt;br /&gt;
      }&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.1 2o (sbagliato) ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define car 1&lt;br /&gt;
#define ship 2 &lt;br /&gt;
#define fromDX 1&lt;br /&gt;
#define fromSX 0&lt;br /&gt;
&lt;br /&gt;
monitor bridge  {&lt;br /&gt;
  int carsOnBridge = 0;&lt;br /&gt;
  int shippingDX = 0; //nave che sta passando dal lato destro&lt;br /&gt;
  int shippingSX = 0; //nave che sta passando dal lato sinistro&lt;br /&gt;
  bool isBridgeUp = false;&lt;br /&gt;
  int last2pass = 0;     //ultimo che ha passato il ponte&lt;br /&gt;
  int waitingS = 0;  //navi che stanno aspettando&lt;br /&gt;
  int waitingC = 0 ; //auto che stanno aspettando&lt;br /&gt;
  &lt;br /&gt;
  condition ok2ship&lt;br /&gt;
  condition ok2drive&lt;br /&gt;
&lt;br /&gt;
entry car_enter(int direction){&lt;br /&gt;
    //un auto si ferma se il numero di auto sul ponte è massimo&lt;br /&gt;
    //e se l'ultima a passare è stata un auto mentre ci sono navi in attesa&lt;br /&gt;
    if(carsOnBridge == MAX || isBridgeUp || (last2pass==car &amp;amp;&amp;amp; waitingS &amp;gt; 0) ){&lt;br /&gt;
        waitingC++;&lt;br /&gt;
        ok2drive.wait;&lt;br /&gt;
    }&lt;br /&gt;
    carsOnBridge++;&lt;br /&gt;
    waitingC--;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
entry car_exit(int direction){&lt;br /&gt;
    carsOnBridge--;&lt;br /&gt;
    last2pass = car;&lt;br /&gt;
    if(carsOnBridge == 0 &amp;amp;&amp;amp; waitingS&amp;gt;0){&lt;br /&gt;
        isBrigdeUp = true;&lt;br /&gt;
        ok2ship.signal;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
entry ship_enter(int direction){&lt;br /&gt;
    //se la barca viene da destra&lt;br /&gt;
    if(direction == fromDX){&lt;br /&gt;
        //si ferma anche quando c'è una nave che sta già attraversando nella sua stessa direzione&lt;br /&gt;
        if (isBridgeup == false || shippingDX || (last2pass==ship &amp;amp;&amp;amp; waitingC &amp;gt; 0) ){&lt;br /&gt;
            waitingS++;&lt;br /&gt;
            ok2ship.wait;&lt;br /&gt;
        }&lt;br /&gt;
        if (waitingS &amp;gt; 0)&lt;br /&gt;
            waitingS--;&lt;br /&gt;
        shippingDX = 1;&lt;br /&gt;
        }&lt;br /&gt;
    //se la barca viene da sinistra&lt;br /&gt;
    else if(direction == fromSX){&lt;br /&gt;
        if (isBridgeup == false || shippingSX || ( (last2pass==ship &amp;amp;&amp;amp; waitingC &amp;gt; 0))){&lt;br /&gt;
        waitingS++;&lt;br /&gt;
        ok2ship.wait;&lt;br /&gt;
        }&lt;br /&gt;
        if (waitingS &amp;gt; 0)&lt;br /&gt;
            waitingS--;        &lt;br /&gt;
        shippingSX = 1;&lt;br /&gt;
    &lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
entry ship_exit(int direction){&lt;br /&gt;
        if(direction == fromDX)&lt;br /&gt;
            shippingDX = 0;&lt;br /&gt;
        else if (direction == fromSX)&lt;br /&gt;
            shippingSX = 0;&lt;br /&gt;
        last2pass = ship;&lt;br /&gt;
        if(shippingDX == 0 &amp;amp;&amp;amp; shippingSX == 0 &amp;amp;&amp;amp; waitingC)&lt;br /&gt;
            isBrigdeUp == false;&lt;br /&gt;
            ok2drive.signal;&lt;br /&gt;
        else if(shippingDX == 0 &amp;amp;&amp;amp; shippingSX == 0 &amp;amp;&amp;amp; waitingS &amp;gt; 0)&lt;br /&gt;
            ok2ship.signal;    &lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.2 (sbagliato) ===&lt;br /&gt;
&lt;br /&gt;
# (Ri)Controllato dall'utente [[User:Acsor|Acsor]] ([[User talk:Acsor|talk]]) in data 26/08/2020&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
list printed_msg;  # questa è una variabile condivisa che ai fini dell'esercizio non si può utilizzare (message passing)&lt;br /&gt;
&lt;br /&gt;
process server[i]:&lt;br /&gt;
  while true:&lt;br /&gt;
    &amp;lt;msg, pid&amp;gt; = arecv(*)&lt;br /&gt;
&lt;br /&gt;
    if printed_msg.length == 0 or &amp;lt;msg, pid&amp;gt; is not in printed_msg:&lt;br /&gt;
      printed_msg.append(&amp;lt;msg,id&amp;gt;)&lt;br /&gt;
      print(msg)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.2 (da controllare) ===&lt;br /&gt;
Nello svolgimento seguente, receiver incapsula l'ambiente privato del processo; _peers rappresenta il vettore di processi &amp;quot;fratelli&amp;quot; ai quali può essere chiesto di stampare un messaggio, mentre _printed contiene l'hash di tutti i messaggi stampati dal processo locale. Si suppone che istanze della classe receiver possano essere passate come parametro ad areceive() ed asend() (non implementate).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
class receiver:&lt;br /&gt;
    def __init__(self, peers):&lt;br /&gt;
        &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
        :param peers: list of processes this process communicates with.&lt;br /&gt;
        &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
        self._peers = tuple(peers)&lt;br /&gt;
        self._printed = list()&lt;br /&gt;
    &lt;br /&gt;
    def run(self):&lt;br /&gt;
        while True:&lt;br /&gt;
            process, message = areceive(ANY)&lt;br /&gt;
&lt;br /&gt;
            if process in self._peers:&lt;br /&gt;
                self._reply_query(process, message)&lt;br /&gt;
            else:&lt;br /&gt;
                self._print(process, message)&lt;br /&gt;
&lt;br /&gt;
    def _print(self, sender, message):&lt;br /&gt;
        h = hash(message.text)&lt;br /&gt;
&lt;br /&gt;
        if h not in self._printed and not self._printed_from_peers(message):&lt;br /&gt;
            self._printed.append(h)&lt;br /&gt;
            print(message.text)&lt;br /&gt;
&lt;br /&gt;
    def _reply_query(self, sender, h):&lt;br /&gt;
        &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
        Invoked when the current process receive a &amp;quot;query&amp;quot; from a peer process.&lt;br /&gt;
        `h` contains the hash of a message which may or may have not been&lt;br /&gt;
        sent from this process; if it was sent, the reply is `Yes`, otherwise `No`.&lt;br /&gt;
        &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
        reply = &amp;quot;Yes&amp;quot; if int(h) in self._printed else &amp;quot;No&amp;quot;&lt;br /&gt;
        asend(sender, reply)&lt;br /&gt;
&lt;br /&gt;
    def _printed_from_peers(self, message):&lt;br /&gt;
        &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
        :return: `True` if this message has already been printed from any of the&lt;br /&gt;
        peer processes, `False` otherwise.&lt;br /&gt;
        &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
        h = hash(message)&lt;br /&gt;
&lt;br /&gt;
        for p in self._peers:&lt;br /&gt;
            asend(p, str(h))&lt;br /&gt;
&lt;br /&gt;
        for p in self._peers:&lt;br /&gt;
            _, reply = areceive(p)&lt;br /&gt;
&lt;br /&gt;
            if reply.text == &amp;quot;Yes&amp;quot;:&lt;br /&gt;
                return True&lt;br /&gt;
            else if reply.text != &amp;quot;No&amp;quot;:&lt;br /&gt;
                # If the response is neither &amp;quot;Yes&amp;quot; nor &amp;quot;No&amp;quot;, then we have got a query&lt;br /&gt;
                self._reply_query(p, reply)&lt;br /&gt;
&lt;br /&gt;
        return False&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Esercizio g.1 (da controllare) ===&lt;br /&gt;
Sulla base dei valori in entrata, è possibile costruire le matrici Allocation (q.tà di risorse allocate per processo e per tipo), Need (q.tà di risorse che ogni processo potrebbe ancora chiedere) e il vettore Available (num. di risorse correntemente disponibili).&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;float: left&amp;quot;&lt;br /&gt;
! colspan=3 | Allocation&lt;br /&gt;
|-&lt;br /&gt;
   !   !! A !! B&lt;br /&gt;
|-&lt;br /&gt;
   | p1 || 4 || 5&lt;br /&gt;
|-&lt;br /&gt;
   | p2 || 3 || 3&lt;br /&gt;
|-&lt;br /&gt;
   | p3 || 2 || 4&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;float: left; margin-left: 1em&amp;quot;&lt;br /&gt;
! colspan=3 | Need&lt;br /&gt;
|-&lt;br /&gt;
   !    !! A !! B&lt;br /&gt;
|-&lt;br /&gt;
   | p1 || 6 || 8&lt;br /&gt;
|-&lt;br /&gt;
   | p2 || 6 || 3&lt;br /&gt;
|-&lt;br /&gt;
   | p3 || 6 || 8&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;float: left; margin-left: 1em&amp;quot;&lt;br /&gt;
! colspan=2 | Available&lt;br /&gt;
|-&lt;br /&gt;
   ! A !! B&lt;br /&gt;
|-&lt;br /&gt;
   | x || y&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nel caso delle risorse di tipo A, deve aversi x &amp;gt;= 6 in quanto un processo dovrà essere selezionato come primo nella permutazione dell'algoritmo del banchiere multivaluta, e tutti quelli correnti hanno lo stesso valore Need(i)(1); per ciò che riguarda le risorse di tipo B, possiamo ragionare per esaustione&lt;br /&gt;
&lt;br /&gt;
* Se il primo processo della permutazione è p1, allora y &amp;gt;= 8 (con questo valore posso soddisfare la richiesta di p1 e in seguito tutte le altre)&lt;br /&gt;
* Se il primo processo della permutazione è p2, allora y &amp;gt;= 5: con questo valore è possibile soddisfare la richiesta di p2; una volta che esso avrà finito, restituirà 3 unità della risorsa B, che permetteranno di soddisfare sia le richieste di A sia quelle di C&lt;br /&gt;
* Se il primo processo della permutazione è p3, allora y &amp;gt;= 8 (ragionamento analogo come per p1)&lt;br /&gt;
&lt;br /&gt;
Volendo scegliere il minimo, y &amp;gt;= 5, ed in conclusione (x, y) &amp;gt;= (6, 5).&lt;br /&gt;
&lt;br /&gt;
''Svolgimento basato in parte sull'approccio di Operating System Concepts di Silberschatz. et al, 9th edition, cap. 7.''&lt;br /&gt;
&lt;br /&gt;
=== Esercizio g.2 (da controllare) ===&lt;br /&gt;
# Può accadere che il sistema torni in uno stato di safety o che invece porti a deadlock. Diversamente uno stato di safety non può portare direttamente ad uno stato di deadlock, ma solo ad uno di non-safety.&lt;br /&gt;
# Selezionare uno o più tra i processi attivi e sospenderli, salvando il loro stato su memoria secondaria operando delle operazioni di swap-out, finché l'insieme dei frame nella memoria centrale non è in grado di soddisfare tutti i processi rimasti attivi.&lt;br /&gt;
# La scelta è determinata perlopiù dal fattore costo. Con un sistema RAID 1 è possibile ripristinare un disco guasto molto brevemente, in quanto le operazioni coinvolte prevedono una semplice ricopiatura dal disco di backup; con un sistema RAID 5 il ripristino del disco guasto deve coinvolgere tutti i dischi dell'intero array, e ciò può richiedere anche ore per dischi di grandi dimensioni. D'altra parte RAID 1 è più costoso (con n dischi, posso memorizzare tanta informazione quanto potrei con n / 2 dischi) rispetto a RAID 5 dove, tra gli n dischi, complessivamente soltanto uno è destinato alle informazioni di ridondanza.&lt;br /&gt;
# ''Completare.''&lt;/div&gt;</summary>
		<author><name>LiberaL</name></author>
	</entry>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=Prove_scritte_2018&amp;diff=2974</id>
		<title>Prove scritte 2018</title>
		<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php?title=Prove_scritte_2018&amp;diff=2974"/>
		<updated>2023-05-12T14:41:18Z</updated>

		<summary type="html">&lt;p&gt;LiberaL: /* Soluzione &amp;quot;schiacciasassi&amp;quot; */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Esame 19/09/2018 =&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2018.09.19.tot.pdf Testo dell'esame].&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.2 (da controllare) ===&lt;br /&gt;
&lt;br /&gt;
* Controllato dall'utente ? in data ?&lt;br /&gt;
* ...&lt;br /&gt;
&lt;br /&gt;
Nello pseudocodice seguente, il termine this fa riferimento al processo corrente, mentre ANY ad uno qualunque.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
stack&amp;lt;message&amp;gt; messages;&lt;br /&gt;
&lt;br /&gt;
void lifo_send(string m, process dest) {&lt;br /&gt;
	do {&lt;br /&gt;
		asend(m, dest);&lt;br /&gt;
	} while (areceive(dest).text != &amp;quot;ACK&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
message lifo_receive(process source) {&lt;br /&gt;
	if (source != ANY) {&lt;br /&gt;
		message m = areceive(source);&lt;br /&gt;
&lt;br /&gt;
		asend(&amp;quot;ACK&amp;quot;, source);&lt;br /&gt;
&lt;br /&gt;
		return m;&lt;br /&gt;
	} else {&lt;br /&gt;
		message m;&lt;br /&gt;
&lt;br /&gt;
		asend(&amp;quot;END&amp;quot;, this);&lt;br /&gt;
		m = areceive(ANY);&lt;br /&gt;
&lt;br /&gt;
		while (m.text != &amp;quot;END&amp;quot; || m.sender != this) {&lt;br /&gt;
			messages.push(m);&lt;br /&gt;
			asend(&amp;quot;ACK&amp;quot;, m.sender);&lt;br /&gt;
&lt;br /&gt;
			m = areceive(ANY);&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
                /* Bisogna tenere conto dei casi in cui lifo_receive() viene invocata quando nessun&lt;br /&gt;
                 * messaggio è stato ancora spedito da altri processi. In tal caso si attende il&lt;br /&gt;
                 * il primo e lo si restituisce.&lt;br /&gt;
                 */&lt;br /&gt;
		if (messages.empty()) {&lt;br /&gt;
			m = areceive(ANY);&lt;br /&gt;
			asend(&amp;quot;ACK&amp;quot;, m.sender);&lt;br /&gt;
&lt;br /&gt;
			return m;&lt;br /&gt;
		} else {&lt;br /&gt;
			return messages.pop();&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Esame 17/07/2018 =&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2018.07.17.tot.pdf 2018.07.17.tot.pdf]&lt;br /&gt;
== Esercizio c.1 ==&lt;br /&gt;
A Bruxelles c'è un locale chiamato Delirium Café. Alla vigilia del FOSDEM tutti gli anni gli sviluppatori europei di&lt;br /&gt;
software libero si ritrovano a bere birra (il locale è nel guinnes dei primati con più di duemila tipi di birra). Il prossimo appuntamento è&lt;br /&gt;
fissato per il 1 febbraio 2019 ore 20. Numerosi sono i tipi di birra alla spina. I baristi (tanti) prendono gli ordini (es. mezza pinta, 1 o 2&lt;br /&gt;
pinte) e riempiono i bicchieri. Quando un fusto e' vuoto avvertono i magazzinieri che prendono un nuovo fusto che contiene più di&lt;br /&gt;
cento pinte e lo sostituiscono, a questo punto il barista può completare il riempimento del bicchiere.&lt;br /&gt;
La vita di un barista del Delirium è:&lt;br /&gt;
 while True:&lt;br /&gt;
   (type, quantity) = get_order()&lt;br /&gt;
   delirium.pour(type, quantity)&lt;br /&gt;
La vita di un Magazziniere è:&lt;br /&gt;
 while True:&lt;br /&gt;
   type = delirium.isempty()&lt;br /&gt;
   capacity = change_keg(type)&lt;br /&gt;
   delirium.loaded(type, capacity)&lt;br /&gt;
&lt;br /&gt;
Attenzione: se il fusto (keg) è quasi vuoto il barista dovrà riempire parzialmente il bicchiere, occorrerà attivare il magazziniere che&lt;br /&gt;
cambierà il fusto e poi il barista riempirà il bicchiere fino alla quantità richiesta dal cliente. Mentre un barista sta attendendo il&lt;br /&gt;
cambiamento di un fusto altri baristi potrebbero ricevere ordini per lo stesso tipo di birra: gestire opportunamente questo caso.&lt;br /&gt;
Scrivere il monitor Delirium.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Proposta di soluzione 1 === &lt;br /&gt;
* ERRORE: Secondo me c'è un leggero errore nella parte di load, nel caso in cui la nuova pinta non riesca a soddisfare completamente la richiesta ossia quando vale availableBeer[t] &amp;lt;= requests[t].head(), allora non lo risveglio nemmeno, invece dovrei risvegliare il pour, fargli versare quanto può, e richiedere una altra pinta, perché questo era un requisito del problema. [[User:Flecart|Flecart]] ([[User talk:Flecart|talk]]) 12:00, 15 January 2023 (CET)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
/* Monitor Delirum: */&lt;br /&gt;
&lt;br /&gt;
// Condition: Ok2Load;&lt;br /&gt;
// Condition: Ok2Pour[]; // Un elemento per Type&lt;br /&gt;
int availableBeer[]; // Un elemento per Type &lt;br /&gt;
Queue requests[]; // Un elemento per Type&lt;br /&gt;
Queue pendingRequests;&lt;br /&gt;
&lt;br /&gt;
Procedure entry: void Pour(Type t, Quantity c)&lt;br /&gt;
{&lt;br /&gt;
    if (c &amp;gt; availableBeer[t]) // Richiesta maggiore della birra disponibile&lt;br /&gt;
    {&lt;br /&gt;
        c -= availableBeer[t];&lt;br /&gt;
        availableBeer[t] = 0;              &lt;br /&gt;
        requests[t].Enqueue(c);&lt;br /&gt;
        if (requests[t].Length == 1) // Risveglio un magazziniere solo se è la prima richiesta di questo tipo di birra&lt;br /&gt;
        {&lt;br /&gt;
            pendingRequests.Enqueue(t);&lt;br /&gt;
            Ok2Load().Signal();&lt;br /&gt;
        }&lt;br /&gt;
        Ok2Pour[t].Wait();&lt;br /&gt;
        requests[t].Dequeue(); // Quando ho ottenuto la birra che voglio, elimino la mia richiesta&lt;br /&gt;
    }&lt;br /&gt;
    availableBeer[t] -= c;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: Type isEmpty()&lt;br /&gt;
{&lt;br /&gt;
    if (pendingRequests.Length == 0)&lt;br /&gt;
    {&lt;br /&gt;
        Ok2Load.Wait();&lt;br /&gt;
    }&lt;br /&gt;
    return pendingRequests.Dequeue();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: Loaded(Type t, Capacity c)&lt;br /&gt;
{&lt;br /&gt;
    availableBeer[t] += c;&lt;br /&gt;
    while (requests[t].Length &amp;gt; 0 &amp;amp;&amp;amp; availableBeer[t] &amp;gt; requests[t].head())&lt;br /&gt;
    {&lt;br /&gt;
        Ok2Pour[t].Signal();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (requests[t].Length &amp;gt; 0) // serve per evitare che a causa di un magazziniere lento si accodino cosi tante richieste che mentre si sta caricando si svuota subito il fusto&lt;br /&gt;
    {&lt;br /&gt;
        pendingRequests.Enqueue(t);&lt;br /&gt;
        Ok2Load.Signal();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Proposta di soluzione 2 ===&lt;br /&gt;
* Proposto da [[User:Flecart|Flecart]] ([[User talk:Flecart|talk]]) 13:41, 15 January 2023 (CET)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
extern int MAX_TYPE;&lt;br /&gt;
class Delirium {&lt;br /&gt;
    int keg[MAX_TYPE];      // qnty fusto attuale&lt;br /&gt;
    int orders[MAX_TYPE];   // qnty richiesta&lt;br /&gt;
    bool worked[MAX_TYPE];  // 1 se magazziniere sta lavorando su questo.&lt;br /&gt;
&lt;br /&gt;
    condition type_wait[MAX_TYPE];&lt;br /&gt;
    int num_wait[MAX_TYPE];&lt;br /&gt;
&lt;br /&gt;
    queue&amp;lt;int&amp;gt; empty_type;&lt;br /&gt;
    condition is_empty;&lt;br /&gt;
&lt;br /&gt;
    entry pour(type, quantity) {&lt;br /&gt;
        while (keg[type] &amp;lt; quantity) {&lt;br /&gt;
            quantity -= keg[type];&lt;br /&gt;
            keg[type] = 0;&lt;br /&gt;
            if (!empty_type.find(type) &amp;amp;&amp;amp; !worked[type]) {&lt;br /&gt;
                empty_type.enqueue(type);&lt;br /&gt;
                is_empty.signal();&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            num_wait[type]++;&lt;br /&gt;
            type_wait[type].wait();&lt;br /&gt;
            num_wait[type]--;&lt;br /&gt;
        }&lt;br /&gt;
        keg[type] -= quantity;&lt;br /&gt;
        quantity = 0;  // questo è inutile, ma concettualmente è corretto, l'ordine è completato.&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    entry loaded(type, capacity) {&lt;br /&gt;
        keg[type] += capacity;&lt;br /&gt;
        worked[type] = false;&lt;br /&gt;
&lt;br /&gt;
        for (int i = num_wait[type]; i &amp;gt; 0; i--) {&lt;br /&gt;
            type_wait[type].signal();&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // si suppone che un singolo tipo di fusto è lavorabile da un solo magazziniere alla volta.&lt;br /&gt;
    // worked impedisce di avere nella coda un fusto su cuisi sta già lavorando.&lt;br /&gt;
    entry isempty() {&lt;br /&gt;
        if (empty_type.size() &amp;lt;= 0) {&lt;br /&gt;
            is_emtpy.wait();&lt;br /&gt;
        }&lt;br /&gt;
        int type = emtpy_type.dequeue();&lt;br /&gt;
        worked[type] = true;&lt;br /&gt;
        return type;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Esercizio c.2 ==&lt;br /&gt;
&lt;br /&gt;
=== Proposta di soluzione 1 ===&lt;br /&gt;
* Visto e corretto dall'utente [[User:Acsor|Acsor]] in data 23/08/2020&lt;br /&gt;
* Visto e corretto dall'utente ? in data ?&lt;br /&gt;
* Visto, ritenuto corretto [[User:Flecart|Flecart]] ([[User talk:Flecart|talk]]) 09:27, 15 January 2023 (CET)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
class LIFOBuffer {&lt;br /&gt;
	stack&amp;lt;T&amp;gt; s;&lt;br /&gt;
	semaphore mutex(1); // mutua esclusione&lt;br /&gt;
	semaphore ok2consume(0);&lt;br /&gt;
&lt;br /&gt;
	void push (T value) {&lt;br /&gt;
		mutex.P();&lt;br /&gt;
		s.push(value);&lt;br /&gt;
                // (1)&lt;br /&gt;
		mutex.V()&lt;br /&gt;
&lt;br /&gt;
		ok2consume.V()  // Curiosità: che succede se spostiamo quest'istruzione in (1)? Edit: funziona lo stesso, solo che aggiorni il valore del semaforo prima di uscire dalla mutex.&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	T pop () {&lt;br /&gt;
		T value;&lt;br /&gt;
&lt;br /&gt;
		ok2consume.P();&lt;br /&gt;
		mutex.P();&lt;br /&gt;
		value = s.pop();&lt;br /&gt;
		mutex.V();&lt;br /&gt;
&lt;br /&gt;
		return value;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Proposta di soluzione 2 ===&lt;br /&gt;
Proposto da [[User:Flecart|Flecart]] ([[User talk:Flecart|talk]]) 09:27, 15 January 2023 (CET)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
class lifobuf {&lt;br /&gt;
	semaphore mutex(1);&lt;br /&gt;
	stack&amp;lt;int&amp;gt; values;	// empty initialized&lt;br /&gt;
	stack&amp;lt;semaphore&amp;gt; waiting;	&lt;br /&gt;
&lt;br /&gt;
	push(int value) {&lt;br /&gt;
		mutex.P();&lt;br /&gt;
		values.push(value);&lt;br /&gt;
		if (waiting.size() &amp;gt; 0) {&lt;br /&gt;
			semaphore s = waiting.pop();&lt;br /&gt;
			s.V();&lt;br /&gt;
			return;&lt;br /&gt;
		}&lt;br /&gt;
			&lt;br /&gt;
		mutex.V();	&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	pop() {&lt;br /&gt;
		int ret_val;&lt;br /&gt;
		mutex.P();&lt;br /&gt;
		if (values.size() &amp;lt;= 0) {&lt;br /&gt;
			semaphore s = new semaphore(0);&lt;br /&gt;
			waiting.push(s);&lt;br /&gt;
			mutex.V();&lt;br /&gt;
			s.P();&lt;br /&gt;
			free(s);&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		ret_val = values.pop();&lt;br /&gt;
		mutex.V();	&lt;br /&gt;
&lt;br /&gt;
		return ret_val;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Esercizio g.1 ==&lt;br /&gt;
Possiamo notare subito che il sistema ha due processori ed un dispositivo di I/O.&lt;br /&gt;
'''A''' e '''B''' partono insieme al tempo 0.&amp;lt;br&amp;gt;&lt;br /&gt;
'''C''' parte tra il tempo 0 ed il tempo 2 (non possiamo sapere di preciso quando perchè entrambe le CPU sono occupate).&amp;lt;br&amp;gt;&lt;br /&gt;
'''D''' parte tra il tempo 0 ed il tempo 3.&amp;lt;br&amp;gt;&lt;br /&gt;
A questo punto possiamo supporre che tutti e 4 i processi partano in sequenza ('''A''', '''B''', '''C''', '''D''') nello stesso momento, e ognuno prende la prima CPU libera che trova.&amp;lt;br&amp;gt;&lt;br /&gt;
'''A''' lavora per 3ms, poi scade il time slice.&amp;lt;br&amp;gt;&lt;br /&gt;
Nel frattempo '''B''' lavora per 2ms, poi richiede I/O per 4ms.&amp;lt;br&amp;gt;&lt;br /&gt;
La CPU su cui lavora '''B''' quindi si libera, e si manda in esecuzione il processo '''C'''.&amp;lt;br&amp;gt;&lt;br /&gt;
Scaduto il time slice per '''A''', si da il controllo ad un nuovo processo. '''B''' è occupato con I/O, '''C''' sta già lavorando, quindi è il turno di '''D'''.&amp;lt;br&amp;gt;&lt;br /&gt;
'''C''' lavora per 3ms, poi richiede I/O per 3ms, che però è occupato da '''B''', quindi si mette in coda per utilizzarlo.&amp;lt;br&amp;gt;&lt;br /&gt;
La CPU su cui lavorava '''C''' si libera ed il controllo torna ad '''A''', che doveva lavorare ancora per 2ms prima di chiedere il controllo di I/O, quindi lavora e si mette in coda dietro a '''C'''.&amp;lt;br&amp;gt;&lt;br /&gt;
Tornando a '''D''', questo lavora per 3ms prima che scada il time slice. Anche '''B''' ha finito il lavoro e ha bisogno di una CPU.&amp;lt;br&amp;gt;&lt;br /&gt;
In questo momento sia '''D''' che '''B''' sono nella coda dei processi in stato ready, ma dal diagramma possiamo notare che il controllo torna a '''D'''.&amp;lt;br&amp;gt;&lt;br /&gt;
La CPU ha scelto a caso un processo tra i due, perchè arrivati a questo punto possiamo supporre che lo scheduler sia Round-Robin.&amp;lt;br&amp;gt;&lt;br /&gt;
'''B''' prende possesso della prima CPU che si libera, ovvero quella occupata da '''A''', poi lavora per 2ms e termina il suo lavoro.&amp;lt;br&amp;gt;&lt;br /&gt;
Nel momento in cui '''B''' termina il lavoro, scade anche il time slice per '''D''', e '''C''' termina di usare I/O.&amp;lt;br&amp;gt;&lt;br /&gt;
Abbiamo due processi ('''C''' e '''D''') in coda ready. Ma abbiamo anche due CPU libere, perchè '''A''' è in coda per I/O e ci entra appena '''C''' finisce di usarlo.&amp;lt;br&amp;gt;&lt;br /&gt;
Lo scheduler sceglie di mandare '''C''' sul primo processore e '''D''' sul secondo.&amp;lt;br&amp;gt;&lt;br /&gt;
'''A''' nel frattempo, lavora per 4ms con I/O.&amp;lt;br&amp;gt;&lt;br /&gt;
'''C''' lavora per 3ms, poi termina il suo lavoro.&amp;lt;br&amp;gt;&lt;br /&gt;
'''D''' lavora per 3ms, poi scade il time slice. Ci sono due processori liberi, quindi '''D''' riparte subito in esecuzione.&amp;lt;br&amp;gt;&lt;br /&gt;
'''D''' doveva lavorare ancora per 1ms prima di aver bisogno di I/O, quindi finisce e si mette in coda.&amp;lt;br&amp;gt;&lt;br /&gt;
Ma nello stesso momento '''A''' termina di usare I/O, si prende un processore libero e lavora per i suoi ultimi 2ms.&amp;lt;br&amp;gt;&lt;br /&gt;
'''D''' lavora per 1ms con I/O, poi prende il secondo processore libero e lavora per 1ms prima di terminare il suo lavoro.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Il time slice è di 3ms, lo scheduler è di tipo Round-Robin.&amp;lt;br&amp;gt;&lt;br /&gt;
Il dispositivo di I/O è FIFO. L'ordine con cui partono i processi è quello alfabetico.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
A(){&lt;br /&gt;
    compute_a1(); // 5ms&lt;br /&gt;
    io_a(); // 4ms&lt;br /&gt;
    compute_a2(); // 2ms&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
B(){&lt;br /&gt;
    compute_b(); // 2ms&lt;br /&gt;
    io_b(); // 4ms&lt;br /&gt;
    compute_b(); // 2ms&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
C(){&lt;br /&gt;
    compute_c(); // 3ms&lt;br /&gt;
    io_c(); // 3ms&lt;br /&gt;
    compute_c(); // 3ms&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
D(){&lt;br /&gt;
    compute_d1(); // 10ms&lt;br /&gt;
    io_d(); // 1ms&lt;br /&gt;
    compute_d2(); // 1ms&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Lo scheduler potrebbe anche essere a priorità:&amp;lt;br&amp;gt;&lt;br /&gt;
Priorità '''B''' &amp;lt; priorità '''D''' &amp;lt; priorità '''C'''&amp;lt;br&amp;gt;&lt;br /&gt;
Priorità '''A''' = ?&amp;lt;br&amp;gt;&lt;br /&gt;
'''B''' fatto partire prima di '''C''' e '''D'''.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Esercizio g.2 (da controllare) ==&lt;br /&gt;
# In sistemi dove dispositivi di archiviazione o supporti hardware per la memoria virtuale (e dunque per la paginazione, spesso utilizzata per realizzare il supporto di memoria virtuale) non sono presenti (es. sistemi embedded). ''(In sistemi real-time la memoria virtuale è praticabile? Annotare.)''&lt;br /&gt;
# Perchè ad esempio sulle chiavette USB quasi mai abbiamo il problema di dover utilizzare file di dimensione maggiore ai 4GB. Non utilizza il journaling, che richiede molteplici scritture per ogni azione ed in dispositivi portatili può ridurre di molto la durata. Non supporta i permessi sui file, e questo è un vantaggio per le chiavette USB, pensate per trasferire dati tra PC diversi.&lt;br /&gt;
# Per fornire parallelismo e ridondanza. Non è necessario fare backup dei dati sul disco, nel senso di mantenere una copia identica di dati già memorizzati altrove, in quanto diversi sistemi di codici permettono il rilevamento e/o la correzione di errori.&lt;br /&gt;
# Se in un grafo di Holt multirisorsa esiste un ciclo tra più processi e risorse, ciò non significa che allo stesso tempo non siano coinvolti processi con archi esclusivamente entranti. Ogni processo appartenente a questa categoria non è in attesa di risorse, e può dunque procedere con i suoi calcoli; quando avrà terminato rilascerà le risorse precedentemente allocategli, eventualmente sbloccando uno dei processi coinvolti nel ciclo.&lt;br /&gt;
&lt;br /&gt;
= Esame 21/06/2018 =&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2018.06.21.tot.pdf 2018.06.21.tot.pdf]&lt;br /&gt;
=== Esercizio c.1 (sbagliato) ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
/* Monitor tmon */&lt;br /&gt;
&lt;br /&gt;
define MAX n;&lt;br /&gt;
define TERRAFERMA 1;&lt;br /&gt;
define ISOLA 2;&lt;br /&gt;
&lt;br /&gt;
semaphore ok2unload;&lt;br /&gt;
semaphore ok2load;&lt;br /&gt;
semaphore ok2ship;&lt;br /&gt;
semaphore mutex(1); // la rampa è zona critica --&amp;gt; mutua esclusione&lt;br /&gt;
&lt;br /&gt;
stack ferry;&lt;br /&gt;
int current_port = 0;&lt;br /&gt;
&lt;br /&gt;
Procedure entry: al_porto(int location)&lt;br /&gt;
{&lt;br /&gt;
    current_port = location; // traghetto arriva a destinazione&lt;br /&gt;
    ok2unload.signal(); // da il via per far sbarcare le macchine&lt;br /&gt;
    ok2ship.wait(); // si ferma&lt;br /&gt;
    current_port = 0; // traghetto sta viaggiando tra i due porti&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: imbarca(int location)&lt;br /&gt;
{&lt;br /&gt;
    mutex.wait(); // prende possesso della rampa&lt;br /&gt;
    ferry.push(1); // sale sul traghetto&lt;br /&gt;
    mutex.signal(); // libera la rampa&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: imbarcato(int location)&lt;br /&gt;
{&lt;br /&gt;
    if(ferry.lenght() == MAX) // se il traghetto è pieno da il via per farlo salpare&lt;br /&gt;
    {&lt;br /&gt;
        ok2load.wait();&lt;br /&gt;
        ok2ship.signal();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: sbarca(int location)&lt;br /&gt;
{&lt;br /&gt;
    mutex.wait(); // prende possesso della rampa&lt;br /&gt;
    ferry.pop(); // scende dal traghetto&lt;br /&gt;
    mutex.signal(); // libera la rampa&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: sbarcato(int location)&lt;br /&gt;
{&lt;br /&gt;
    if(ferry.lenght() == 0) // se il traghetto è vuoto da il via per far imbarcare le macchine&lt;br /&gt;
    {&lt;br /&gt;
        ok2unload.wait();&lt;br /&gt;
        ok2load.signal();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.1 ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
/* Monitor tmon */&lt;br /&gt;
 &lt;br /&gt;
#define MAX n&lt;br /&gt;
#define NONE 0&lt;br /&gt;
#define TERRAFERMA 1&lt;br /&gt;
#define ISOLA 2&lt;br /&gt;
 &lt;br /&gt;
condition ok2unload;&lt;br /&gt;
condition ok2load[2];&lt;br /&gt;
condition ok2ship;&lt;br /&gt;
condition empty;&lt;br /&gt;
 &lt;br /&gt;
int onboard = 0;&lt;br /&gt;
int onramp = 0;&lt;br /&gt;
int current_port = NONE;&lt;br /&gt;
&lt;br /&gt;
Procedure entry: al_porto(int location)&lt;br /&gt;
{&lt;br /&gt;
    //arrivando&lt;br /&gt;
    current_port = location;&lt;br /&gt;
    ok2unload.signal();&lt;br /&gt;
    if (onboard &amp;gt; 0)&lt;br /&gt;
        empty.wait()&lt;br /&gt;
    ok2load[location].signal()&lt;br /&gt;
    if (onboard &amp;lt; MAX)&lt;br /&gt;
        ok2ship.wait()&lt;br /&gt;
    //partendo&lt;br /&gt;
    current_port = NONE;&lt;br /&gt;
}&lt;br /&gt;
 &lt;br /&gt;
Procedure entry: imbarca(int location)&lt;br /&gt;
{&lt;br /&gt;
    if (current_port != location || onramp &amp;gt; 0 || onboard &amp;gt;= MAX)&lt;br /&gt;
        ok2load[location].wait()&lt;br /&gt;
    onramp = 1;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: imbarcato(int location)&lt;br /&gt;
{&lt;br /&gt;
    onramp = 0; onboard++;&lt;br /&gt;
    if (onboard &amp;lt; MAX)&lt;br /&gt;
        ok2load[location].signal();&lt;br /&gt;
    else&lt;br /&gt;
        ok2ship.signal();&lt;br /&gt;
}&lt;br /&gt;
 &lt;br /&gt;
Procedure entry: sbarca(int location)&lt;br /&gt;
{&lt;br /&gt;
    if (current_port != location || onramp &amp;gt; 0)&lt;br /&gt;
        ok2unload.wait()&lt;br /&gt;
    onramp = 1;&lt;br /&gt;
}&lt;br /&gt;
 &lt;br /&gt;
Procedure entry: sbarcato(int location)&lt;br /&gt;
{&lt;br /&gt;
    onramp = 0; onboard--;&lt;br /&gt;
    if (onboard == 0)&lt;br /&gt;
        empty.signal();&lt;br /&gt;
    else&lt;br /&gt;
        ok2unload.signal();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.2 (sbagliato) ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define N n // limite operazioni&lt;br /&gt;
semaphore mutex(1); // sezione critica&lt;br /&gt;
&lt;br /&gt;
class lim_semaphore()&lt;br /&gt;
{&lt;br /&gt;
    int value;&lt;br /&gt;
    semaphore plus;&lt;br /&gt;
    semaphore minus;&lt;br /&gt;
    &lt;br /&gt;
    P()&lt;br /&gt;
    {&lt;br /&gt;
        mutex.P();&lt;br /&gt;
        if(value &amp;lt; N)&lt;br /&gt;
        {&lt;br /&gt;
            if (value &amp;gt;= 0)&lt;br /&gt;
            {&lt;br /&gt;
                plus.P();&lt;br /&gt;
            }&lt;br /&gt;
            else&lt;br /&gt;
            {&lt;br /&gt;
                minus.V();&lt;br /&gt;
            }&lt;br /&gt;
            value--;&lt;br /&gt;
        }&lt;br /&gt;
        mutex.V();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    V()&lt;br /&gt;
    {&lt;br /&gt;
        mutex.P();&lt;br /&gt;
        if(value &amp;gt; -N)&lt;br /&gt;
        {&lt;br /&gt;
            if (value &amp;lt;= 0)&lt;br /&gt;
            {&lt;br /&gt;
                minus.P();&lt;br /&gt;
            } &lt;br /&gt;
            else&lt;br /&gt;
            {&lt;br /&gt;
                plus.V();&lt;br /&gt;
            }&lt;br /&gt;
            value++;&lt;br /&gt;
        }&lt;br /&gt;
        mutex.V();        &lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.2 ===&lt;br /&gt;
==== Soluzione &amp;quot;furba e facile&amp;quot; ====&lt;br /&gt;
* Visto dall'utente [[User:Acsor|Acsor]] ([[User talk:Acsor|talk]]) in data 18:53, 9 September 2020 (CEST). Ritengo sia: corretto (perché l'ho fatto pressappoco uguale). (Ritengo anche che possedere strumenti di analisi formale per verificare la correttezza di codice simile sarebbe di grande ausilio.)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
class bounded_semaphore {&lt;br /&gt;
    semaphore plus;&lt;br /&gt;
    semaphore minus;&lt;br /&gt;
    int value;   // serve per significato&lt;br /&gt;
    &lt;br /&gt;
    bounded_semaphore (int initval, unsigned maxval) {&lt;br /&gt;
        value = initval;&lt;br /&gt;
        plus = new semaphore(maxval + initval);&lt;br /&gt;
        minus = new semaphore(maxval - initval);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void P() {&lt;br /&gt;
        plus.P();&lt;br /&gt;
        value--;&lt;br /&gt;
        minus.V(); &lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void V() {&lt;br /&gt;
        minus.P();&lt;br /&gt;
        value++;&lt;br /&gt;
        plus.V();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Soluzione &amp;quot;schiacciasassi&amp;quot; ====&lt;br /&gt;
Controllato da [[LiberaL|https://t.me/llibera]] in data 2023/05/12, perchè nel primo if della V() si fa value &amp;gt;= - maxval? non dovrebbe essere + maxval?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
class bounded_semaphore {&lt;br /&gt;
    semaphore mutex;&lt;br /&gt;
    queue&amp;lt;semaphore&amp;gt; okmin, okmax;&lt;br /&gt;
    int value;&lt;br /&gt;
    unsigned maxval;&lt;br /&gt;
&lt;br /&gt;
    bounded_semaphore (int initval, unsigned maxval) {&lt;br /&gt;
	value = initval;&lt;br /&gt;
        this.maxval = maxval;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void P() {&lt;br /&gt;
        mutex.P();&lt;br /&gt;
&lt;br /&gt;
        if (value &amp;lt;= -maxval)  {&lt;br /&gt;
            s=semaphore(0);&lt;br /&gt;
            okmin.enqueue(s);&lt;br /&gt;
            mutex.V();&lt;br /&gt;
            s.P();&lt;br /&gt;
        } else if (okmax.length() &amp;gt; 0) {&lt;br /&gt;
            s = okmax.dequeue()&lt;br /&gt;
            s.V();&lt;br /&gt;
            mutex.V();&lt;br /&gt;
        } else {&lt;br /&gt;
            value--;&lt;br /&gt;
            mutex.V();&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void V() {&lt;br /&gt;
        mutex.P();&lt;br /&gt;
&lt;br /&gt;
        if (value &amp;gt;= -maxval)  {  //qui...&lt;br /&gt;
            s=semaphore(0);&lt;br /&gt;
            okmax.enqueue(s);&lt;br /&gt;
            mutex.V();&lt;br /&gt;
            s.P();&lt;br /&gt;
        } else if (okmin.length() &amp;gt; 0) {&lt;br /&gt;
            s = okmin.dequeue()&lt;br /&gt;
            s.V();&lt;br /&gt;
            mutex.V();&lt;br /&gt;
        } else {&lt;br /&gt;
            value++;&lt;br /&gt;
            mutex.V();&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Esercizio g.1 ===&lt;br /&gt;
* Controllato dall'utente [[User:Acsor|Acsor]] ([[User talk:Acsor|talk]]), 23:17, 9 September 2020 (CEST). Ritengo sia: corretto&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
IC = 10,10,10 // Capitale iniziale&lt;br /&gt;
COH = 4,4,4   // Saldo in cassa&lt;br /&gt;
 &lt;br /&gt;
      MAX     ATT     RES    AVAIL&lt;br /&gt;
P1 | 6,6,6 | 1,1,1 | 5,5,5 | 4,4,4&lt;br /&gt;
P2 | 6,6,6 | 1,1,1 | 5,5,5 | 5,5,5&lt;br /&gt;
P3 | 9,9,9 | 4,4,4 | 5,5,5 | 6,6,6&lt;br /&gt;
 &amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Minimizzato&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
IC = 4,4,4&lt;br /&gt;
COH = 1,1,1&lt;br /&gt;
 &lt;br /&gt;
      MAX     ATT     RES  &lt;br /&gt;
P1 | 3,3,3 | 1,1,1 | 2,2,2&lt;br /&gt;
P2 | 3,3,3 | 1,1,1 | 2,2,2&lt;br /&gt;
P3 | 3,3,3 | 1,1,1 | 2,2,2&lt;br /&gt;
 &amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Esercizio g.2 (da controllare) ===&lt;br /&gt;
&lt;br /&gt;
* Visto e rimaneggiato in data 19:40, 10 September 2020 (CEST) dall'utente [[User:Acsor|Acsor]] ([[User talk:Acsor|talk]])&lt;br /&gt;
&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
&lt;br /&gt;
# Il calcolo del working set serve a determinare il numero di processi che possono essere mantenuti attivi sulla base del limite della memoria principale, più precisamente del suo numero di frame. Può essere svolto ad ogni page fault, ossia quando un processo tra quelli attivi richiede una pagina non presente in memoria, o prima di avviare un nuovo processo.&lt;br /&gt;
# La lunghezza massima di un file che può essere memorizzato su un file system di tipo FAT viene calcolata moltiplicando il massimo numero di cluster (dimensione dell'unità di allocazione) identificabili per la loro dimensione. Il massimo numero di cluster identificabili dipende da quanti bit sono allocati per numerarli, e per questa distinzione esistono varie versioni di FAT (FAT12, FAT16, FAT32).&lt;br /&gt;
## FAT32 memorizza la dimensione dei file in un intero unsigned da 32bit, e non può quindi gestire un file di dimensione superiore ai 2^32 bit = ~4GB.&lt;br /&gt;
## FAT16, allocando 16bit per identificare i cluster, può contarne al massimo 2^16 (65536). Prendendo quindi, ad esempio, un file system FAT16 con cluster da 32KB, possiamo avere file grandi al massimo 32KB*65536 = ~2GB.&lt;br /&gt;
## FAT12 di conseguenza può numerare al massimo 2^12 (4096) cluster, ma dato che il numero dei settori del disco viene memorizzato in un intero signed a 16bit, la massima dimensione del disco è 2^15 = 32MB. Ovviamente, non si può memorizzare un file di grandezza superiore alla dimensione dell'unità di memorizzazione stessa, e quindi anche i file in FAT12 possono avere dimensione massima di 32MB.&lt;br /&gt;
# Entrambi condividono l'intento di infettare host con codice malevolo, ma differiscono fondamentalmente nella modalità: i virus infettano programmi già esistenti mediante un ''virus dropper'', mentre i worm diffondono copie di se stessi, solitamente attraverso la rete.&lt;br /&gt;
# In vari casi sulla base della natura del sistema. Innanzitutto, in sistemi batch ciò avviene se non sono stati inseriti più processi per un certo lasso di tempo. In sistemi general-purpose (es. per PC o dispositivi mobili) tale condizione è verificabile se tutti i processi sono in attesa su una coda che non è quella dello scheduler (ad. es. di un semaforo o di una periferica di I/O); casi concreti sono pertanto il deadlock (di tutti i processi del sistema) o attesa generale di I/O. Infine sempre in sistemi general-purpose tale condizione può manifestarsi, stavolta in condizioni patologiche, se ogni processo è assegnato ad una propria CPU/core, lasciando pertanto la coda d'attesa vuota.&lt;br /&gt;
&lt;br /&gt;
= Esame 28/05/2018 =&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2018.05.28.tot.pdf 2018.05.28.tot.pdf]&lt;br /&gt;
=== Esercizio c.1 ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
Stack&amp;lt;int&amp;gt; entriesStack;&lt;br /&gt;
&lt;br /&gt;
int vid[MAX];&lt;br /&gt;
condition ok2esci[MAX]&lt;br /&gt;
int in = 0; &lt;br /&gt;
int out = -1;&lt;br /&gt;
&lt;br /&gt;
Procedure-entry: entra(int id) {&lt;br /&gt;
    if (in &amp;gt;= MAX)&lt;br /&gt;
        ok2entra.wait()&lt;br /&gt;
    vid[in++] = id;&lt;br /&gt;
    if (in &amp;lt; MAX)&lt;br /&gt;
        ok2entra.signal()&lt;br /&gt;
    else&lt;br /&gt;
        out = MAX - 1;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure-entry: esci(int id) {&lt;br /&gt;
    int i;&lt;br /&gt;
    for (i = 0; i &amp;lt; in; i++)&lt;br /&gt;
        if (vid[i] == id)&lt;br /&gt;
            break; //cerco l'indice di id nel vettore vid&lt;br /&gt;
&lt;br /&gt;
    if (i != out)&lt;br /&gt;
        ok2esci[i].wait();&lt;br /&gt;
&lt;br /&gt;
    if (out &amp;gt; 0) {&lt;br /&gt;
        out--;&lt;br /&gt;
        ok2esci[out].signal();&lt;br /&gt;
    } else {&lt;br /&gt;
        out--;&lt;br /&gt;
        in = 0; &lt;br /&gt;
        ok2entra.signal();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.1 (da controllare) ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
Monitor riempisvuota {&lt;br /&gt;
    Int MAXPROCESSI;&lt;br /&gt;
    Stack s;&lt;br /&gt;
    condition ok2enter;&lt;br /&gt;
    condition ok2exit;&lt;br /&gt;
 &lt;br /&gt;
    p.e void entra(getPid()){ &lt;br /&gt;
        if( s.size() &amp;gt;= MAXPROCESSI)&lt;br /&gt;
            ok2enter.wait();&lt;br /&gt;
        s.insert(getPid());&lt;br /&gt;
        if(s.size() &amp;gt; MAXPROCESSI)&lt;br /&gt;
            ok2exit.signal() &lt;br /&gt;
    }&lt;br /&gt;
 &lt;br /&gt;
    p.e void esci(getPid()){ &lt;br /&gt;
        if(s.size() &amp;gt; MAXPROCESSI &amp;amp;&amp;amp; s.top == getPid()) {&lt;br /&gt;
            s.pop();&lt;br /&gt;
            ok2entra.signal()&lt;br /&gt;
        }&lt;br /&gt;
        else&lt;br /&gt;
            ok2exit.wait();&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Esercizio c.2 (ERRATO) ===&lt;br /&gt;
&lt;br /&gt;
* Soluzione proposta è errata, non puoi riceve in modo greedy e printare subito il carattere [[User:Flecart|Flecart]] ([[User talk:Flecart|talk]]) 11:33, 18 January 2023 (CET)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
proc[x]: x='a',...,'z'&lt;br /&gt;
 while True:&lt;br /&gt;
  //c sarà il carattere stampato dal processo precedente&lt;br /&gt;
  (c, string) = arecv(*)&lt;br /&gt;
  if(string == wait){&lt;br /&gt;
    //mi metto in attesa di ricevere l'ACK da proc[x]&lt;br /&gt;
    m=arecv(x);&lt;br /&gt;
  }&lt;br /&gt;
  if (c == NONE){&lt;br /&gt;
    //significa che sei il primo a ricevere quella stringa&lt;br /&gt;
    print(x);&lt;br /&gt;
    if (len(string) &amp;gt; 1){&lt;br /&gt;
      //mando la wait a tutti, il primo che riceve qualcosa da stampare manda una wait a tutti&lt;br /&gt;
      asend(wait,*);&lt;br /&gt;
      int l = len(string);&lt;br /&gt;
      int i = 1;&lt;br /&gt;
      while(l != 0){&lt;br /&gt;
        asend(proc[string[i]], (x, string[i...]));&lt;br /&gt;
        //si mette in attesa di ricevere l'ACK dal processo dell'ultima lettera della parola&lt;br /&gt;
        m=areceive(proc[string[i]]);&lt;br /&gt;
        //rimando la wait al processo per ribloccarlo&lt;br /&gt;
        asend(wait, proc[string[i]])&lt;br /&gt;
        l--;&lt;br /&gt;
        i++;&lt;br /&gt;
      }&lt;br /&gt;
      //dopo aver finito la stampa della stringa sblocco tutti i processi&lt;br /&gt;
      asend(ACK, *);&lt;br /&gt;
    }&lt;br /&gt;
  }else{&lt;br /&gt;
    print(x);&lt;br /&gt;
    asend(ACK, x);&lt;br /&gt;
    //ricomincia il ciclo while, si rimette in attesa e il 'gestore gli rimanda la wait'&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.2  ===&lt;br /&gt;
[[User:Flecart|Flecart friend]] ([[User talk:Flecart|talk]]) cedo la proprità intellettuale di questa soluzione a flecart&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
process [x]: x='a'..'z'&lt;br /&gt;
  if(x=='a'){&lt;br /&gt;
    asend(&amp;lt;NULL,NULL&amp;gt;,'b');&lt;br /&gt;
    asend(&amp;lt;NULL,NULL&amp;gt;,'b');&lt;br /&gt;
  }&lt;br /&gt;
  While True:&lt;br /&gt;
    &amp;lt;c,string&amp;gt;=arecv(x-1+26%26);&lt;br /&gt;
    if(string==NULL):&lt;br /&gt;
      &amp;lt;c,string&amp;gt;=arecv(*);&lt;br /&gt;
      if(string!=NULL):&lt;br /&gt;
        &amp;lt;c,string&amp;gt;=arecv(x-1+26%26);&lt;br /&gt;
&lt;br /&gt;
    if(string!=NULL):&lt;br /&gt;
      if(string[0]==x):&lt;br /&gt;
        print(string[0]);&lt;br /&gt;
        if(string.len()&amp;gt;1):&lt;br /&gt;
          aasend(&amp;lt;NULL,string[1:]&amp;gt;,(x+1)%26);&lt;br /&gt;
        else:&lt;br /&gt;
          aasend(&amp;lt;NULL,NULL&amp;gt;,(x+1)%26);&lt;br /&gt;
          aasend(&amp;lt;NULL,NULL&amp;gt;,(x+1)%26);&lt;br /&gt;
      else:&lt;br /&gt;
          aasend(&amp;lt;NULL,string&amp;gt;,(x+1)%26);&lt;br /&gt;
    else:&lt;br /&gt;
      aasend(&amp;lt;NULL,NULL&amp;gt;,(x+1)%26);&lt;br /&gt;
      aasend(&amp;lt;NULL,NULL&amp;gt;,(x+1)%26);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Proposta c2 ===&lt;br /&gt;
* Proposto [[User:Flecart|Flecart]] ([[User talk:Flecart|talk]]) 11:31, 18 January 2023 (CET)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
proc[a]:&lt;br /&gt;
	bool occupied = false;&lt;br /&gt;
	queue&amp;lt;string&amp;gt; s;&lt;br /&gt;
	&lt;br /&gt;
	while True {&lt;br /&gt;
		(c, string) = arecv(*);&lt;br /&gt;
		&lt;br /&gt;
		if (c == NONE) {&lt;br /&gt;
			if (occupied) {&lt;br /&gt;
				s.enqueue(string);&lt;br /&gt;
			} else {&lt;br /&gt;
				if (string.len() &amp;lt; 1)&lt;br /&gt;
					continue;&lt;br /&gt;
			&lt;br /&gt;
				occupied = true;&lt;br /&gt;
				asend(string[0], (MIDDLE, string));&lt;br /&gt;
			}&lt;br /&gt;
		} else if (c == END) {&lt;br /&gt;
			if (s.size() &amp;gt; 0) {&lt;br /&gt;
				string ss = s.dequeue();&lt;br /&gt;
				asend(string[0], (MIDLLE, string));&lt;br /&gt;
			} else {&lt;br /&gt;
				occupied = false;&lt;br /&gt;
			}&lt;br /&gt;
		} else {&lt;br /&gt;
			print(x);&lt;br /&gt;
			if (len(string) &amp;gt; 1) &lt;br /&gt;
				asend(proc[string[0]], (MIDDLE, string[1:]));&lt;br /&gt;
			else:&lt;br /&gt;
				asend(proc[a], (END, &amp;quot;&amp;quot;));&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
		&lt;br /&gt;
proc[x]: x = 'b', ... 'z';&lt;br /&gt;
	while True {&lt;br /&gt;
		(c, string) = arecv(*);&lt;br /&gt;
		if (c == NONE) {&lt;br /&gt;
			asend(proc['a'], (NONE, string));&lt;br /&gt;
		} else {  // potrà essere solo MIDDLE&lt;br /&gt;
			print(x);&lt;br /&gt;
			if (len(string) &amp;gt; 1) &lt;br /&gt;
				asend(proc[string[0]], (MIDDLE, string[1:]));&lt;br /&gt;
			else:&lt;br /&gt;
				asend(proc[a], (END, &amp;quot;&amp;quot;));&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Esame 12/02/2018 =&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2018.02.12.tot.pdf 2018.02.12.tot.pdf]&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.1 (da controllare) ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
monitor bridge:&lt;br /&gt;
&lt;br /&gt;
    int ncar&lt;br /&gt;
    bool boat_on_0&lt;br /&gt;
    bool boat_on_1       // per semplicità, quando nel codice si trova boat_on_(direction) oppure isBoat(direction)(),&lt;br /&gt;
                         // si valuta il valore booleano di direction e lo si applica sotto forma di stringa al simbolo&lt;br /&gt;
                         // ad esso adiacente&lt;br /&gt;
    bool is_raised&lt;br /&gt;
    queue waiting_mean   // i valori possibili sono: boat0, boat1 oppure car&lt;br /&gt;
    condition ok2go&lt;br /&gt;
  &lt;br /&gt;
    entry car_enter(direction): &lt;br /&gt;
        if is_raised || ncar == MAXCAR:&lt;br /&gt;
            waiting_mean.enqueue(car)&lt;br /&gt;
            ok2go.wait()&lt;br /&gt;
        is_raised = false&lt;br /&gt;
        ++ncar&lt;br /&gt;
  &lt;br /&gt;
    entry car_exit(direction):&lt;br /&gt;
        --ncar&lt;br /&gt;
        if (waiting_mean.top().isBoat() &amp;amp;&amp;amp; ncar == 0) || waiting_mean.top().isCar():    // isBoat ritorna true se l'oggetto su cui&lt;br /&gt;
            waiting_mean.dequeue()                                                      // è invocata è boat0 oppure boat1&lt;br /&gt;
            ok2go.signal()&lt;br /&gt;
  &lt;br /&gt;
    entry boat_enter(direction):&lt;br /&gt;
        if !is_raised || boat_on_(direction):&lt;br /&gt;
            waiting_mean.enqueue(boat)&lt;br /&gt;
            ok2go.wait()&lt;br /&gt;
        if waiting_mean.top().isBoat(!direction)():&lt;br /&gt;
            waiting_mean.dequeue()&lt;br /&gt;
            ok2go.signal()&lt;br /&gt;
        is_raised = true&lt;br /&gt;
        boat_on_(direction) = true&lt;br /&gt;
  &lt;br /&gt;
    entry boat_exit(direction):&lt;br /&gt;
        boat_on_(direction) = false&lt;br /&gt;
        if !boat_on_(!direction):&lt;br /&gt;
            waiting_mean.dequeue()&lt;br /&gt;
            ok2go.signal()&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.1 ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
monitor bridge  {&lt;br /&gt;
  int carsOnBridge = 0;&lt;br /&gt;
  int shipping[2] = {0, 0}; //navi da entrambe le direzioni&lt;br /&gt;
  int status = NONE; //UP DOWN NONE&lt;br /&gt;
  int last2pass = 0;     //ultimo che ha passato il ponte&lt;br /&gt;
  int waitingC = 0;      //coda delle macchine che aspettano&lt;br /&gt;
  int waitingS[2] = {0,0};  //navi che stanno aspettando&lt;br /&gt;
   &lt;br /&gt;
  condition ok2ship[2]&lt;br /&gt;
  condition ok2drive&lt;br /&gt;
 &lt;br /&gt;
entry car_enter(int direction){&lt;br /&gt;
    if(carsOnBridge &amp;gt;= MAX || status == UP || waitingS[0] + waitingS[1] &amp;gt; 0 ){&lt;br /&gt;
        waitingC++;ok2drive.wait;waitingC--;}&lt;br /&gt;
    status = DOWN;&lt;br /&gt;
    carsOnBridge++&lt;br /&gt;
    if (carsOnBridge &amp;lt; MAX)&lt;br /&gt;
       ok2drive.signal();     //vanno tutte le MAX car che stanno aspettando&lt;br /&gt;
} &lt;br /&gt;
entry car_exit(int direction){&lt;br /&gt;
    carsOnBridge--&lt;br /&gt;
    if (waitingS[0] + waitingS[1] == 0)&lt;br /&gt;
    ok2drive.signal();&lt;br /&gt;
    if(carsOnBridge == 0){&lt;br /&gt;
        ok2ship[0].signal(); ok2ship[1].signal();&lt;br /&gt;
    }&lt;br /&gt;
    if(carsOnBridge + waitingS[0] + waitingS[1] == 0) &lt;br /&gt;
    status = NONE&lt;br /&gt;
}&lt;br /&gt;
 &lt;br /&gt;
entry ship_enter(int direction){&lt;br /&gt;
    if (bridge = DOWN || shipping[direction] != 0 || waitingC &amp;gt; 0)&lt;br /&gt;
    {&lt;br /&gt;
        waitingS[i]++; ok2ship[i].wait(); waitingS[i]--; &lt;br /&gt;
    }&lt;br /&gt;
    isBridgeUp = false;&lt;br /&gt;
    shipping[i] = 1;&lt;br /&gt;
 &lt;br /&gt;
entry ship_exit(int direction){&lt;br /&gt;
      shipping[i] = 0;&lt;br /&gt;
      if (waitingC == 0)&lt;br /&gt;
          ok2ship[i].signal()&lt;br /&gt;
      else if(shipping[1-i] == 0)&lt;br /&gt;
          ok2drive.signal();&lt;br /&gt;
      if(carsOnBridge + waitingS[0] + waitingS[1] == 0) &lt;br /&gt;
      status = NONE&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.1 (da controllare) ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
monitor bridge {&lt;br /&gt;
&lt;br /&gt;
  UP=0;&lt;br /&gt;
  DOWN=1;&lt;br /&gt;
  bridgeis = DOWN;&lt;br /&gt;
&lt;br /&gt;
  bool carAreExiting = false;&lt;br /&gt;
&lt;br /&gt;
  condition ok2drive;&lt;br /&gt;
  condition ok2barca[2];&lt;br /&gt;
&lt;br /&gt;
  waitingCar = 0;&lt;br /&gt;
  carOnBridge = 0;&lt;br /&gt;
&lt;br /&gt;
  boatWaiting[2] = {0,0};&lt;br /&gt;
  boatIsPassing[2] = {false,false}&lt;br /&gt;
&lt;br /&gt;
  entry car_enter(direction) {&lt;br /&gt;
&lt;br /&gt;
    if (bridgeis == DOWN)&lt;br /&gt;
      if(carOnBridge == MAXCAR)&lt;br /&gt;
        waitingCar++;&lt;br /&gt;
        ok2drive.wait();&lt;br /&gt;
        waitingCar--;&lt;br /&gt;
      else if (carAreExiting)&lt;br /&gt;
        waitingCar++;&lt;br /&gt;
        ok2drive.wait();&lt;br /&gt;
        waitingCar--;&lt;br /&gt;
    else &lt;br /&gt;
      if (boatIsPassing[0] || boatIsPassing[1])&lt;br /&gt;
        waitingCar++;&lt;br /&gt;
        ok2drive.wait();&lt;br /&gt;
        waitingCar--;&lt;br /&gt;
        bridgeis = DOWN;&lt;br /&gt;
&lt;br /&gt;
    carOnBridge++;&lt;br /&gt;
    carAreExiting = false;&lt;br /&gt;
    if(carOnBridge &amp;lt; MAXCAR &amp;amp;&amp;amp; !carAreExiting) &lt;br /&gt;
      ok2drive.signal();&lt;br /&gt;
      &lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  entry car_exit(direction) {&lt;br /&gt;
&lt;br /&gt;
    carOnBridge--;&lt;br /&gt;
    carAreExiting = true;&lt;br /&gt;
&lt;br /&gt;
    if(carOnBridge == 0)&lt;br /&gt;
      carAreExiting = false;&lt;br /&gt;
      if(boatWaiting[0] &amp;gt; 0)&lt;br /&gt;
        bridgeis = UP;&lt;br /&gt;
        ok2barca[0].signal();&lt;br /&gt;
      else if (boatWaiting[1] &amp;gt; 0)&lt;br /&gt;
        bridgeis = UP;&lt;br /&gt;
        ok2barca[1].signal();&lt;br /&gt;
      else &lt;br /&gt;
        ok2drive.signal();&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  entry boat_enter(direction) {&lt;br /&gt;
&lt;br /&gt;
    if (bridgeis == UP)&lt;br /&gt;
    | if (boatIsPassing[direction] == true)&lt;br /&gt;
    | |  boatWaiting[direction]++;&lt;br /&gt;
    | |  ok2barca.wait();&lt;br /&gt;
    | |  boatWaiting[direction]--;&lt;br /&gt;
    else &lt;br /&gt;
    | if (carOnBridge &amp;gt; 0)&lt;br /&gt;
    | | boatWaiting[direction]++;&lt;br /&gt;
    | | ok2barca.wait();&lt;br /&gt;
    | | boatWaiting[direction]--;&lt;br /&gt;
    | | bridgeis = UP;&lt;br /&gt;
&lt;br /&gt;
    boatIsPassing[direction] = true;&lt;br /&gt;
&lt;br /&gt;
    if(boatIsPassing[1-direction] == false &amp;amp;&amp;amp; boatWaiting[1-direction] &amp;gt; 0)&lt;br /&gt;
      ok2barca[1-direction].signal();&lt;br /&gt;
    &lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  entry boat_exit(direction) {&lt;br /&gt;
&lt;br /&gt;
    boatIsPassing[direction] = false;&lt;br /&gt;
&lt;br /&gt;
    if (boatIsPassing[1-direction] == false)&lt;br /&gt;
      if (waitingCar &amp;gt; 0)&lt;br /&gt;
        bridgeis = DOWN;&lt;br /&gt;
        ok2drive.signal();&lt;br /&gt;
    else&lt;br /&gt;
        if (waitingCar == 0)&lt;br /&gt;
          ok2barca[direction].signal();&lt;br /&gt;
          &lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.1 (sbagliato) ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
monitor bridge&lt;br /&gt;
  condition ok2passCar;&lt;br /&gt;
  condition ok2passBoat;&lt;br /&gt;
  condition ok2up;&lt;br /&gt;
  condition ok2down;&lt;br /&gt;
  int carOnBridge[2] = 0; //2 sensi di marcia&lt;br /&gt;
  int boatUnderBridge[2] = 0;&lt;br /&gt;
  boolean bridge_down = false; //vuol dire che il ponte parte alzato, true ponte abbassato&lt;br /&gt;
  &lt;br /&gt;
  procedure entry car_enter(direction){&lt;br /&gt;
      if(bridge_down &amp;amp;&amp;amp; carOnBridge[direction] &amp;lt; MAXCAR){&lt;br /&gt;
        carOnBridge[direction]++;&lt;br /&gt;
        ok2passCar.signal();&lt;br /&gt;
      }else if (bridge_down &amp;amp;&amp;amp; boatUnderBridge[0] == 0 &amp;amp;&amp;amp; boatUnderBridge[1] == 0){&lt;br /&gt;
        //se non ci sono navi in transito e arriva una macchina abbassa ponte&lt;br /&gt;
        ok2down.signal();&lt;br /&gt;
        ok2passCar.signal();&lt;br /&gt;
        ok2passBoat.wait();&lt;br /&gt;
      }else{&lt;br /&gt;
        ok2passCar.wait();&lt;br /&gt;
      }&lt;br /&gt;
  }     &lt;br /&gt;
        &lt;br /&gt;
  procedure entry car_exit(direction){&lt;br /&gt;
      carOnBridge[direction]--;&lt;br /&gt;
      if(carOnBridge[0] == 0 &amp;amp;&amp;amp; carOnBridge[1] == 0){&lt;br /&gt;
        bridge_down = false;&lt;br /&gt;
        ok2up.signal();&lt;br /&gt;
      }else{&lt;br /&gt;
        ok2up.wait();&lt;br /&gt;
      }&lt;br /&gt;
  }&lt;br /&gt;
      &lt;br /&gt;
  procedure entry boat_enter(direction){&lt;br /&gt;
      if(!bridge_down &amp;amp;&amp;amp; boatUnderBridge[direction] &amp;lt; 1){&lt;br /&gt;
        boatUnderBridge[direction]++;&lt;br /&gt;
        ok2passBoat.signal();&lt;br /&gt;
      }else if(!bridge_down &amp;amp;&amp;amp; carOnBridge[0] == 0 &amp;amp;&amp;amp; carOnBridge[1] == 0){&lt;br /&gt;
        ok2up.signal();&lt;br /&gt;
        ok2passBoat.signal();&lt;br /&gt;
        ok2passCar.wait();&lt;br /&gt;
      }else {&lt;br /&gt;
        ok2passBoat.wait();&lt;br /&gt;
      }&lt;br /&gt;
  }&lt;br /&gt;
      &lt;br /&gt;
  procedure entry boat_exit(direction){  &lt;br /&gt;
      boatUnderBridge[direction]--;&lt;br /&gt;
      if(boatUnderBridge[0] == 0 &amp;amp;&amp;amp; boatUnderBridge[1] == 0){&lt;br /&gt;
        bridge_down = true;&lt;br /&gt;
        ok2down.signal();&lt;br /&gt;
      }else{&lt;br /&gt;
        ok2down.wait();&lt;br /&gt;
      }&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.1 2o (sbagliato) ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define car 1&lt;br /&gt;
#define ship 2 &lt;br /&gt;
#define fromDX 1&lt;br /&gt;
#define fromSX 0&lt;br /&gt;
&lt;br /&gt;
monitor bridge  {&lt;br /&gt;
  int carsOnBridge = 0;&lt;br /&gt;
  int shippingDX = 0; //nave che sta passando dal lato destro&lt;br /&gt;
  int shippingSX = 0; //nave che sta passando dal lato sinistro&lt;br /&gt;
  bool isBridgeUp = false;&lt;br /&gt;
  int last2pass = 0;     //ultimo che ha passato il ponte&lt;br /&gt;
  int waitingS = 0;  //navi che stanno aspettando&lt;br /&gt;
  int waitingC = 0 ; //auto che stanno aspettando&lt;br /&gt;
  &lt;br /&gt;
  condition ok2ship&lt;br /&gt;
  condition ok2drive&lt;br /&gt;
&lt;br /&gt;
entry car_enter(int direction){&lt;br /&gt;
    //un auto si ferma se il numero di auto sul ponte è massimo&lt;br /&gt;
    //e se l'ultima a passare è stata un auto mentre ci sono navi in attesa&lt;br /&gt;
    if(carsOnBridge == MAX || isBridgeUp || (last2pass==car &amp;amp;&amp;amp; waitingS &amp;gt; 0) ){&lt;br /&gt;
        waitingC++;&lt;br /&gt;
        ok2drive.wait;&lt;br /&gt;
    }&lt;br /&gt;
    carsOnBridge++;&lt;br /&gt;
    waitingC--;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
entry car_exit(int direction){&lt;br /&gt;
    carsOnBridge--;&lt;br /&gt;
    last2pass = car;&lt;br /&gt;
    if(carsOnBridge == 0 &amp;amp;&amp;amp; waitingS&amp;gt;0){&lt;br /&gt;
        isBrigdeUp = true;&lt;br /&gt;
        ok2ship.signal;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
entry ship_enter(int direction){&lt;br /&gt;
    //se la barca viene da destra&lt;br /&gt;
    if(direction == fromDX){&lt;br /&gt;
        //si ferma anche quando c'è una nave che sta già attraversando nella sua stessa direzione&lt;br /&gt;
        if (isBridgeup == false || shippingDX || (last2pass==ship &amp;amp;&amp;amp; waitingC &amp;gt; 0) ){&lt;br /&gt;
            waitingS++;&lt;br /&gt;
            ok2ship.wait;&lt;br /&gt;
        }&lt;br /&gt;
        if (waitingS &amp;gt; 0)&lt;br /&gt;
            waitingS--;&lt;br /&gt;
        shippingDX = 1;&lt;br /&gt;
        }&lt;br /&gt;
    //se la barca viene da sinistra&lt;br /&gt;
    else if(direction == fromSX){&lt;br /&gt;
        if (isBridgeup == false || shippingSX || ( (last2pass==ship &amp;amp;&amp;amp; waitingC &amp;gt; 0))){&lt;br /&gt;
        waitingS++;&lt;br /&gt;
        ok2ship.wait;&lt;br /&gt;
        }&lt;br /&gt;
        if (waitingS &amp;gt; 0)&lt;br /&gt;
            waitingS--;        &lt;br /&gt;
        shippingSX = 1;&lt;br /&gt;
    &lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
entry ship_exit(int direction){&lt;br /&gt;
        if(direction == fromDX)&lt;br /&gt;
            shippingDX = 0;&lt;br /&gt;
        else if (direction == fromSX)&lt;br /&gt;
            shippingSX = 0;&lt;br /&gt;
        last2pass = ship;&lt;br /&gt;
        if(shippingDX == 0 &amp;amp;&amp;amp; shippingSX == 0 &amp;amp;&amp;amp; waitingC)&lt;br /&gt;
            isBrigdeUp == false;&lt;br /&gt;
            ok2drive.signal;&lt;br /&gt;
        else if(shippingDX == 0 &amp;amp;&amp;amp; shippingSX == 0 &amp;amp;&amp;amp; waitingS &amp;gt; 0)&lt;br /&gt;
            ok2ship.signal;    &lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.2 (sbagliato) ===&lt;br /&gt;
&lt;br /&gt;
# (Ri)Controllato dall'utente [[User:Acsor|Acsor]] ([[User talk:Acsor|talk]]) in data 26/08/2020&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
list printed_msg;  # questa è una variabile condivisa che ai fini dell'esercizio non si può utilizzare (message passing)&lt;br /&gt;
&lt;br /&gt;
process server[i]:&lt;br /&gt;
  while true:&lt;br /&gt;
    &amp;lt;msg, pid&amp;gt; = arecv(*)&lt;br /&gt;
&lt;br /&gt;
    if printed_msg.length == 0 or &amp;lt;msg, pid&amp;gt; is not in printed_msg:&lt;br /&gt;
      printed_msg.append(&amp;lt;msg,id&amp;gt;)&lt;br /&gt;
      print(msg)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.2 (da controllare) ===&lt;br /&gt;
Nello svolgimento seguente, receiver incapsula l'ambiente privato del processo; _peers rappresenta il vettore di processi &amp;quot;fratelli&amp;quot; ai quali può essere chiesto di stampare un messaggio, mentre _printed contiene l'hash di tutti i messaggi stampati dal processo locale. Si suppone che istanze della classe receiver possano essere passate come parametro ad areceive() ed asend() (non implementate).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
class receiver:&lt;br /&gt;
    def __init__(self, peers):&lt;br /&gt;
        &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
        :param peers: list of processes this process communicates with.&lt;br /&gt;
        &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
        self._peers = tuple(peers)&lt;br /&gt;
        self._printed = list()&lt;br /&gt;
    &lt;br /&gt;
    def run(self):&lt;br /&gt;
        while True:&lt;br /&gt;
            process, message = areceive(ANY)&lt;br /&gt;
&lt;br /&gt;
            if process in self._peers:&lt;br /&gt;
                self._reply_query(process, message)&lt;br /&gt;
            else:&lt;br /&gt;
                self._print(process, message)&lt;br /&gt;
&lt;br /&gt;
    def _print(self, sender, message):&lt;br /&gt;
        h = hash(message.text)&lt;br /&gt;
&lt;br /&gt;
        if h not in self._printed and not self._printed_from_peers(message):&lt;br /&gt;
            self._printed.append(h)&lt;br /&gt;
            print(message.text)&lt;br /&gt;
&lt;br /&gt;
    def _reply_query(self, sender, h):&lt;br /&gt;
        &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
        Invoked when the current process receive a &amp;quot;query&amp;quot; from a peer process.&lt;br /&gt;
        `h` contains the hash of a message which may or may have not been&lt;br /&gt;
        sent from this process; if it was sent, the reply is `Yes`, otherwise `No`.&lt;br /&gt;
        &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
        reply = &amp;quot;Yes&amp;quot; if int(h) in self._printed else &amp;quot;No&amp;quot;&lt;br /&gt;
        asend(sender, reply)&lt;br /&gt;
&lt;br /&gt;
    def _printed_from_peers(self, message):&lt;br /&gt;
        &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
        :return: `True` if this message has already been printed from any of the&lt;br /&gt;
        peer processes, `False` otherwise.&lt;br /&gt;
        &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
        h = hash(message)&lt;br /&gt;
&lt;br /&gt;
        for p in self._peers:&lt;br /&gt;
            asend(p, str(h))&lt;br /&gt;
&lt;br /&gt;
        for p in self._peers:&lt;br /&gt;
            _, reply = areceive(p)&lt;br /&gt;
&lt;br /&gt;
            if reply.text == &amp;quot;Yes&amp;quot;:&lt;br /&gt;
                return True&lt;br /&gt;
            else if reply.text != &amp;quot;No&amp;quot;:&lt;br /&gt;
                # If the response is neither &amp;quot;Yes&amp;quot; nor &amp;quot;No&amp;quot;, then we have got a query&lt;br /&gt;
                self._reply_query(p, reply)&lt;br /&gt;
&lt;br /&gt;
        return False&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Esercizio g.1 (da controllare) ===&lt;br /&gt;
Sulla base dei valori in entrata, è possibile costruire le matrici Allocation (q.tà di risorse allocate per processo e per tipo), Need (q.tà di risorse che ogni processo potrebbe ancora chiedere) e il vettore Available (num. di risorse correntemente disponibili).&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;float: left&amp;quot;&lt;br /&gt;
! colspan=3 | Allocation&lt;br /&gt;
|-&lt;br /&gt;
   !   !! A !! B&lt;br /&gt;
|-&lt;br /&gt;
   | p1 || 4 || 5&lt;br /&gt;
|-&lt;br /&gt;
   | p2 || 3 || 3&lt;br /&gt;
|-&lt;br /&gt;
   | p3 || 2 || 4&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;float: left; margin-left: 1em&amp;quot;&lt;br /&gt;
! colspan=3 | Need&lt;br /&gt;
|-&lt;br /&gt;
   !    !! A !! B&lt;br /&gt;
|-&lt;br /&gt;
   | p1 || 6 || 8&lt;br /&gt;
|-&lt;br /&gt;
   | p2 || 6 || 3&lt;br /&gt;
|-&lt;br /&gt;
   | p3 || 6 || 8&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;float: left; margin-left: 1em&amp;quot;&lt;br /&gt;
! colspan=2 | Available&lt;br /&gt;
|-&lt;br /&gt;
   ! A !! B&lt;br /&gt;
|-&lt;br /&gt;
   | x || y&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nel caso delle risorse di tipo A, deve aversi x &amp;gt;= 6 in quanto un processo dovrà essere selezionato come primo nella permutazione dell'algoritmo del banchiere multivaluta, e tutti quelli correnti hanno lo stesso valore Need(i)(1); per ciò che riguarda le risorse di tipo B, possiamo ragionare per esaustione&lt;br /&gt;
&lt;br /&gt;
* Se il primo processo della permutazione è p1, allora y &amp;gt;= 8 (con questo valore posso soddisfare la richiesta di p1 e in seguito tutte le altre)&lt;br /&gt;
* Se il primo processo della permutazione è p2, allora y &amp;gt;= 5: con questo valore è possibile soddisfare la richiesta di p2; una volta che esso avrà finito, restituirà 3 unità della risorsa B, che permetteranno di soddisfare sia le richieste di A sia quelle di C&lt;br /&gt;
* Se il primo processo della permutazione è p3, allora y &amp;gt;= 8 (ragionamento analogo come per p1)&lt;br /&gt;
&lt;br /&gt;
Volendo scegliere il minimo, y &amp;gt;= 5, ed in conclusione (x, y) &amp;gt;= (6, 5).&lt;br /&gt;
&lt;br /&gt;
''Svolgimento basato in parte sull'approccio di Operating System Concepts di Silberschatz. et al, 9th edition, cap. 7.''&lt;br /&gt;
&lt;br /&gt;
=== Esercizio g.2 (da controllare) ===&lt;br /&gt;
# Può accadere che il sistema torni in uno stato di safety o che invece porti a deadlock. Diversamente uno stato di safety non può portare direttamente ad uno stato di deadlock, ma solo ad uno di non-safety.&lt;br /&gt;
# Selezionare uno o più tra i processi attivi e sospenderli, salvando il loro stato su memoria secondaria operando delle operazioni di swap-out, finché l'insieme dei frame nella memoria centrale non è in grado di soddisfare tutti i processi rimasti attivi.&lt;br /&gt;
# La scelta è determinata perlopiù dal fattore costo. Con un sistema RAID 1 è possibile ripristinare un disco guasto molto brevemente, in quanto le operazioni coinvolte prevedono una semplice ricopiatura dal disco di backup; con un sistema RAID 5 il ripristino del disco guasto deve coinvolgere tutti i dischi dell'intero array, e ciò può richiedere anche ore per dischi di grandi dimensioni. D'altra parte RAID 1 è più costoso (con n dischi, posso memorizzare tanta informazione quanto potrei con n / 2 dischi) rispetto a RAID 5 dove, tra gli n dischi, complessivamente soltanto uno è destinato alle informazioni di ridondanza.&lt;br /&gt;
# ''Completare.''&lt;/div&gt;</summary>
		<author><name>LiberaL</name></author>
	</entry>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=Prove_scritte_2018&amp;diff=2973</id>
		<title>Prove scritte 2018</title>
		<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php?title=Prove_scritte_2018&amp;diff=2973"/>
		<updated>2023-05-12T14:39:00Z</updated>

		<summary type="html">&lt;p&gt;LiberaL: /* Soluzione &amp;quot;schiacciasassi&amp;quot; */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Esame 19/09/2018 =&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2018.09.19.tot.pdf Testo dell'esame].&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.2 (da controllare) ===&lt;br /&gt;
&lt;br /&gt;
* Controllato dall'utente ? in data ?&lt;br /&gt;
* ...&lt;br /&gt;
&lt;br /&gt;
Nello pseudocodice seguente, il termine this fa riferimento al processo corrente, mentre ANY ad uno qualunque.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
stack&amp;lt;message&amp;gt; messages;&lt;br /&gt;
&lt;br /&gt;
void lifo_send(string m, process dest) {&lt;br /&gt;
	do {&lt;br /&gt;
		asend(m, dest);&lt;br /&gt;
	} while (areceive(dest).text != &amp;quot;ACK&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
message lifo_receive(process source) {&lt;br /&gt;
	if (source != ANY) {&lt;br /&gt;
		message m = areceive(source);&lt;br /&gt;
&lt;br /&gt;
		asend(&amp;quot;ACK&amp;quot;, source);&lt;br /&gt;
&lt;br /&gt;
		return m;&lt;br /&gt;
	} else {&lt;br /&gt;
		message m;&lt;br /&gt;
&lt;br /&gt;
		asend(&amp;quot;END&amp;quot;, this);&lt;br /&gt;
		m = areceive(ANY);&lt;br /&gt;
&lt;br /&gt;
		while (m.text != &amp;quot;END&amp;quot; || m.sender != this) {&lt;br /&gt;
			messages.push(m);&lt;br /&gt;
			asend(&amp;quot;ACK&amp;quot;, m.sender);&lt;br /&gt;
&lt;br /&gt;
			m = areceive(ANY);&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
                /* Bisogna tenere conto dei casi in cui lifo_receive() viene invocata quando nessun&lt;br /&gt;
                 * messaggio è stato ancora spedito da altri processi. In tal caso si attende il&lt;br /&gt;
                 * il primo e lo si restituisce.&lt;br /&gt;
                 */&lt;br /&gt;
		if (messages.empty()) {&lt;br /&gt;
			m = areceive(ANY);&lt;br /&gt;
			asend(&amp;quot;ACK&amp;quot;, m.sender);&lt;br /&gt;
&lt;br /&gt;
			return m;&lt;br /&gt;
		} else {&lt;br /&gt;
			return messages.pop();&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Esame 17/07/2018 =&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2018.07.17.tot.pdf 2018.07.17.tot.pdf]&lt;br /&gt;
== Esercizio c.1 ==&lt;br /&gt;
A Bruxelles c'è un locale chiamato Delirium Café. Alla vigilia del FOSDEM tutti gli anni gli sviluppatori europei di&lt;br /&gt;
software libero si ritrovano a bere birra (il locale è nel guinnes dei primati con più di duemila tipi di birra). Il prossimo appuntamento è&lt;br /&gt;
fissato per il 1 febbraio 2019 ore 20. Numerosi sono i tipi di birra alla spina. I baristi (tanti) prendono gli ordini (es. mezza pinta, 1 o 2&lt;br /&gt;
pinte) e riempiono i bicchieri. Quando un fusto e' vuoto avvertono i magazzinieri che prendono un nuovo fusto che contiene più di&lt;br /&gt;
cento pinte e lo sostituiscono, a questo punto il barista può completare il riempimento del bicchiere.&lt;br /&gt;
La vita di un barista del Delirium è:&lt;br /&gt;
 while True:&lt;br /&gt;
   (type, quantity) = get_order()&lt;br /&gt;
   delirium.pour(type, quantity)&lt;br /&gt;
La vita di un Magazziniere è:&lt;br /&gt;
 while True:&lt;br /&gt;
   type = delirium.isempty()&lt;br /&gt;
   capacity = change_keg(type)&lt;br /&gt;
   delirium.loaded(type, capacity)&lt;br /&gt;
&lt;br /&gt;
Attenzione: se il fusto (keg) è quasi vuoto il barista dovrà riempire parzialmente il bicchiere, occorrerà attivare il magazziniere che&lt;br /&gt;
cambierà il fusto e poi il barista riempirà il bicchiere fino alla quantità richiesta dal cliente. Mentre un barista sta attendendo il&lt;br /&gt;
cambiamento di un fusto altri baristi potrebbero ricevere ordini per lo stesso tipo di birra: gestire opportunamente questo caso.&lt;br /&gt;
Scrivere il monitor Delirium.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Proposta di soluzione 1 === &lt;br /&gt;
* ERRORE: Secondo me c'è un leggero errore nella parte di load, nel caso in cui la nuova pinta non riesca a soddisfare completamente la richiesta ossia quando vale availableBeer[t] &amp;lt;= requests[t].head(), allora non lo risveglio nemmeno, invece dovrei risvegliare il pour, fargli versare quanto può, e richiedere una altra pinta, perché questo era un requisito del problema. [[User:Flecart|Flecart]] ([[User talk:Flecart|talk]]) 12:00, 15 January 2023 (CET)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
/* Monitor Delirum: */&lt;br /&gt;
&lt;br /&gt;
// Condition: Ok2Load;&lt;br /&gt;
// Condition: Ok2Pour[]; // Un elemento per Type&lt;br /&gt;
int availableBeer[]; // Un elemento per Type &lt;br /&gt;
Queue requests[]; // Un elemento per Type&lt;br /&gt;
Queue pendingRequests;&lt;br /&gt;
&lt;br /&gt;
Procedure entry: void Pour(Type t, Quantity c)&lt;br /&gt;
{&lt;br /&gt;
    if (c &amp;gt; availableBeer[t]) // Richiesta maggiore della birra disponibile&lt;br /&gt;
    {&lt;br /&gt;
        c -= availableBeer[t];&lt;br /&gt;
        availableBeer[t] = 0;              &lt;br /&gt;
        requests[t].Enqueue(c);&lt;br /&gt;
        if (requests[t].Length == 1) // Risveglio un magazziniere solo se è la prima richiesta di questo tipo di birra&lt;br /&gt;
        {&lt;br /&gt;
            pendingRequests.Enqueue(t);&lt;br /&gt;
            Ok2Load().Signal();&lt;br /&gt;
        }&lt;br /&gt;
        Ok2Pour[t].Wait();&lt;br /&gt;
        requests[t].Dequeue(); // Quando ho ottenuto la birra che voglio, elimino la mia richiesta&lt;br /&gt;
    }&lt;br /&gt;
    availableBeer[t] -= c;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: Type isEmpty()&lt;br /&gt;
{&lt;br /&gt;
    if (pendingRequests.Length == 0)&lt;br /&gt;
    {&lt;br /&gt;
        Ok2Load.Wait();&lt;br /&gt;
    }&lt;br /&gt;
    return pendingRequests.Dequeue();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: Loaded(Type t, Capacity c)&lt;br /&gt;
{&lt;br /&gt;
    availableBeer[t] += c;&lt;br /&gt;
    while (requests[t].Length &amp;gt; 0 &amp;amp;&amp;amp; availableBeer[t] &amp;gt; requests[t].head())&lt;br /&gt;
    {&lt;br /&gt;
        Ok2Pour[t].Signal();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if (requests[t].Length &amp;gt; 0) // serve per evitare che a causa di un magazziniere lento si accodino cosi tante richieste che mentre si sta caricando si svuota subito il fusto&lt;br /&gt;
    {&lt;br /&gt;
        pendingRequests.Enqueue(t);&lt;br /&gt;
        Ok2Load.Signal();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Proposta di soluzione 2 ===&lt;br /&gt;
* Proposto da [[User:Flecart|Flecart]] ([[User talk:Flecart|talk]]) 13:41, 15 January 2023 (CET)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
extern int MAX_TYPE;&lt;br /&gt;
class Delirium {&lt;br /&gt;
    int keg[MAX_TYPE];      // qnty fusto attuale&lt;br /&gt;
    int orders[MAX_TYPE];   // qnty richiesta&lt;br /&gt;
    bool worked[MAX_TYPE];  // 1 se magazziniere sta lavorando su questo.&lt;br /&gt;
&lt;br /&gt;
    condition type_wait[MAX_TYPE];&lt;br /&gt;
    int num_wait[MAX_TYPE];&lt;br /&gt;
&lt;br /&gt;
    queue&amp;lt;int&amp;gt; empty_type;&lt;br /&gt;
    condition is_empty;&lt;br /&gt;
&lt;br /&gt;
    entry pour(type, quantity) {&lt;br /&gt;
        while (keg[type] &amp;lt; quantity) {&lt;br /&gt;
            quantity -= keg[type];&lt;br /&gt;
            keg[type] = 0;&lt;br /&gt;
            if (!empty_type.find(type) &amp;amp;&amp;amp; !worked[type]) {&lt;br /&gt;
                empty_type.enqueue(type);&lt;br /&gt;
                is_empty.signal();&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            num_wait[type]++;&lt;br /&gt;
            type_wait[type].wait();&lt;br /&gt;
            num_wait[type]--;&lt;br /&gt;
        }&lt;br /&gt;
        keg[type] -= quantity;&lt;br /&gt;
        quantity = 0;  // questo è inutile, ma concettualmente è corretto, l'ordine è completato.&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    entry loaded(type, capacity) {&lt;br /&gt;
        keg[type] += capacity;&lt;br /&gt;
        worked[type] = false;&lt;br /&gt;
&lt;br /&gt;
        for (int i = num_wait[type]; i &amp;gt; 0; i--) {&lt;br /&gt;
            type_wait[type].signal();&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // si suppone che un singolo tipo di fusto è lavorabile da un solo magazziniere alla volta.&lt;br /&gt;
    // worked impedisce di avere nella coda un fusto su cuisi sta già lavorando.&lt;br /&gt;
    entry isempty() {&lt;br /&gt;
        if (empty_type.size() &amp;lt;= 0) {&lt;br /&gt;
            is_emtpy.wait();&lt;br /&gt;
        }&lt;br /&gt;
        int type = emtpy_type.dequeue();&lt;br /&gt;
        worked[type] = true;&lt;br /&gt;
        return type;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Esercizio c.2 ==&lt;br /&gt;
&lt;br /&gt;
=== Proposta di soluzione 1 ===&lt;br /&gt;
* Visto e corretto dall'utente [[User:Acsor|Acsor]] in data 23/08/2020&lt;br /&gt;
* Visto e corretto dall'utente ? in data ?&lt;br /&gt;
* Visto, ritenuto corretto [[User:Flecart|Flecart]] ([[User talk:Flecart|talk]]) 09:27, 15 January 2023 (CET)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
class LIFOBuffer {&lt;br /&gt;
	stack&amp;lt;T&amp;gt; s;&lt;br /&gt;
	semaphore mutex(1); // mutua esclusione&lt;br /&gt;
	semaphore ok2consume(0);&lt;br /&gt;
&lt;br /&gt;
	void push (T value) {&lt;br /&gt;
		mutex.P();&lt;br /&gt;
		s.push(value);&lt;br /&gt;
                // (1)&lt;br /&gt;
		mutex.V()&lt;br /&gt;
&lt;br /&gt;
		ok2consume.V()  // Curiosità: che succede se spostiamo quest'istruzione in (1)? Edit: funziona lo stesso, solo che aggiorni il valore del semaforo prima di uscire dalla mutex.&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	T pop () {&lt;br /&gt;
		T value;&lt;br /&gt;
&lt;br /&gt;
		ok2consume.P();&lt;br /&gt;
		mutex.P();&lt;br /&gt;
		value = s.pop();&lt;br /&gt;
		mutex.V();&lt;br /&gt;
&lt;br /&gt;
		return value;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Proposta di soluzione 2 ===&lt;br /&gt;
Proposto da [[User:Flecart|Flecart]] ([[User talk:Flecart|talk]]) 09:27, 15 January 2023 (CET)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
class lifobuf {&lt;br /&gt;
	semaphore mutex(1);&lt;br /&gt;
	stack&amp;lt;int&amp;gt; values;	// empty initialized&lt;br /&gt;
	stack&amp;lt;semaphore&amp;gt; waiting;	&lt;br /&gt;
&lt;br /&gt;
	push(int value) {&lt;br /&gt;
		mutex.P();&lt;br /&gt;
		values.push(value);&lt;br /&gt;
		if (waiting.size() &amp;gt; 0) {&lt;br /&gt;
			semaphore s = waiting.pop();&lt;br /&gt;
			s.V();&lt;br /&gt;
			return;&lt;br /&gt;
		}&lt;br /&gt;
			&lt;br /&gt;
		mutex.V();	&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	pop() {&lt;br /&gt;
		int ret_val;&lt;br /&gt;
		mutex.P();&lt;br /&gt;
		if (values.size() &amp;lt;= 0) {&lt;br /&gt;
			semaphore s = new semaphore(0);&lt;br /&gt;
			waiting.push(s);&lt;br /&gt;
			mutex.V();&lt;br /&gt;
			s.P();&lt;br /&gt;
			free(s);&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		ret_val = values.pop();&lt;br /&gt;
		mutex.V();	&lt;br /&gt;
&lt;br /&gt;
		return ret_val;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Esercizio g.1 ==&lt;br /&gt;
Possiamo notare subito che il sistema ha due processori ed un dispositivo di I/O.&lt;br /&gt;
'''A''' e '''B''' partono insieme al tempo 0.&amp;lt;br&amp;gt;&lt;br /&gt;
'''C''' parte tra il tempo 0 ed il tempo 2 (non possiamo sapere di preciso quando perchè entrambe le CPU sono occupate).&amp;lt;br&amp;gt;&lt;br /&gt;
'''D''' parte tra il tempo 0 ed il tempo 3.&amp;lt;br&amp;gt;&lt;br /&gt;
A questo punto possiamo supporre che tutti e 4 i processi partano in sequenza ('''A''', '''B''', '''C''', '''D''') nello stesso momento, e ognuno prende la prima CPU libera che trova.&amp;lt;br&amp;gt;&lt;br /&gt;
'''A''' lavora per 3ms, poi scade il time slice.&amp;lt;br&amp;gt;&lt;br /&gt;
Nel frattempo '''B''' lavora per 2ms, poi richiede I/O per 4ms.&amp;lt;br&amp;gt;&lt;br /&gt;
La CPU su cui lavora '''B''' quindi si libera, e si manda in esecuzione il processo '''C'''.&amp;lt;br&amp;gt;&lt;br /&gt;
Scaduto il time slice per '''A''', si da il controllo ad un nuovo processo. '''B''' è occupato con I/O, '''C''' sta già lavorando, quindi è il turno di '''D'''.&amp;lt;br&amp;gt;&lt;br /&gt;
'''C''' lavora per 3ms, poi richiede I/O per 3ms, che però è occupato da '''B''', quindi si mette in coda per utilizzarlo.&amp;lt;br&amp;gt;&lt;br /&gt;
La CPU su cui lavorava '''C''' si libera ed il controllo torna ad '''A''', che doveva lavorare ancora per 2ms prima di chiedere il controllo di I/O, quindi lavora e si mette in coda dietro a '''C'''.&amp;lt;br&amp;gt;&lt;br /&gt;
Tornando a '''D''', questo lavora per 3ms prima che scada il time slice. Anche '''B''' ha finito il lavoro e ha bisogno di una CPU.&amp;lt;br&amp;gt;&lt;br /&gt;
In questo momento sia '''D''' che '''B''' sono nella coda dei processi in stato ready, ma dal diagramma possiamo notare che il controllo torna a '''D'''.&amp;lt;br&amp;gt;&lt;br /&gt;
La CPU ha scelto a caso un processo tra i due, perchè arrivati a questo punto possiamo supporre che lo scheduler sia Round-Robin.&amp;lt;br&amp;gt;&lt;br /&gt;
'''B''' prende possesso della prima CPU che si libera, ovvero quella occupata da '''A''', poi lavora per 2ms e termina il suo lavoro.&amp;lt;br&amp;gt;&lt;br /&gt;
Nel momento in cui '''B''' termina il lavoro, scade anche il time slice per '''D''', e '''C''' termina di usare I/O.&amp;lt;br&amp;gt;&lt;br /&gt;
Abbiamo due processi ('''C''' e '''D''') in coda ready. Ma abbiamo anche due CPU libere, perchè '''A''' è in coda per I/O e ci entra appena '''C''' finisce di usarlo.&amp;lt;br&amp;gt;&lt;br /&gt;
Lo scheduler sceglie di mandare '''C''' sul primo processore e '''D''' sul secondo.&amp;lt;br&amp;gt;&lt;br /&gt;
'''A''' nel frattempo, lavora per 4ms con I/O.&amp;lt;br&amp;gt;&lt;br /&gt;
'''C''' lavora per 3ms, poi termina il suo lavoro.&amp;lt;br&amp;gt;&lt;br /&gt;
'''D''' lavora per 3ms, poi scade il time slice. Ci sono due processori liberi, quindi '''D''' riparte subito in esecuzione.&amp;lt;br&amp;gt;&lt;br /&gt;
'''D''' doveva lavorare ancora per 1ms prima di aver bisogno di I/O, quindi finisce e si mette in coda.&amp;lt;br&amp;gt;&lt;br /&gt;
Ma nello stesso momento '''A''' termina di usare I/O, si prende un processore libero e lavora per i suoi ultimi 2ms.&amp;lt;br&amp;gt;&lt;br /&gt;
'''D''' lavora per 1ms con I/O, poi prende il secondo processore libero e lavora per 1ms prima di terminare il suo lavoro.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Il time slice è di 3ms, lo scheduler è di tipo Round-Robin.&amp;lt;br&amp;gt;&lt;br /&gt;
Il dispositivo di I/O è FIFO. L'ordine con cui partono i processi è quello alfabetico.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
A(){&lt;br /&gt;
    compute_a1(); // 5ms&lt;br /&gt;
    io_a(); // 4ms&lt;br /&gt;
    compute_a2(); // 2ms&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
B(){&lt;br /&gt;
    compute_b(); // 2ms&lt;br /&gt;
    io_b(); // 4ms&lt;br /&gt;
    compute_b(); // 2ms&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
C(){&lt;br /&gt;
    compute_c(); // 3ms&lt;br /&gt;
    io_c(); // 3ms&lt;br /&gt;
    compute_c(); // 3ms&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
D(){&lt;br /&gt;
    compute_d1(); // 10ms&lt;br /&gt;
    io_d(); // 1ms&lt;br /&gt;
    compute_d2(); // 1ms&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Lo scheduler potrebbe anche essere a priorità:&amp;lt;br&amp;gt;&lt;br /&gt;
Priorità '''B''' &amp;lt; priorità '''D''' &amp;lt; priorità '''C'''&amp;lt;br&amp;gt;&lt;br /&gt;
Priorità '''A''' = ?&amp;lt;br&amp;gt;&lt;br /&gt;
'''B''' fatto partire prima di '''C''' e '''D'''.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Esercizio g.2 (da controllare) ==&lt;br /&gt;
# In sistemi dove dispositivi di archiviazione o supporti hardware per la memoria virtuale (e dunque per la paginazione, spesso utilizzata per realizzare il supporto di memoria virtuale) non sono presenti (es. sistemi embedded). ''(In sistemi real-time la memoria virtuale è praticabile? Annotare.)''&lt;br /&gt;
# Perchè ad esempio sulle chiavette USB quasi mai abbiamo il problema di dover utilizzare file di dimensione maggiore ai 4GB. Non utilizza il journaling, che richiede molteplici scritture per ogni azione ed in dispositivi portatili può ridurre di molto la durata. Non supporta i permessi sui file, e questo è un vantaggio per le chiavette USB, pensate per trasferire dati tra PC diversi.&lt;br /&gt;
# Per fornire parallelismo e ridondanza. Non è necessario fare backup dei dati sul disco, nel senso di mantenere una copia identica di dati già memorizzati altrove, in quanto diversi sistemi di codici permettono il rilevamento e/o la correzione di errori.&lt;br /&gt;
# Se in un grafo di Holt multirisorsa esiste un ciclo tra più processi e risorse, ciò non significa che allo stesso tempo non siano coinvolti processi con archi esclusivamente entranti. Ogni processo appartenente a questa categoria non è in attesa di risorse, e può dunque procedere con i suoi calcoli; quando avrà terminato rilascerà le risorse precedentemente allocategli, eventualmente sbloccando uno dei processi coinvolti nel ciclo.&lt;br /&gt;
&lt;br /&gt;
= Esame 21/06/2018 =&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2018.06.21.tot.pdf 2018.06.21.tot.pdf]&lt;br /&gt;
=== Esercizio c.1 (sbagliato) ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
/* Monitor tmon */&lt;br /&gt;
&lt;br /&gt;
define MAX n;&lt;br /&gt;
define TERRAFERMA 1;&lt;br /&gt;
define ISOLA 2;&lt;br /&gt;
&lt;br /&gt;
semaphore ok2unload;&lt;br /&gt;
semaphore ok2load;&lt;br /&gt;
semaphore ok2ship;&lt;br /&gt;
semaphore mutex(1); // la rampa è zona critica --&amp;gt; mutua esclusione&lt;br /&gt;
&lt;br /&gt;
stack ferry;&lt;br /&gt;
int current_port = 0;&lt;br /&gt;
&lt;br /&gt;
Procedure entry: al_porto(int location)&lt;br /&gt;
{&lt;br /&gt;
    current_port = location; // traghetto arriva a destinazione&lt;br /&gt;
    ok2unload.signal(); // da il via per far sbarcare le macchine&lt;br /&gt;
    ok2ship.wait(); // si ferma&lt;br /&gt;
    current_port = 0; // traghetto sta viaggiando tra i due porti&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: imbarca(int location)&lt;br /&gt;
{&lt;br /&gt;
    mutex.wait(); // prende possesso della rampa&lt;br /&gt;
    ferry.push(1); // sale sul traghetto&lt;br /&gt;
    mutex.signal(); // libera la rampa&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: imbarcato(int location)&lt;br /&gt;
{&lt;br /&gt;
    if(ferry.lenght() == MAX) // se il traghetto è pieno da il via per farlo salpare&lt;br /&gt;
    {&lt;br /&gt;
        ok2load.wait();&lt;br /&gt;
        ok2ship.signal();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: sbarca(int location)&lt;br /&gt;
{&lt;br /&gt;
    mutex.wait(); // prende possesso della rampa&lt;br /&gt;
    ferry.pop(); // scende dal traghetto&lt;br /&gt;
    mutex.signal(); // libera la rampa&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: sbarcato(int location)&lt;br /&gt;
{&lt;br /&gt;
    if(ferry.lenght() == 0) // se il traghetto è vuoto da il via per far imbarcare le macchine&lt;br /&gt;
    {&lt;br /&gt;
        ok2unload.wait();&lt;br /&gt;
        ok2load.signal();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.1 ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
/* Monitor tmon */&lt;br /&gt;
 &lt;br /&gt;
#define MAX n&lt;br /&gt;
#define NONE 0&lt;br /&gt;
#define TERRAFERMA 1&lt;br /&gt;
#define ISOLA 2&lt;br /&gt;
 &lt;br /&gt;
condition ok2unload;&lt;br /&gt;
condition ok2load[2];&lt;br /&gt;
condition ok2ship;&lt;br /&gt;
condition empty;&lt;br /&gt;
 &lt;br /&gt;
int onboard = 0;&lt;br /&gt;
int onramp = 0;&lt;br /&gt;
int current_port = NONE;&lt;br /&gt;
&lt;br /&gt;
Procedure entry: al_porto(int location)&lt;br /&gt;
{&lt;br /&gt;
    //arrivando&lt;br /&gt;
    current_port = location;&lt;br /&gt;
    ok2unload.signal();&lt;br /&gt;
    if (onboard &amp;gt; 0)&lt;br /&gt;
        empty.wait()&lt;br /&gt;
    ok2load[location].signal()&lt;br /&gt;
    if (onboard &amp;lt; MAX)&lt;br /&gt;
        ok2ship.wait()&lt;br /&gt;
    //partendo&lt;br /&gt;
    current_port = NONE;&lt;br /&gt;
}&lt;br /&gt;
 &lt;br /&gt;
Procedure entry: imbarca(int location)&lt;br /&gt;
{&lt;br /&gt;
    if (current_port != location || onramp &amp;gt; 0 || onboard &amp;gt;= MAX)&lt;br /&gt;
        ok2load[location].wait()&lt;br /&gt;
    onramp = 1;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure entry: imbarcato(int location)&lt;br /&gt;
{&lt;br /&gt;
    onramp = 0; onboard++;&lt;br /&gt;
    if (onboard &amp;lt; MAX)&lt;br /&gt;
        ok2load[location].signal();&lt;br /&gt;
    else&lt;br /&gt;
        ok2ship.signal();&lt;br /&gt;
}&lt;br /&gt;
 &lt;br /&gt;
Procedure entry: sbarca(int location)&lt;br /&gt;
{&lt;br /&gt;
    if (current_port != location || onramp &amp;gt; 0)&lt;br /&gt;
        ok2unload.wait()&lt;br /&gt;
    onramp = 1;&lt;br /&gt;
}&lt;br /&gt;
 &lt;br /&gt;
Procedure entry: sbarcato(int location)&lt;br /&gt;
{&lt;br /&gt;
    onramp = 0; onboard--;&lt;br /&gt;
    if (onboard == 0)&lt;br /&gt;
        empty.signal();&lt;br /&gt;
    else&lt;br /&gt;
        ok2unload.signal();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.2 (sbagliato) ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define N n // limite operazioni&lt;br /&gt;
semaphore mutex(1); // sezione critica&lt;br /&gt;
&lt;br /&gt;
class lim_semaphore()&lt;br /&gt;
{&lt;br /&gt;
    int value;&lt;br /&gt;
    semaphore plus;&lt;br /&gt;
    semaphore minus;&lt;br /&gt;
    &lt;br /&gt;
    P()&lt;br /&gt;
    {&lt;br /&gt;
        mutex.P();&lt;br /&gt;
        if(value &amp;lt; N)&lt;br /&gt;
        {&lt;br /&gt;
            if (value &amp;gt;= 0)&lt;br /&gt;
            {&lt;br /&gt;
                plus.P();&lt;br /&gt;
            }&lt;br /&gt;
            else&lt;br /&gt;
            {&lt;br /&gt;
                minus.V();&lt;br /&gt;
            }&lt;br /&gt;
            value--;&lt;br /&gt;
        }&lt;br /&gt;
        mutex.V();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    V()&lt;br /&gt;
    {&lt;br /&gt;
        mutex.P();&lt;br /&gt;
        if(value &amp;gt; -N)&lt;br /&gt;
        {&lt;br /&gt;
            if (value &amp;lt;= 0)&lt;br /&gt;
            {&lt;br /&gt;
                minus.P();&lt;br /&gt;
            } &lt;br /&gt;
            else&lt;br /&gt;
            {&lt;br /&gt;
                plus.V();&lt;br /&gt;
            }&lt;br /&gt;
            value++;&lt;br /&gt;
        }&lt;br /&gt;
        mutex.V();        &lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.2 ===&lt;br /&gt;
==== Soluzione &amp;quot;furba e facile&amp;quot; ====&lt;br /&gt;
* Visto dall'utente [[User:Acsor|Acsor]] ([[User talk:Acsor|talk]]) in data 18:53, 9 September 2020 (CEST). Ritengo sia: corretto (perché l'ho fatto pressappoco uguale). (Ritengo anche che possedere strumenti di analisi formale per verificare la correttezza di codice simile sarebbe di grande ausilio.)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
class bounded_semaphore {&lt;br /&gt;
    semaphore plus;&lt;br /&gt;
    semaphore minus;&lt;br /&gt;
    int value;   // serve per significato&lt;br /&gt;
    &lt;br /&gt;
    bounded_semaphore (int initval, unsigned maxval) {&lt;br /&gt;
        value = initval;&lt;br /&gt;
        plus = new semaphore(maxval + initval);&lt;br /&gt;
        minus = new semaphore(maxval - initval);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void P() {&lt;br /&gt;
        plus.P();&lt;br /&gt;
        value--;&lt;br /&gt;
        minus.V(); &lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void V() {&lt;br /&gt;
        minus.P();&lt;br /&gt;
        value++;&lt;br /&gt;
        plus.V();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Soluzione &amp;quot;schiacciasassi&amp;quot; ====&lt;br /&gt;
Controllato da [LiberaL](https://t.me/llibera) in data 2023/05/12, perchè nel primo if della V() si fa value &amp;gt;= - maxval? non dovrebbe essere + maxval?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
class bounded_semaphore {&lt;br /&gt;
    semaphore mutex;&lt;br /&gt;
    queue&amp;lt;semaphore&amp;gt; okmin, okmax;&lt;br /&gt;
    int value;&lt;br /&gt;
    unsigned maxval;&lt;br /&gt;
&lt;br /&gt;
    bounded_semaphore (int initval, unsigned maxval) {&lt;br /&gt;
	value = initval;&lt;br /&gt;
        this.maxval = maxval;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void P() {&lt;br /&gt;
        mutex.P();&lt;br /&gt;
&lt;br /&gt;
        if (value &amp;lt;= -maxval)  {&lt;br /&gt;
            s=semaphore(0);&lt;br /&gt;
            okmin.enqueue(s);&lt;br /&gt;
            mutex.V();&lt;br /&gt;
            s.P();&lt;br /&gt;
        } else if (okmax.length() &amp;gt; 0) {&lt;br /&gt;
            s = okmax.dequeue()&lt;br /&gt;
            s.V();&lt;br /&gt;
            mutex.V();&lt;br /&gt;
        } else {&lt;br /&gt;
            value--;&lt;br /&gt;
            mutex.V();&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void V() {&lt;br /&gt;
        mutex.P();&lt;br /&gt;
&lt;br /&gt;
        if (value &amp;gt;= -maxval)  {  //qui...&lt;br /&gt;
            s=semaphore(0);&lt;br /&gt;
            okmax.enqueue(s);&lt;br /&gt;
            mutex.V();&lt;br /&gt;
            s.P();&lt;br /&gt;
        } else if (okmin.length() &amp;gt; 0) {&lt;br /&gt;
            s = okmin.dequeue()&lt;br /&gt;
            s.V();&lt;br /&gt;
            mutex.V();&lt;br /&gt;
        } else {&lt;br /&gt;
            value++;&lt;br /&gt;
            mutex.V();&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Esercizio g.1 ===&lt;br /&gt;
* Controllato dall'utente [[User:Acsor|Acsor]] ([[User talk:Acsor|talk]]), 23:17, 9 September 2020 (CEST). Ritengo sia: corretto&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
IC = 10,10,10 // Capitale iniziale&lt;br /&gt;
COH = 4,4,4   // Saldo in cassa&lt;br /&gt;
 &lt;br /&gt;
      MAX     ATT     RES    AVAIL&lt;br /&gt;
P1 | 6,6,6 | 1,1,1 | 5,5,5 | 4,4,4&lt;br /&gt;
P2 | 6,6,6 | 1,1,1 | 5,5,5 | 5,5,5&lt;br /&gt;
P3 | 9,9,9 | 4,4,4 | 5,5,5 | 6,6,6&lt;br /&gt;
 &amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Minimizzato&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
IC = 4,4,4&lt;br /&gt;
COH = 1,1,1&lt;br /&gt;
 &lt;br /&gt;
      MAX     ATT     RES  &lt;br /&gt;
P1 | 3,3,3 | 1,1,1 | 2,2,2&lt;br /&gt;
P2 | 3,3,3 | 1,1,1 | 2,2,2&lt;br /&gt;
P3 | 3,3,3 | 1,1,1 | 2,2,2&lt;br /&gt;
 &amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Esercizio g.2 (da controllare) ===&lt;br /&gt;
&lt;br /&gt;
* Visto e rimaneggiato in data 19:40, 10 September 2020 (CEST) dall'utente [[User:Acsor|Acsor]] ([[User talk:Acsor|talk]])&lt;br /&gt;
&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
&lt;br /&gt;
# Il calcolo del working set serve a determinare il numero di processi che possono essere mantenuti attivi sulla base del limite della memoria principale, più precisamente del suo numero di frame. Può essere svolto ad ogni page fault, ossia quando un processo tra quelli attivi richiede una pagina non presente in memoria, o prima di avviare un nuovo processo.&lt;br /&gt;
# La lunghezza massima di un file che può essere memorizzato su un file system di tipo FAT viene calcolata moltiplicando il massimo numero di cluster (dimensione dell'unità di allocazione) identificabili per la loro dimensione. Il massimo numero di cluster identificabili dipende da quanti bit sono allocati per numerarli, e per questa distinzione esistono varie versioni di FAT (FAT12, FAT16, FAT32).&lt;br /&gt;
## FAT32 memorizza la dimensione dei file in un intero unsigned da 32bit, e non può quindi gestire un file di dimensione superiore ai 2^32 bit = ~4GB.&lt;br /&gt;
## FAT16, allocando 16bit per identificare i cluster, può contarne al massimo 2^16 (65536). Prendendo quindi, ad esempio, un file system FAT16 con cluster da 32KB, possiamo avere file grandi al massimo 32KB*65536 = ~2GB.&lt;br /&gt;
## FAT12 di conseguenza può numerare al massimo 2^12 (4096) cluster, ma dato che il numero dei settori del disco viene memorizzato in un intero signed a 16bit, la massima dimensione del disco è 2^15 = 32MB. Ovviamente, non si può memorizzare un file di grandezza superiore alla dimensione dell'unità di memorizzazione stessa, e quindi anche i file in FAT12 possono avere dimensione massima di 32MB.&lt;br /&gt;
# Entrambi condividono l'intento di infettare host con codice malevolo, ma differiscono fondamentalmente nella modalità: i virus infettano programmi già esistenti mediante un ''virus dropper'', mentre i worm diffondono copie di se stessi, solitamente attraverso la rete.&lt;br /&gt;
# In vari casi sulla base della natura del sistema. Innanzitutto, in sistemi batch ciò avviene se non sono stati inseriti più processi per un certo lasso di tempo. In sistemi general-purpose (es. per PC o dispositivi mobili) tale condizione è verificabile se tutti i processi sono in attesa su una coda che non è quella dello scheduler (ad. es. di un semaforo o di una periferica di I/O); casi concreti sono pertanto il deadlock (di tutti i processi del sistema) o attesa generale di I/O. Infine sempre in sistemi general-purpose tale condizione può manifestarsi, stavolta in condizioni patologiche, se ogni processo è assegnato ad una propria CPU/core, lasciando pertanto la coda d'attesa vuota.&lt;br /&gt;
&lt;br /&gt;
= Esame 28/05/2018 =&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2018.05.28.tot.pdf 2018.05.28.tot.pdf]&lt;br /&gt;
=== Esercizio c.1 ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
Stack&amp;lt;int&amp;gt; entriesStack;&lt;br /&gt;
&lt;br /&gt;
int vid[MAX];&lt;br /&gt;
condition ok2esci[MAX]&lt;br /&gt;
int in = 0; &lt;br /&gt;
int out = -1;&lt;br /&gt;
&lt;br /&gt;
Procedure-entry: entra(int id) {&lt;br /&gt;
    if (in &amp;gt;= MAX)&lt;br /&gt;
        ok2entra.wait()&lt;br /&gt;
    vid[in++] = id;&lt;br /&gt;
    if (in &amp;lt; MAX)&lt;br /&gt;
        ok2entra.signal()&lt;br /&gt;
    else&lt;br /&gt;
        out = MAX - 1;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Procedure-entry: esci(int id) {&lt;br /&gt;
    int i;&lt;br /&gt;
    for (i = 0; i &amp;lt; in; i++)&lt;br /&gt;
        if (vid[i] == id)&lt;br /&gt;
            break; //cerco l'indice di id nel vettore vid&lt;br /&gt;
&lt;br /&gt;
    if (i != out)&lt;br /&gt;
        ok2esci[i].wait();&lt;br /&gt;
&lt;br /&gt;
    if (out &amp;gt; 0) {&lt;br /&gt;
        out--;&lt;br /&gt;
        ok2esci[out].signal();&lt;br /&gt;
    } else {&lt;br /&gt;
        out--;&lt;br /&gt;
        in = 0; &lt;br /&gt;
        ok2entra.signal();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.1 (da controllare) ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
Monitor riempisvuota {&lt;br /&gt;
    Int MAXPROCESSI;&lt;br /&gt;
    Stack s;&lt;br /&gt;
    condition ok2enter;&lt;br /&gt;
    condition ok2exit;&lt;br /&gt;
 &lt;br /&gt;
    p.e void entra(getPid()){ &lt;br /&gt;
        if( s.size() &amp;gt;= MAXPROCESSI)&lt;br /&gt;
            ok2enter.wait();&lt;br /&gt;
        s.insert(getPid());&lt;br /&gt;
        if(s.size() &amp;gt; MAXPROCESSI)&lt;br /&gt;
            ok2exit.signal() &lt;br /&gt;
    }&lt;br /&gt;
 &lt;br /&gt;
    p.e void esci(getPid()){ &lt;br /&gt;
        if(s.size() &amp;gt; MAXPROCESSI &amp;amp;&amp;amp; s.top == getPid()) {&lt;br /&gt;
            s.pop();&lt;br /&gt;
            ok2entra.signal()&lt;br /&gt;
        }&lt;br /&gt;
        else&lt;br /&gt;
            ok2exit.wait();&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
=== Esercizio c.2 (ERRATO) ===&lt;br /&gt;
&lt;br /&gt;
* Soluzione proposta è errata, non puoi riceve in modo greedy e printare subito il carattere [[User:Flecart|Flecart]] ([[User talk:Flecart|talk]]) 11:33, 18 January 2023 (CET)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
proc[x]: x='a',...,'z'&lt;br /&gt;
 while True:&lt;br /&gt;
  //c sarà il carattere stampato dal processo precedente&lt;br /&gt;
  (c, string) = arecv(*)&lt;br /&gt;
  if(string == wait){&lt;br /&gt;
    //mi metto in attesa di ricevere l'ACK da proc[x]&lt;br /&gt;
    m=arecv(x);&lt;br /&gt;
  }&lt;br /&gt;
  if (c == NONE){&lt;br /&gt;
    //significa che sei il primo a ricevere quella stringa&lt;br /&gt;
    print(x);&lt;br /&gt;
    if (len(string) &amp;gt; 1){&lt;br /&gt;
      //mando la wait a tutti, il primo che riceve qualcosa da stampare manda una wait a tutti&lt;br /&gt;
      asend(wait,*);&lt;br /&gt;
      int l = len(string);&lt;br /&gt;
      int i = 1;&lt;br /&gt;
      while(l != 0){&lt;br /&gt;
        asend(proc[string[i]], (x, string[i...]));&lt;br /&gt;
        //si mette in attesa di ricevere l'ACK dal processo dell'ultima lettera della parola&lt;br /&gt;
        m=areceive(proc[string[i]]);&lt;br /&gt;
        //rimando la wait al processo per ribloccarlo&lt;br /&gt;
        asend(wait, proc[string[i]])&lt;br /&gt;
        l--;&lt;br /&gt;
        i++;&lt;br /&gt;
      }&lt;br /&gt;
      //dopo aver finito la stampa della stringa sblocco tutti i processi&lt;br /&gt;
      asend(ACK, *);&lt;br /&gt;
    }&lt;br /&gt;
  }else{&lt;br /&gt;
    print(x);&lt;br /&gt;
    asend(ACK, x);&lt;br /&gt;
    //ricomincia il ciclo while, si rimette in attesa e il 'gestore gli rimanda la wait'&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.2  ===&lt;br /&gt;
[[User:Flecart|Flecart friend]] ([[User talk:Flecart|talk]]) cedo la proprità intellettuale di questa soluzione a flecart&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
process [x]: x='a'..'z'&lt;br /&gt;
  if(x=='a'){&lt;br /&gt;
    asend(&amp;lt;NULL,NULL&amp;gt;,'b');&lt;br /&gt;
    asend(&amp;lt;NULL,NULL&amp;gt;,'b');&lt;br /&gt;
  }&lt;br /&gt;
  While True:&lt;br /&gt;
    &amp;lt;c,string&amp;gt;=arecv(x-1+26%26);&lt;br /&gt;
    if(string==NULL):&lt;br /&gt;
      &amp;lt;c,string&amp;gt;=arecv(*);&lt;br /&gt;
      if(string!=NULL):&lt;br /&gt;
        &amp;lt;c,string&amp;gt;=arecv(x-1+26%26);&lt;br /&gt;
&lt;br /&gt;
    if(string!=NULL):&lt;br /&gt;
      if(string[0]==x):&lt;br /&gt;
        print(string[0]);&lt;br /&gt;
        if(string.len()&amp;gt;1):&lt;br /&gt;
          aasend(&amp;lt;NULL,string[1:]&amp;gt;,(x+1)%26);&lt;br /&gt;
        else:&lt;br /&gt;
          aasend(&amp;lt;NULL,NULL&amp;gt;,(x+1)%26);&lt;br /&gt;
          aasend(&amp;lt;NULL,NULL&amp;gt;,(x+1)%26);&lt;br /&gt;
      else:&lt;br /&gt;
          aasend(&amp;lt;NULL,string&amp;gt;,(x+1)%26);&lt;br /&gt;
    else:&lt;br /&gt;
      aasend(&amp;lt;NULL,NULL&amp;gt;,(x+1)%26);&lt;br /&gt;
      aasend(&amp;lt;NULL,NULL&amp;gt;,(x+1)%26);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Proposta c2 ===&lt;br /&gt;
* Proposto [[User:Flecart|Flecart]] ([[User talk:Flecart|talk]]) 11:31, 18 January 2023 (CET)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
proc[a]:&lt;br /&gt;
	bool occupied = false;&lt;br /&gt;
	queue&amp;lt;string&amp;gt; s;&lt;br /&gt;
	&lt;br /&gt;
	while True {&lt;br /&gt;
		(c, string) = arecv(*);&lt;br /&gt;
		&lt;br /&gt;
		if (c == NONE) {&lt;br /&gt;
			if (occupied) {&lt;br /&gt;
				s.enqueue(string);&lt;br /&gt;
			} else {&lt;br /&gt;
				if (string.len() &amp;lt; 1)&lt;br /&gt;
					continue;&lt;br /&gt;
			&lt;br /&gt;
				occupied = true;&lt;br /&gt;
				asend(string[0], (MIDDLE, string));&lt;br /&gt;
			}&lt;br /&gt;
		} else if (c == END) {&lt;br /&gt;
			if (s.size() &amp;gt; 0) {&lt;br /&gt;
				string ss = s.dequeue();&lt;br /&gt;
				asend(string[0], (MIDLLE, string));&lt;br /&gt;
			} else {&lt;br /&gt;
				occupied = false;&lt;br /&gt;
			}&lt;br /&gt;
		} else {&lt;br /&gt;
			print(x);&lt;br /&gt;
			if (len(string) &amp;gt; 1) &lt;br /&gt;
				asend(proc[string[0]], (MIDDLE, string[1:]));&lt;br /&gt;
			else:&lt;br /&gt;
				asend(proc[a], (END, &amp;quot;&amp;quot;));&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
		&lt;br /&gt;
proc[x]: x = 'b', ... 'z';&lt;br /&gt;
	while True {&lt;br /&gt;
		(c, string) = arecv(*);&lt;br /&gt;
		if (c == NONE) {&lt;br /&gt;
			asend(proc['a'], (NONE, string));&lt;br /&gt;
		} else {  // potrà essere solo MIDDLE&lt;br /&gt;
			print(x);&lt;br /&gt;
			if (len(string) &amp;gt; 1) &lt;br /&gt;
				asend(proc[string[0]], (MIDDLE, string[1:]));&lt;br /&gt;
			else:&lt;br /&gt;
				asend(proc[a], (END, &amp;quot;&amp;quot;));&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Esame 12/02/2018 =&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2018.02.12.tot.pdf 2018.02.12.tot.pdf]&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.1 (da controllare) ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
monitor bridge:&lt;br /&gt;
&lt;br /&gt;
    int ncar&lt;br /&gt;
    bool boat_on_0&lt;br /&gt;
    bool boat_on_1       // per semplicità, quando nel codice si trova boat_on_(direction) oppure isBoat(direction)(),&lt;br /&gt;
                         // si valuta il valore booleano di direction e lo si applica sotto forma di stringa al simbolo&lt;br /&gt;
                         // ad esso adiacente&lt;br /&gt;
    bool is_raised&lt;br /&gt;
    queue waiting_mean   // i valori possibili sono: boat0, boat1 oppure car&lt;br /&gt;
    condition ok2go&lt;br /&gt;
  &lt;br /&gt;
    entry car_enter(direction): &lt;br /&gt;
        if is_raised || ncar == MAXCAR:&lt;br /&gt;
            waiting_mean.enqueue(car)&lt;br /&gt;
            ok2go.wait()&lt;br /&gt;
        is_raised = false&lt;br /&gt;
        ++ncar&lt;br /&gt;
  &lt;br /&gt;
    entry car_exit(direction):&lt;br /&gt;
        --ncar&lt;br /&gt;
        if (waiting_mean.top().isBoat() &amp;amp;&amp;amp; ncar == 0) || waiting_mean.top().isCar():    // isBoat ritorna true se l'oggetto su cui&lt;br /&gt;
            waiting_mean.dequeue()                                                      // è invocata è boat0 oppure boat1&lt;br /&gt;
            ok2go.signal()&lt;br /&gt;
  &lt;br /&gt;
    entry boat_enter(direction):&lt;br /&gt;
        if !is_raised || boat_on_(direction):&lt;br /&gt;
            waiting_mean.enqueue(boat)&lt;br /&gt;
            ok2go.wait()&lt;br /&gt;
        if waiting_mean.top().isBoat(!direction)():&lt;br /&gt;
            waiting_mean.dequeue()&lt;br /&gt;
            ok2go.signal()&lt;br /&gt;
        is_raised = true&lt;br /&gt;
        boat_on_(direction) = true&lt;br /&gt;
  &lt;br /&gt;
    entry boat_exit(direction):&lt;br /&gt;
        boat_on_(direction) = false&lt;br /&gt;
        if !boat_on_(!direction):&lt;br /&gt;
            waiting_mean.dequeue()&lt;br /&gt;
            ok2go.signal()&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.1 ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
monitor bridge  {&lt;br /&gt;
  int carsOnBridge = 0;&lt;br /&gt;
  int shipping[2] = {0, 0}; //navi da entrambe le direzioni&lt;br /&gt;
  int status = NONE; //UP DOWN NONE&lt;br /&gt;
  int last2pass = 0;     //ultimo che ha passato il ponte&lt;br /&gt;
  int waitingC = 0;      //coda delle macchine che aspettano&lt;br /&gt;
  int waitingS[2] = {0,0};  //navi che stanno aspettando&lt;br /&gt;
   &lt;br /&gt;
  condition ok2ship[2]&lt;br /&gt;
  condition ok2drive&lt;br /&gt;
 &lt;br /&gt;
entry car_enter(int direction){&lt;br /&gt;
    if(carsOnBridge &amp;gt;= MAX || status == UP || waitingS[0] + waitingS[1] &amp;gt; 0 ){&lt;br /&gt;
        waitingC++;ok2drive.wait;waitingC--;}&lt;br /&gt;
    status = DOWN;&lt;br /&gt;
    carsOnBridge++&lt;br /&gt;
    if (carsOnBridge &amp;lt; MAX)&lt;br /&gt;
       ok2drive.signal();     //vanno tutte le MAX car che stanno aspettando&lt;br /&gt;
} &lt;br /&gt;
entry car_exit(int direction){&lt;br /&gt;
    carsOnBridge--&lt;br /&gt;
    if (waitingS[0] + waitingS[1] == 0)&lt;br /&gt;
    ok2drive.signal();&lt;br /&gt;
    if(carsOnBridge == 0){&lt;br /&gt;
        ok2ship[0].signal(); ok2ship[1].signal();&lt;br /&gt;
    }&lt;br /&gt;
    if(carsOnBridge + waitingS[0] + waitingS[1] == 0) &lt;br /&gt;
    status = NONE&lt;br /&gt;
}&lt;br /&gt;
 &lt;br /&gt;
entry ship_enter(int direction){&lt;br /&gt;
    if (bridge = DOWN || shipping[direction] != 0 || waitingC &amp;gt; 0)&lt;br /&gt;
    {&lt;br /&gt;
        waitingS[i]++; ok2ship[i].wait(); waitingS[i]--; &lt;br /&gt;
    }&lt;br /&gt;
    isBridgeUp = false;&lt;br /&gt;
    shipping[i] = 1;&lt;br /&gt;
 &lt;br /&gt;
entry ship_exit(int direction){&lt;br /&gt;
      shipping[i] = 0;&lt;br /&gt;
      if (waitingC == 0)&lt;br /&gt;
          ok2ship[i].signal()&lt;br /&gt;
      else if(shipping[1-i] == 0)&lt;br /&gt;
          ok2drive.signal();&lt;br /&gt;
      if(carsOnBridge + waitingS[0] + waitingS[1] == 0) &lt;br /&gt;
      status = NONE&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.1 (da controllare) ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
monitor bridge {&lt;br /&gt;
&lt;br /&gt;
  UP=0;&lt;br /&gt;
  DOWN=1;&lt;br /&gt;
  bridgeis = DOWN;&lt;br /&gt;
&lt;br /&gt;
  bool carAreExiting = false;&lt;br /&gt;
&lt;br /&gt;
  condition ok2drive;&lt;br /&gt;
  condition ok2barca[2];&lt;br /&gt;
&lt;br /&gt;
  waitingCar = 0;&lt;br /&gt;
  carOnBridge = 0;&lt;br /&gt;
&lt;br /&gt;
  boatWaiting[2] = {0,0};&lt;br /&gt;
  boatIsPassing[2] = {false,false}&lt;br /&gt;
&lt;br /&gt;
  entry car_enter(direction) {&lt;br /&gt;
&lt;br /&gt;
    if (bridgeis == DOWN)&lt;br /&gt;
      if(carOnBridge == MAXCAR)&lt;br /&gt;
        waitingCar++;&lt;br /&gt;
        ok2drive.wait();&lt;br /&gt;
        waitingCar--;&lt;br /&gt;
      else if (carAreExiting)&lt;br /&gt;
        waitingCar++;&lt;br /&gt;
        ok2drive.wait();&lt;br /&gt;
        waitingCar--;&lt;br /&gt;
    else &lt;br /&gt;
      if (boatIsPassing[0] || boatIsPassing[1])&lt;br /&gt;
        waitingCar++;&lt;br /&gt;
        ok2drive.wait();&lt;br /&gt;
        waitingCar--;&lt;br /&gt;
        bridgeis = DOWN;&lt;br /&gt;
&lt;br /&gt;
    carOnBridge++;&lt;br /&gt;
    carAreExiting = false;&lt;br /&gt;
    if(carOnBridge &amp;lt; MAXCAR &amp;amp;&amp;amp; !carAreExiting) &lt;br /&gt;
      ok2drive.signal();&lt;br /&gt;
      &lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  entry car_exit(direction) {&lt;br /&gt;
&lt;br /&gt;
    carOnBridge--;&lt;br /&gt;
    carAreExiting = true;&lt;br /&gt;
&lt;br /&gt;
    if(carOnBridge == 0)&lt;br /&gt;
      carAreExiting = false;&lt;br /&gt;
      if(boatWaiting[0] &amp;gt; 0)&lt;br /&gt;
        bridgeis = UP;&lt;br /&gt;
        ok2barca[0].signal();&lt;br /&gt;
      else if (boatWaiting[1] &amp;gt; 0)&lt;br /&gt;
        bridgeis = UP;&lt;br /&gt;
        ok2barca[1].signal();&lt;br /&gt;
      else &lt;br /&gt;
        ok2drive.signal();&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  entry boat_enter(direction) {&lt;br /&gt;
&lt;br /&gt;
    if (bridgeis == UP)&lt;br /&gt;
    | if (boatIsPassing[direction] == true)&lt;br /&gt;
    | |  boatWaiting[direction]++;&lt;br /&gt;
    | |  ok2barca.wait();&lt;br /&gt;
    | |  boatWaiting[direction]--;&lt;br /&gt;
    else &lt;br /&gt;
    | if (carOnBridge &amp;gt; 0)&lt;br /&gt;
    | | boatWaiting[direction]++;&lt;br /&gt;
    | | ok2barca.wait();&lt;br /&gt;
    | | boatWaiting[direction]--;&lt;br /&gt;
    | | bridgeis = UP;&lt;br /&gt;
&lt;br /&gt;
    boatIsPassing[direction] = true;&lt;br /&gt;
&lt;br /&gt;
    if(boatIsPassing[1-direction] == false &amp;amp;&amp;amp; boatWaiting[1-direction] &amp;gt; 0)&lt;br /&gt;
      ok2barca[1-direction].signal();&lt;br /&gt;
    &lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  entry boat_exit(direction) {&lt;br /&gt;
&lt;br /&gt;
    boatIsPassing[direction] = false;&lt;br /&gt;
&lt;br /&gt;
    if (boatIsPassing[1-direction] == false)&lt;br /&gt;
      if (waitingCar &amp;gt; 0)&lt;br /&gt;
        bridgeis = DOWN;&lt;br /&gt;
        ok2drive.signal();&lt;br /&gt;
    else&lt;br /&gt;
        if (waitingCar == 0)&lt;br /&gt;
          ok2barca[direction].signal();&lt;br /&gt;
          &lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.1 (sbagliato) ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
monitor bridge&lt;br /&gt;
  condition ok2passCar;&lt;br /&gt;
  condition ok2passBoat;&lt;br /&gt;
  condition ok2up;&lt;br /&gt;
  condition ok2down;&lt;br /&gt;
  int carOnBridge[2] = 0; //2 sensi di marcia&lt;br /&gt;
  int boatUnderBridge[2] = 0;&lt;br /&gt;
  boolean bridge_down = false; //vuol dire che il ponte parte alzato, true ponte abbassato&lt;br /&gt;
  &lt;br /&gt;
  procedure entry car_enter(direction){&lt;br /&gt;
      if(bridge_down &amp;amp;&amp;amp; carOnBridge[direction] &amp;lt; MAXCAR){&lt;br /&gt;
        carOnBridge[direction]++;&lt;br /&gt;
        ok2passCar.signal();&lt;br /&gt;
      }else if (bridge_down &amp;amp;&amp;amp; boatUnderBridge[0] == 0 &amp;amp;&amp;amp; boatUnderBridge[1] == 0){&lt;br /&gt;
        //se non ci sono navi in transito e arriva una macchina abbassa ponte&lt;br /&gt;
        ok2down.signal();&lt;br /&gt;
        ok2passCar.signal();&lt;br /&gt;
        ok2passBoat.wait();&lt;br /&gt;
      }else{&lt;br /&gt;
        ok2passCar.wait();&lt;br /&gt;
      }&lt;br /&gt;
  }     &lt;br /&gt;
        &lt;br /&gt;
  procedure entry car_exit(direction){&lt;br /&gt;
      carOnBridge[direction]--;&lt;br /&gt;
      if(carOnBridge[0] == 0 &amp;amp;&amp;amp; carOnBridge[1] == 0){&lt;br /&gt;
        bridge_down = false;&lt;br /&gt;
        ok2up.signal();&lt;br /&gt;
      }else{&lt;br /&gt;
        ok2up.wait();&lt;br /&gt;
      }&lt;br /&gt;
  }&lt;br /&gt;
      &lt;br /&gt;
  procedure entry boat_enter(direction){&lt;br /&gt;
      if(!bridge_down &amp;amp;&amp;amp; boatUnderBridge[direction] &amp;lt; 1){&lt;br /&gt;
        boatUnderBridge[direction]++;&lt;br /&gt;
        ok2passBoat.signal();&lt;br /&gt;
      }else if(!bridge_down &amp;amp;&amp;amp; carOnBridge[0] == 0 &amp;amp;&amp;amp; carOnBridge[1] == 0){&lt;br /&gt;
        ok2up.signal();&lt;br /&gt;
        ok2passBoat.signal();&lt;br /&gt;
        ok2passCar.wait();&lt;br /&gt;
      }else {&lt;br /&gt;
        ok2passBoat.wait();&lt;br /&gt;
      }&lt;br /&gt;
  }&lt;br /&gt;
      &lt;br /&gt;
  procedure entry boat_exit(direction){  &lt;br /&gt;
      boatUnderBridge[direction]--;&lt;br /&gt;
      if(boatUnderBridge[0] == 0 &amp;amp;&amp;amp; boatUnderBridge[1] == 0){&lt;br /&gt;
        bridge_down = true;&lt;br /&gt;
        ok2down.signal();&lt;br /&gt;
      }else{&lt;br /&gt;
        ok2down.wait();&lt;br /&gt;
      }&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.1 2o (sbagliato) ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define car 1&lt;br /&gt;
#define ship 2 &lt;br /&gt;
#define fromDX 1&lt;br /&gt;
#define fromSX 0&lt;br /&gt;
&lt;br /&gt;
monitor bridge  {&lt;br /&gt;
  int carsOnBridge = 0;&lt;br /&gt;
  int shippingDX = 0; //nave che sta passando dal lato destro&lt;br /&gt;
  int shippingSX = 0; //nave che sta passando dal lato sinistro&lt;br /&gt;
  bool isBridgeUp = false;&lt;br /&gt;
  int last2pass = 0;     //ultimo che ha passato il ponte&lt;br /&gt;
  int waitingS = 0;  //navi che stanno aspettando&lt;br /&gt;
  int waitingC = 0 ; //auto che stanno aspettando&lt;br /&gt;
  &lt;br /&gt;
  condition ok2ship&lt;br /&gt;
  condition ok2drive&lt;br /&gt;
&lt;br /&gt;
entry car_enter(int direction){&lt;br /&gt;
    //un auto si ferma se il numero di auto sul ponte è massimo&lt;br /&gt;
    //e se l'ultima a passare è stata un auto mentre ci sono navi in attesa&lt;br /&gt;
    if(carsOnBridge == MAX || isBridgeUp || (last2pass==car &amp;amp;&amp;amp; waitingS &amp;gt; 0) ){&lt;br /&gt;
        waitingC++;&lt;br /&gt;
        ok2drive.wait;&lt;br /&gt;
    }&lt;br /&gt;
    carsOnBridge++;&lt;br /&gt;
    waitingC--;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
entry car_exit(int direction){&lt;br /&gt;
    carsOnBridge--;&lt;br /&gt;
    last2pass = car;&lt;br /&gt;
    if(carsOnBridge == 0 &amp;amp;&amp;amp; waitingS&amp;gt;0){&lt;br /&gt;
        isBrigdeUp = true;&lt;br /&gt;
        ok2ship.signal;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
entry ship_enter(int direction){&lt;br /&gt;
    //se la barca viene da destra&lt;br /&gt;
    if(direction == fromDX){&lt;br /&gt;
        //si ferma anche quando c'è una nave che sta già attraversando nella sua stessa direzione&lt;br /&gt;
        if (isBridgeup == false || shippingDX || (last2pass==ship &amp;amp;&amp;amp; waitingC &amp;gt; 0) ){&lt;br /&gt;
            waitingS++;&lt;br /&gt;
            ok2ship.wait;&lt;br /&gt;
        }&lt;br /&gt;
        if (waitingS &amp;gt; 0)&lt;br /&gt;
            waitingS--;&lt;br /&gt;
        shippingDX = 1;&lt;br /&gt;
        }&lt;br /&gt;
    //se la barca viene da sinistra&lt;br /&gt;
    else if(direction == fromSX){&lt;br /&gt;
        if (isBridgeup == false || shippingSX || ( (last2pass==ship &amp;amp;&amp;amp; waitingC &amp;gt; 0))){&lt;br /&gt;
        waitingS++;&lt;br /&gt;
        ok2ship.wait;&lt;br /&gt;
        }&lt;br /&gt;
        if (waitingS &amp;gt; 0)&lt;br /&gt;
            waitingS--;        &lt;br /&gt;
        shippingSX = 1;&lt;br /&gt;
    &lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
entry ship_exit(int direction){&lt;br /&gt;
        if(direction == fromDX)&lt;br /&gt;
            shippingDX = 0;&lt;br /&gt;
        else if (direction == fromSX)&lt;br /&gt;
            shippingSX = 0;&lt;br /&gt;
        last2pass = ship;&lt;br /&gt;
        if(shippingDX == 0 &amp;amp;&amp;amp; shippingSX == 0 &amp;amp;&amp;amp; waitingC)&lt;br /&gt;
            isBrigdeUp == false;&lt;br /&gt;
            ok2drive.signal;&lt;br /&gt;
        else if(shippingDX == 0 &amp;amp;&amp;amp; shippingSX == 0 &amp;amp;&amp;amp; waitingS &amp;gt; 0)&lt;br /&gt;
            ok2ship.signal;    &lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.2 (sbagliato) ===&lt;br /&gt;
&lt;br /&gt;
# (Ri)Controllato dall'utente [[User:Acsor|Acsor]] ([[User talk:Acsor|talk]]) in data 26/08/2020&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
list printed_msg;  # questa è una variabile condivisa che ai fini dell'esercizio non si può utilizzare (message passing)&lt;br /&gt;
&lt;br /&gt;
process server[i]:&lt;br /&gt;
  while true:&lt;br /&gt;
    &amp;lt;msg, pid&amp;gt; = arecv(*)&lt;br /&gt;
&lt;br /&gt;
    if printed_msg.length == 0 or &amp;lt;msg, pid&amp;gt; is not in printed_msg:&lt;br /&gt;
      printed_msg.append(&amp;lt;msg,id&amp;gt;)&lt;br /&gt;
      print(msg)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.2 (da controllare) ===&lt;br /&gt;
Nello svolgimento seguente, receiver incapsula l'ambiente privato del processo; _peers rappresenta il vettore di processi &amp;quot;fratelli&amp;quot; ai quali può essere chiesto di stampare un messaggio, mentre _printed contiene l'hash di tutti i messaggi stampati dal processo locale. Si suppone che istanze della classe receiver possano essere passate come parametro ad areceive() ed asend() (non implementate).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
class receiver:&lt;br /&gt;
    def __init__(self, peers):&lt;br /&gt;
        &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
        :param peers: list of processes this process communicates with.&lt;br /&gt;
        &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
        self._peers = tuple(peers)&lt;br /&gt;
        self._printed = list()&lt;br /&gt;
    &lt;br /&gt;
    def run(self):&lt;br /&gt;
        while True:&lt;br /&gt;
            process, message = areceive(ANY)&lt;br /&gt;
&lt;br /&gt;
            if process in self._peers:&lt;br /&gt;
                self._reply_query(process, message)&lt;br /&gt;
            else:&lt;br /&gt;
                self._print(process, message)&lt;br /&gt;
&lt;br /&gt;
    def _print(self, sender, message):&lt;br /&gt;
        h = hash(message.text)&lt;br /&gt;
&lt;br /&gt;
        if h not in self._printed and not self._printed_from_peers(message):&lt;br /&gt;
            self._printed.append(h)&lt;br /&gt;
            print(message.text)&lt;br /&gt;
&lt;br /&gt;
    def _reply_query(self, sender, h):&lt;br /&gt;
        &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
        Invoked when the current process receive a &amp;quot;query&amp;quot; from a peer process.&lt;br /&gt;
        `h` contains the hash of a message which may or may have not been&lt;br /&gt;
        sent from this process; if it was sent, the reply is `Yes`, otherwise `No`.&lt;br /&gt;
        &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
        reply = &amp;quot;Yes&amp;quot; if int(h) in self._printed else &amp;quot;No&amp;quot;&lt;br /&gt;
        asend(sender, reply)&lt;br /&gt;
&lt;br /&gt;
    def _printed_from_peers(self, message):&lt;br /&gt;
        &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
        :return: `True` if this message has already been printed from any of the&lt;br /&gt;
        peer processes, `False` otherwise.&lt;br /&gt;
        &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
        h = hash(message)&lt;br /&gt;
&lt;br /&gt;
        for p in self._peers:&lt;br /&gt;
            asend(p, str(h))&lt;br /&gt;
&lt;br /&gt;
        for p in self._peers:&lt;br /&gt;
            _, reply = areceive(p)&lt;br /&gt;
&lt;br /&gt;
            if reply.text == &amp;quot;Yes&amp;quot;:&lt;br /&gt;
                return True&lt;br /&gt;
            else if reply.text != &amp;quot;No&amp;quot;:&lt;br /&gt;
                # If the response is neither &amp;quot;Yes&amp;quot; nor &amp;quot;No&amp;quot;, then we have got a query&lt;br /&gt;
                self._reply_query(p, reply)&lt;br /&gt;
&lt;br /&gt;
        return False&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Esercizio g.1 (da controllare) ===&lt;br /&gt;
Sulla base dei valori in entrata, è possibile costruire le matrici Allocation (q.tà di risorse allocate per processo e per tipo), Need (q.tà di risorse che ogni processo potrebbe ancora chiedere) e il vettore Available (num. di risorse correntemente disponibili).&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;float: left&amp;quot;&lt;br /&gt;
! colspan=3 | Allocation&lt;br /&gt;
|-&lt;br /&gt;
   !   !! A !! B&lt;br /&gt;
|-&lt;br /&gt;
   | p1 || 4 || 5&lt;br /&gt;
|-&lt;br /&gt;
   | p2 || 3 || 3&lt;br /&gt;
|-&lt;br /&gt;
   | p3 || 2 || 4&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;float: left; margin-left: 1em&amp;quot;&lt;br /&gt;
! colspan=3 | Need&lt;br /&gt;
|-&lt;br /&gt;
   !    !! A !! B&lt;br /&gt;
|-&lt;br /&gt;
   | p1 || 6 || 8&lt;br /&gt;
|-&lt;br /&gt;
   | p2 || 6 || 3&lt;br /&gt;
|-&lt;br /&gt;
   | p3 || 6 || 8&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;float: left; margin-left: 1em&amp;quot;&lt;br /&gt;
! colspan=2 | Available&lt;br /&gt;
|-&lt;br /&gt;
   ! A !! B&lt;br /&gt;
|-&lt;br /&gt;
   | x || y&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nel caso delle risorse di tipo A, deve aversi x &amp;gt;= 6 in quanto un processo dovrà essere selezionato come primo nella permutazione dell'algoritmo del banchiere multivaluta, e tutti quelli correnti hanno lo stesso valore Need(i)(1); per ciò che riguarda le risorse di tipo B, possiamo ragionare per esaustione&lt;br /&gt;
&lt;br /&gt;
* Se il primo processo della permutazione è p1, allora y &amp;gt;= 8 (con questo valore posso soddisfare la richiesta di p1 e in seguito tutte le altre)&lt;br /&gt;
* Se il primo processo della permutazione è p2, allora y &amp;gt;= 5: con questo valore è possibile soddisfare la richiesta di p2; una volta che esso avrà finito, restituirà 3 unità della risorsa B, che permetteranno di soddisfare sia le richieste di A sia quelle di C&lt;br /&gt;
* Se il primo processo della permutazione è p3, allora y &amp;gt;= 8 (ragionamento analogo come per p1)&lt;br /&gt;
&lt;br /&gt;
Volendo scegliere il minimo, y &amp;gt;= 5, ed in conclusione (x, y) &amp;gt;= (6, 5).&lt;br /&gt;
&lt;br /&gt;
''Svolgimento basato in parte sull'approccio di Operating System Concepts di Silberschatz. et al, 9th edition, cap. 7.''&lt;br /&gt;
&lt;br /&gt;
=== Esercizio g.2 (da controllare) ===&lt;br /&gt;
# Può accadere che il sistema torni in uno stato di safety o che invece porti a deadlock. Diversamente uno stato di safety non può portare direttamente ad uno stato di deadlock, ma solo ad uno di non-safety.&lt;br /&gt;
# Selezionare uno o più tra i processi attivi e sospenderli, salvando il loro stato su memoria secondaria operando delle operazioni di swap-out, finché l'insieme dei frame nella memoria centrale non è in grado di soddisfare tutti i processi rimasti attivi.&lt;br /&gt;
# La scelta è determinata perlopiù dal fattore costo. Con un sistema RAID 1 è possibile ripristinare un disco guasto molto brevemente, in quanto le operazioni coinvolte prevedono una semplice ricopiatura dal disco di backup; con un sistema RAID 5 il ripristino del disco guasto deve coinvolgere tutti i dischi dell'intero array, e ciò può richiedere anche ore per dischi di grandi dimensioni. D'altra parte RAID 1 è più costoso (con n dischi, posso memorizzare tanta informazione quanto potrei con n / 2 dischi) rispetto a RAID 5 dove, tra gli n dischi, complessivamente soltanto uno è destinato alle informazioni di ridondanza.&lt;br /&gt;
# ''Completare.''&lt;/div&gt;</summary>
		<author><name>LiberaL</name></author>
	</entry>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=Esercizi_di_%22lettura%22_programmi_in_Python&amp;diff=2940</id>
		<title>Esercizi di &quot;lettura&quot; programmi in Python</title>
		<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php?title=Esercizi_di_%22lettura%22_programmi_in_Python&amp;diff=2940"/>
		<updated>2023-03-10T13:20:28Z</updated>

		<summary type="html">&lt;p&gt;LiberaL: /* aggiunto pinyin senza toni alla numerazione */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Gli esercizi proposti sono programmi funzionanti.&lt;br /&gt;
&lt;br /&gt;
Come svolgimento dell'esercizio si deve:&lt;br /&gt;
* determinare lo scopo del programma&lt;br /&gt;
* modificare, migliorare discutere le soluzioni proposta. Proporre soluzioni alternative dello stesso problema.&lt;br /&gt;
&lt;br /&gt;
==1==&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
def dd(s):&lt;br /&gt;
  d,m,y = s.split('.')&lt;br /&gt;
  d,m,y = int(d),int(m),int(y)&lt;br /&gt;
  md = [0,31,28,31,30,31,30,31,31,30,31,30,31]&lt;br /&gt;
  if y % 4 == 0:&lt;br /&gt;
    md[2]=29&lt;br /&gt;
  dy = d&lt;br /&gt;
  for i in range(1,m):&lt;br /&gt;
    dy += md[i]&lt;br /&gt;
  return dy&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
  data=input(&amp;quot;Dammi una data (es. 14.03.2014): &amp;quot;)&lt;br /&gt;
  print(&amp;quot;il risultato della funzione misteriosa e' &amp;quot;, dd(data))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==2==&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
def imin(l):&lt;br /&gt;
  im,mn = 0,l[0]&lt;br /&gt;
  for i in range(1,len(l)):&lt;br /&gt;
    if l[i]&amp;lt;mn:&lt;br /&gt;
      im,mn = i,l[i]&lt;br /&gt;
  return im&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
  l = input('dammi in input una lista di elementi (es: [1,2,3]): ')&lt;br /&gt;
  print(&amp;quot;l'output della funzione misteriosa e': &amp;quot;, imin(l))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==3==&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
def r13(s):&lt;br /&gt;
        e = ''&lt;br /&gt;
        for c in s:&lt;br /&gt;
                if 'A' &amp;lt;= c &amp;lt;= 'Z':&lt;br /&gt;
                        e += chr(((ord(c)-ord('A')) + 13)%26 + ord('A'))&lt;br /&gt;
                elif 'a' &amp;lt;= c &amp;lt;= 'z':&lt;br /&gt;
                        e += chr(((ord(c)-ord('a')) + 13)%26 + ord('a'))&lt;br /&gt;
                else:&lt;br /&gt;
                        e += c&lt;br /&gt;
        return e&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
        s = input(&amp;quot;scrivi una semplice frase (es: 'Ciao Mondo') &amp;quot;)&lt;br /&gt;
        r = r13(s)&lt;br /&gt;
        print(&amp;quot;il risultato della funzione misteriosa e': &amp;quot;, r)&lt;br /&gt;
        print(&amp;quot;consiglio: prova a eseguire nuovamente il programma scrivendo&amp;quot;)&lt;br /&gt;
        print(&amp;quot;la frase: &amp;quot;, r)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==4==&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
def pf(n):&lt;br /&gt;
        f = []&lt;br /&gt;
        for i in range(2,n+1):&lt;br /&gt;
                while n % i == 0:&lt;br /&gt;
                        f.append(i)&lt;br /&gt;
                        n //= i&lt;br /&gt;
                if n == 1:&lt;br /&gt;
                        break&lt;br /&gt;
        return f&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
        n = int(input(&amp;quot;dammi un numero (consigliato da 2 a 1000): &amp;quot;))&lt;br /&gt;
        print(&amp;quot;il risultato della funzione misteriosa e' &amp;quot;, pf(n))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==5==&lt;br /&gt;
(richiede il modulo turtle)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
import turtle&lt;br /&gt;
import random&lt;br /&gt;
&lt;br /&gt;
def cy(r):&lt;br /&gt;
    turtle.setup(400,400)&lt;br /&gt;
    turtle.penup()&lt;br /&gt;
    turtle.hideturtle()&lt;br /&gt;
    turtle.speed(0)&lt;br /&gt;
    for i in range(1000):&lt;br /&gt;
        x,y = random.randint(-200,200),random.randint(-200,200)&lt;br /&gt;
        if (x*x + y*y)**0.5 &amp;lt; r:&lt;br /&gt;
            color = &amp;quot;red&amp;quot;&lt;br /&gt;
        else:&lt;br /&gt;
            color = &amp;quot;blue&amp;quot;&lt;br /&gt;
        turtle.goto(x,y)&lt;br /&gt;
        turtle.dot(5,color)&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    r = float(input(&amp;quot;scrivi un numero (consigliato da 100 a 200): &amp;quot;))&lt;br /&gt;
    print(&amp;quot;guarda il risultato della funzione misteriosa&amp;quot;)&lt;br /&gt;
    cy(r)&lt;br /&gt;
    turtle.exitonclick()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==6==&lt;br /&gt;
(richiede il modulo turtle)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
import turtle&lt;br /&gt;
&lt;br /&gt;
def poly(n):&lt;br /&gt;
        for i in range(n):&lt;br /&gt;
                turtle.forward(50)&lt;br /&gt;
                turtle.left(360/n)&lt;br /&gt;
&lt;br /&gt;
if __name__==&amp;quot;__main__&amp;quot;:&lt;br /&gt;
        n=int(input(&amp;quot;dammi un intero (consigliato da 3 a 12): &amp;quot;))&lt;br /&gt;
        poly(n)&lt;br /&gt;
        turtle.exitonclick()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==7==&lt;br /&gt;
Questo e' contorto. Se vi piace... iniziate a preoccuparvi: state diventando informatici ;-)&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
f=&amp;quot;f={0}{1}{0};print(f.format(chr(34),f))&amp;quot;;print(f.format(chr(34),f))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
NB: non e' necessario capire questo programma, e' solo per chi si vuole cimentare in una sfida...&lt;br /&gt;
&lt;br /&gt;
==8==&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
def pf(n):&lt;br /&gt;
        f=[]&lt;br /&gt;
        for i in range(2,n+1):&lt;br /&gt;
                while n % i == 0:&lt;br /&gt;
                        f.append(i)&lt;br /&gt;
                        n //= i&lt;br /&gt;
                if n == 1:&lt;br /&gt;
                        break&lt;br /&gt;
        return f&lt;br /&gt;
&lt;br /&gt;
def fgcd(a,b):&lt;br /&gt;
        def rgcd(fa,fb):&lt;br /&gt;
                if fa and fb:&lt;br /&gt;
                        if fa[0]==fb[0]:&lt;br /&gt;
                                return fa[:1]+rgcd(fa[1:],fb[1:])&lt;br /&gt;
                        elif fa[0]&amp;lt;fb[0]:&lt;br /&gt;
                                return rgcd(fa[1:],fb)&lt;br /&gt;
                        else:&lt;br /&gt;
                                return rgcd(fa,fb[1:])&lt;br /&gt;
                else:&lt;br /&gt;
                        return []&lt;br /&gt;
        return rgcd(pf(a),pf(b))&lt;br /&gt;
&lt;br /&gt;
def flcm(a,b):&lt;br /&gt;
        def rlcm(fa,fb):&lt;br /&gt;
                if fa and fb:&lt;br /&gt;
                        if fa[0]==fb[0]:&lt;br /&gt;
                                return fa[:1]+rlcm(fa[1:],fb[1:])&lt;br /&gt;
                        elif fa[0]&amp;lt;fb[0]:&lt;br /&gt;
                                return fa[:1]+rlcm(fa[1:],fb)&lt;br /&gt;
                        else:&lt;br /&gt;
                                return fa[:1]+rlcm(fa,fb[1:])&lt;br /&gt;
                else:&lt;br /&gt;
                        return fa if fa else fb&lt;br /&gt;
        return rlcm(pf(a),pf(b))&lt;br /&gt;
&lt;br /&gt;
def mul(l):&lt;br /&gt;
        rv=1&lt;br /&gt;
        for el in l:&lt;br /&gt;
                rv *= el&lt;br /&gt;
        return rv&lt;br /&gt;
&lt;br /&gt;
def gcd(x,y):&lt;br /&gt;
        return mul(fgcd(x,y))&lt;br /&gt;
&lt;br /&gt;
def lcm(x,y):&lt;br /&gt;
        return mul(flcm(x,y))&lt;br /&gt;
&lt;br /&gt;
if __name__==&amp;quot;__main__&amp;quot;:&lt;br /&gt;
        a,b=input(&amp;quot;Inserisci due numeri (es: 48 36): &amp;quot;).split()&lt;br /&gt;
        a,b=int(a),int(b)&lt;br /&gt;
        print(&amp;quot;pf({})={}&amp;quot;.format(a,pf(a)))&lt;br /&gt;
        print(&amp;quot;pf({})={}&amp;quot;.format(b,pf(b)))&lt;br /&gt;
        print(&amp;quot;fgcd({},{})={}&amp;quot;.format(a,b,fgcd(a,b)))&lt;br /&gt;
        print(&amp;quot;flcm({},{})={}&amp;quot;.format(a,b,flcm(a,b)))&lt;br /&gt;
        print(&amp;quot;gcd({},{})={}&amp;quot;.format(a,b,gcd(a,b)))&lt;br /&gt;
        print(&amp;quot;lcm({},{})={}&amp;quot;.format(a,b,lcm(a,b)))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==9==&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
def div(n):&lt;br /&gt;
        return {x for x in range(1,n+1) if n % x == 0}&lt;br /&gt;
&lt;br /&gt;
#alternativa:&lt;br /&gt;
#def div(n):&lt;br /&gt;
#       d=set()&lt;br /&gt;
#       for x in range(1,n+1):&lt;br /&gt;
#               if n % x == 0: d.add(x)&lt;br /&gt;
#       return d&lt;br /&gt;
&lt;br /&gt;
def gcd(a,b):&lt;br /&gt;
        return max(div(a) &amp;amp; div(b))&lt;br /&gt;
&lt;br /&gt;
def mul(n,limit):&lt;br /&gt;
        return {x*n for x in range(1,limit//n + 1)}&lt;br /&gt;
&lt;br /&gt;
#alternativa&lt;br /&gt;
#def mul(n,limit):&lt;br /&gt;
#       d=set()&lt;br /&gt;
#       for x in range(1,limit//n + 1):&lt;br /&gt;
#               d.add(x*n)&lt;br /&gt;
#       return d&lt;br /&gt;
&lt;br /&gt;
def lcm(a,b):&lt;br /&gt;
        return min(mul(a,a*b) &amp;amp; mul(b,a*b))&lt;br /&gt;
&lt;br /&gt;
if __name__==&amp;quot;__main__&amp;quot;:&lt;br /&gt;
        a,b=input(&amp;quot;Inserisci due numeri (es: 48 36): &amp;quot;).split()&lt;br /&gt;
        a,b=int(a),int(b)&lt;br /&gt;
        print(&amp;quot;div({})={}&amp;quot;.format(a,div(a)))&lt;br /&gt;
        print(&amp;quot;div({})={}&amp;quot;.format(b,div(b)))&lt;br /&gt;
        print(&amp;quot;mul({},{})={}&amp;quot;.format(a,a*b,mul(a,a*b)))&lt;br /&gt;
        print(&amp;quot;mul({},{})={}&amp;quot;.format(b,a*b,mul(b,a*b)))&lt;br /&gt;
        print(&amp;quot;gcd({},{})={}&amp;quot;.format(a,b,gcd(a,b)))&lt;br /&gt;
        print(&amp;quot;lcm({},{})={}&amp;quot;.format(a,b,lcm(a,b)))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==10==&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
def sdiv(n):&lt;br /&gt;
        return {x for x in range(2,n) if n % x == 0}&lt;br /&gt;
&lt;br /&gt;
#alternativa:&lt;br /&gt;
#def sdiv(n):&lt;br /&gt;
#       d=set()&lt;br /&gt;
#       for x in range(2,n):&lt;br /&gt;
#               if n % x == 0: d.add(x)&lt;br /&gt;
#       return d&lt;br /&gt;
&lt;br /&gt;
def pr(n):&lt;br /&gt;
        return not sdiv(n)&lt;br /&gt;
&lt;br /&gt;
def pdiv(n):&lt;br /&gt;
        return {x for x in sdiv(n) if pr(x)}&lt;br /&gt;
&lt;br /&gt;
#alternativa:&lt;br /&gt;
#def pdiv(n):&lt;br /&gt;
#       d=set()&lt;br /&gt;
#       for x in sdiv(n):&lt;br /&gt;
#               if pr(x): d.add(x)&lt;br /&gt;
#       return d&lt;br /&gt;
&lt;br /&gt;
def gcd(a,b):&lt;br /&gt;
        csdiv=pdiv(a) &amp;amp; pdiv(b)&lt;br /&gt;
        r=1&lt;br /&gt;
        for x in csdiv:&lt;br /&gt;
                while a % (r*x) == 0 and b % (r*x) == 0:&lt;br /&gt;
                        r *= x&lt;br /&gt;
        return r&lt;br /&gt;
&lt;br /&gt;
def lcm(a,b):&lt;br /&gt;
        return a * b // gcd(a,b)&lt;br /&gt;
&lt;br /&gt;
if __name__==&amp;quot;__main__&amp;quot;:&lt;br /&gt;
        a,b=input(&amp;quot;Inserisci due numeri (es: 48 36): &amp;quot;).split()&lt;br /&gt;
        a,b=int(a),int(b)&lt;br /&gt;
        print(&amp;quot;pdiv({})={}&amp;quot;.format(a,pdiv(a)))&lt;br /&gt;
        print(&amp;quot;pdiv({})={}&amp;quot;.format(b,pdiv(b)))&lt;br /&gt;
        print(&amp;quot;gcd({},{})={}&amp;quot;.format(a,b,gcd(a,b)))&lt;br /&gt;
        print(&amp;quot;lcm({},{})={}&amp;quot;.format(a,b,lcm(a,b)))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
==11==&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
def tartline(l):&lt;br /&gt;
        l[:0]=[1]&lt;br /&gt;
        for i in range(1,len(l)-1):&lt;br /&gt;
                l[i] += l[i+1]&lt;br /&gt;
&lt;br /&gt;
l=[]&lt;br /&gt;
for i in range(12):&lt;br /&gt;
        tartline(l)&lt;br /&gt;
        print(&amp;quot;{:^60}&amp;quot;.format(str(l)))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==12==&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
def sdiv(n):&lt;br /&gt;
        return {x for x in range(2,n) if n % x == 0}&lt;br /&gt;
&lt;br /&gt;
#alternativa:&lt;br /&gt;
#def sdiv(n):&lt;br /&gt;
#       d=set()&lt;br /&gt;
#       for x in range(2,n):&lt;br /&gt;
#               if n % x == 0: d.add(x)&lt;br /&gt;
#       return d&lt;br /&gt;
&lt;br /&gt;
def pr(n):&lt;br /&gt;
        return not sdiv(n)&lt;br /&gt;
&lt;br /&gt;
N=int(input(&amp;quot;dammi il numero massimo (es 100): &amp;quot;))&lt;br /&gt;
print(&amp;quot;ecco i numeri ***** fino a&amp;quot;,N,&amp;quot;:&amp;quot;,[n for n in range(1,N+1) if pr(n)])&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==13==&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
vf=[(&amp;quot;Nella vecchia fattoria&amp;quot;,&amp;quot;Quante bestie ha zio Tobia&amp;quot;,&amp;quot;C'e' la capra&amp;quot;,&amp;quot;capra&amp;quot;,&amp;quot;ca&amp;quot;),&lt;br /&gt;
        (&amp;quot;Attaccato a un carrettino&amp;quot;,&amp;quot;C'è un quadrupede piccino&amp;quot;,&amp;quot;L'asinel&amp;quot;,&amp;quot;nel&amp;quot;,&amp;quot;nè&amp;quot;),&lt;br /&gt;
        (&amp;quot;Tra le casse e i ferri rotti&amp;quot;, &amp;quot;Dove i topi son grassotti&amp;quot;,&amp;quot;C'è un bel gatto&amp;quot;,&amp;quot;gatto&amp;quot;,&amp;quot;ga&amp;quot;),&lt;br /&gt;
        (&amp;quot;Tanto grasso e tanto grosso&amp;quot;, &amp;quot;Sempre sporco a più non posso&amp;quot;, &amp;quot;C'è il maiale&amp;quot;,&amp;quot;iale&amp;quot;,&amp;quot;ia&amp;quot;),&lt;br /&gt;
        (&amp;quot;Poi sull'argine del fosso&amp;quot;, &amp;quot;Alle prese con un osso&amp;quot;, &amp;quot;C'è un bel cane&amp;quot;,&amp;quot;cane&amp;quot;,&amp;quot;ca&amp;quot;),&lt;br /&gt;
        (&amp;quot;Nella stalla silenziosa&amp;quot;, &amp;quot;Dopo aver mangiato a iosa&amp;quot;, &amp;quot;Dorme il bue&amp;quot;,&amp;quot;bue&amp;quot;,&amp;quot;bu&amp;quot;)]&lt;br /&gt;
refrain=&amp;quot;ia ia o&amp;quot;&lt;br /&gt;
&lt;br /&gt;
def recverse(m,n):&lt;br /&gt;
        v1,v2,an1,an2,an3=vf[m]&lt;br /&gt;
        if n==m:&lt;br /&gt;
                print(v1,refrain)&lt;br /&gt;
                print(v2,refrain)&lt;br /&gt;
        else:&lt;br /&gt;
                recverse(m+1,n)&lt;br /&gt;
        print(an1,an2,an3,an3,an2)&lt;br /&gt;
&lt;br /&gt;
for i in range(len(vf)):&lt;br /&gt;
        recverse(0,i)&lt;br /&gt;
        print(vf[0][0],refrain)&lt;br /&gt;
        print()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==14==&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
import turtle&lt;br /&gt;
&lt;br /&gt;
def hser(size, level):&lt;br /&gt;
        if level==0:&lt;br /&gt;
                turtle.forward(size)&lt;br /&gt;
        else:&lt;br /&gt;
                hser(size,level-1)&lt;br /&gt;
                turtle.left(45)&lt;br /&gt;
                turtle.forward(size * 2**0.5)&lt;br /&gt;
                turtle.left(45)&lt;br /&gt;
                hser(size,level-1)&lt;br /&gt;
                turtle.right(90)&lt;br /&gt;
                turtle.forward(size)&lt;br /&gt;
                turtle.right(90)&lt;br /&gt;
                hser(size,level-1)&lt;br /&gt;
                turtle.left(45)&lt;br /&gt;
                turtle.forward(size * 2**0.5)&lt;br /&gt;
                turtle.left(45)&lt;br /&gt;
                hser(size,level-1)&lt;br /&gt;
&lt;br /&gt;
def ser(size, level):&lt;br /&gt;
        turtle.penup()&lt;br /&gt;
        pos=(2**(level+2)-3) * size // 2 #posizione iniziale&lt;br /&gt;
        turtle.setpos(-pos,pos)&lt;br /&gt;
        turtle.pendown()&lt;br /&gt;
        hser(size,level)&lt;br /&gt;
        turtle.right(90)&lt;br /&gt;
        hser(size,level)&lt;br /&gt;
        turtle.right(90)&lt;br /&gt;
        hser(size,level)&lt;br /&gt;
        turtle.right(90)&lt;br /&gt;
        hser(size,level)&lt;br /&gt;
        turtle.right(90)&lt;br /&gt;
&lt;br /&gt;
turtle.speed(0)&lt;br /&gt;
turtle.hideturtle()&lt;br /&gt;
ser(2,1)&lt;br /&gt;
ser(2,2)&lt;br /&gt;
ser(2,3)&lt;br /&gt;
ser(2,4)&lt;br /&gt;
turtle.exitonclick()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
==15==&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
import turtle&lt;br /&gt;
import colorsys&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
def arrowstep(level, length, angle):&lt;br /&gt;
        if level:&lt;br /&gt;
                arrowstep(level-1, length/2, -angle)&lt;br /&gt;
                turtle.left(angle)&lt;br /&gt;
                arrowstep(level-1, length/2, angle)&lt;br /&gt;
                turtle.left(angle)&lt;br /&gt;
                arrowstep(level-1, length/2, -angle)&lt;br /&gt;
        else:&lt;br /&gt;
                turtle.forward(length)&lt;br /&gt;
&lt;br /&gt;
def arrow(level, length):&lt;br /&gt;
        if level &amp;amp; 1:&lt;br /&gt;
                turtle.left(60)&lt;br /&gt;
                arrowstep(level, length, -60)&lt;br /&gt;
        else:&lt;br /&gt;
                arrowstep(level, length, -60)&lt;br /&gt;
&lt;br /&gt;
turtle.speed(0)&lt;br /&gt;
turtle.hideturtle()&lt;br /&gt;
turtle.colormode(1)&lt;br /&gt;
nmax=6&lt;br /&gt;
width=256&lt;br /&gt;
xmin= -width//2&lt;br /&gt;
ymin= -width*(3**0.5)//4&lt;br /&gt;
for n in range(nmax):&lt;br /&gt;
        turtle.penup()&lt;br /&gt;
        turtle.setposition(xmin,ymin)&lt;br /&gt;
        turtle.setheading(0)&lt;br /&gt;
        turtle.pencolor(colorsys.hls_to_rgb(1.0*n/6,0.5,1))&lt;br /&gt;
        turtle.pendown()&lt;br /&gt;
        arrow(n,256)&lt;br /&gt;
&lt;br /&gt;
turtle.exitonclick()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
==16==&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
def av(l):&lt;br /&gt;
        return sum(l)/len(l)&lt;br /&gt;
&lt;br /&gt;
def rg(l):&lt;br /&gt;
        return max(l)-min(l)&lt;br /&gt;
&lt;br /&gt;
def md(l):&lt;br /&gt;
        lx=len(l)&lt;br /&gt;
        ls=sorted(l)&lt;br /&gt;
        if lx%2:&lt;br /&gt;
                return ls[lx//2]&lt;br /&gt;
        else:&lt;br /&gt;
                return (ls[lx//2-1]+ls[lx//2])/2&lt;br /&gt;
&lt;br /&gt;
if __name__==&amp;quot;__main__&amp;quot;:&lt;br /&gt;
        l=input(&amp;quot;dammi una lista di numeri separati da virgole (es: 1,2,3,4.4): &amp;quot;)&lt;br /&gt;
        l=[float(x) for x in l.split(',')]&lt;br /&gt;
        print(&amp;quot;i valori trovati dalle tre funzioni sono: {:.4f} {:.4f} {:.4f}&amp;quot;.format(av(l),rg(l),md(l)))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==17==&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
import turtle&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
rows,cols=4,4&lt;br /&gt;
buttonsize=50&lt;br /&gt;
topdisplay=2*buttonsize&lt;br /&gt;
&lt;br /&gt;
stack=[0]&lt;br /&gt;
fresh=True&lt;br /&gt;
&lt;br /&gt;
def num(x):&lt;br /&gt;
        global fresh,stack&lt;br /&gt;
        if fresh:&lt;br /&gt;
                stack[:0]=[x]&lt;br /&gt;
                fresh=False&lt;br /&gt;
        else:&lt;br /&gt;
                stack[0]=stack[0]*10+x&lt;br /&gt;
&lt;br /&gt;
enter,add,sub,mul,div=0,int.__add__,int.__sub__,int.__mul__,int.__floordiv__&lt;br /&gt;
&lt;br /&gt;
def op(x):&lt;br /&gt;
        global fresh,stack&lt;br /&gt;
        if x!=enter and len(stack)&amp;gt;1:&lt;br /&gt;
                stack=[x(stack[1],stack[0])]+stack[2:]&lt;br /&gt;
        fresh=True&lt;br /&gt;
&lt;br /&gt;
def off(x):&lt;br /&gt;
        sys.exit(0)&lt;br /&gt;
&lt;br /&gt;
buttons={ &lt;br /&gt;
        (0,0):('0',num,0), (1,0):('1',num,1), (1,1):('2',num,2), (1,2):('3',num,3), (2,0):('4',num,4), &lt;br /&gt;
        (2,1):('5',num,5), (2,2):('6',num,6), (3,0):('7',num,7), (3,1):('8',num,8), (3,2):('9',num,9), &lt;br /&gt;
        (3,3):('+',op,add), (2,3):('-',op,sub), (1,3):('*',op,mul), (0,3):('/',op,div),&lt;br /&gt;
        (0,2):('ent',op,enter), (0,1):('off',off,0)}&lt;br /&gt;
&lt;br /&gt;
def click(x,y):&lt;br /&gt;
        col=x//buttonsize&lt;br /&gt;
        row=y//buttonsize&lt;br /&gt;
        if (row,col) in buttons:&lt;br /&gt;
                label,op,val=buttons[row,col]&lt;br /&gt;
                op(val)&lt;br /&gt;
                drawcalc()&lt;br /&gt;
&lt;br /&gt;
def drawcalc():&lt;br /&gt;
        def drawbutton(col,row,label):&lt;br /&gt;
                turtle.setpos(row*buttonsize,col*buttonsize)&lt;br /&gt;
                turtle.pendown()&lt;br /&gt;
                for _ in range(4):&lt;br /&gt;
                        turtle.forward(buttonsize)&lt;br /&gt;
                        turtle.left(90)&lt;br /&gt;
                turtle.penup()&lt;br /&gt;
                turtle.setpos(row*buttonsize+buttonsize//2,col*buttonsize+buttonsize//2)&lt;br /&gt;
                turtle.write(label,align=&amp;quot;center&amp;quot;)&lt;br /&gt;
        turtle.clear()&lt;br /&gt;
        turtle.penup()&lt;br /&gt;
        for row,col in buttons:&lt;br /&gt;
                drawbutton(row,col,buttons[row,col][0])&lt;br /&gt;
        turtle.setpos(row*buttonsize*(rows-1),col*buttonsize*(cols+1))&lt;br /&gt;
        turtle.write(str(stack[0]),align=&amp;quot;right&amp;quot;)&lt;br /&gt;
        turtle.update()&lt;br /&gt;
&lt;br /&gt;
turtle.screensize(cols*buttonsize+1, rows*buttonsize+topdisplay+1)&lt;br /&gt;
turtle.setup(cols*buttonsize+1, rows*buttonsize+topdisplay+1)&lt;br /&gt;
turtle.setworldcoordinates(0,0,cols*buttonsize, rows*buttonsize+topdisplay)&lt;br /&gt;
turtle.hideturtle()&lt;br /&gt;
turtle.speed(10)&lt;br /&gt;
turtle.tracer(0)&lt;br /&gt;
drawcalc()&lt;br /&gt;
turtle.onscreenclick(click)&lt;br /&gt;
turtle.listen()&lt;br /&gt;
turtle.mainloop()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==18==&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
import turtle&lt;br /&gt;
import colorsys&lt;br /&gt;
import time&lt;br /&gt;
&lt;br /&gt;
N=6&lt;br /&gt;
frompin=list(range(N,0,-1))&lt;br /&gt;
auxpin=[]&lt;br /&gt;
topin=[]&lt;br /&gt;
&lt;br /&gt;
def rectangle(size, level, pin):&lt;br /&gt;
        turtle.penup()&lt;br /&gt;
        turtle.setpos(2*N*10*pin,level*10)&lt;br /&gt;
        turtle.setheading(0)&lt;br /&gt;
        turtle.pendown()&lt;br /&gt;
        turtle.fillcolor(colorsys.hls_to_rgb(1.0*(size-1)/N,0.5,1))&lt;br /&gt;
        turtle.begin_fill()&lt;br /&gt;
        turtle.forward(size*10)&lt;br /&gt;
        turtle.left(90)&lt;br /&gt;
        turtle.forward(10)&lt;br /&gt;
        turtle.left(90)&lt;br /&gt;
        turtle.forward(size*20)&lt;br /&gt;
        turtle.left(90)&lt;br /&gt;
        turtle.forward(10)&lt;br /&gt;
        turtle.left(90)&lt;br /&gt;
        turtle.forward(size*10)&lt;br /&gt;
        turtle.end_fill()&lt;br /&gt;
&lt;br /&gt;
def showhanoi():&lt;br /&gt;
        turtle.clear()&lt;br /&gt;
        lf,la,lt=map(len,(frompin,auxpin,topin))&lt;br /&gt;
        for i in range(lf):&lt;br /&gt;
                rectangle(frompin[i], i, -1)&lt;br /&gt;
        for i in range(la):&lt;br /&gt;
                rectangle(auxpin[i], i, 0)&lt;br /&gt;
        for i in range(lt):&lt;br /&gt;
                rectangle(topin[i], i, 1)&lt;br /&gt;
        turtle.update()&lt;br /&gt;
        time.sleep(0.2)&lt;br /&gt;
&lt;br /&gt;
def hanoi(n,f,a,t):&lt;br /&gt;
        if n==1:&lt;br /&gt;
                t.append(f.pop())&lt;br /&gt;
                showhanoi()&lt;br /&gt;
        else:&lt;br /&gt;
                hanoi(n-1,f,t,a)&lt;br /&gt;
                hanoi(1,f,a,t)&lt;br /&gt;
                hanoi(n-1,a,f,t)&lt;br /&gt;
&lt;br /&gt;
turtle.hideturtle()&lt;br /&gt;
turtle.speed(10)&lt;br /&gt;
turtle.tracer(0)&lt;br /&gt;
showhanoi()&lt;br /&gt;
hanoi(N,frompin,auxpin,topin)&lt;br /&gt;
turtle.exitonclick()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
==19==&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
#!/usr/bin/env python3&lt;br /&gt;
#   Copyright 2014 Renzo Davoli University of Bologna - Italy&lt;br /&gt;
#   This program is free software; you can redistribute it and/or modify&lt;br /&gt;
#   it under the terms of the GNU General Public License as published by&lt;br /&gt;
#   the Free Software Foundation; either version 2 of the License, or&lt;br /&gt;
#   (at your option) any later version.&lt;br /&gt;
#&lt;br /&gt;
#   This program is distributed in the hope that it will be useful,&lt;br /&gt;
#   but WITHOUT ANY WARRANTY; without even the implied warranty of&lt;br /&gt;
#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the&lt;br /&gt;
#   GNU General Public License for more details.&lt;br /&gt;
#&lt;br /&gt;
#   You should have received a copy of the GNU General Public License along&lt;br /&gt;
#   with this program; if not, write to the Free Software Foundation, Inc.,&lt;br /&gt;
#   51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA.&lt;br /&gt;
#&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
class num:&lt;br /&gt;
	def __init__(self,n):&lt;br /&gt;
		self.val=n&lt;br /&gt;
&lt;br /&gt;
class mul(num):&lt;br /&gt;
	pass&lt;br /&gt;
&lt;br /&gt;
class onemul(mul):&lt;br /&gt;
	pass&lt;br /&gt;
&lt;br /&gt;
class plus():&lt;br /&gt;
	pass&lt;br /&gt;
&lt;br /&gt;
class times():&lt;br /&gt;
	pass&lt;br /&gt;
&lt;br /&gt;
class numlanguage():&lt;br /&gt;
	def __init__(self):&lt;br /&gt;
		self.dict={}&lt;br /&gt;
	def __setitem__(self,s,op):&lt;br /&gt;
		self.dict[s]=op&lt;br /&gt;
		for l in range(len(s)-1,0,-1):&lt;br /&gt;
			if s[:l] in self.dict:&lt;br /&gt;
				break&lt;br /&gt;
			else:&lt;br /&gt;
				self.dict[s[:l]]=None&lt;br /&gt;
		return op&lt;br /&gt;
	def match(self,s):&lt;br /&gt;
		matchlen,obj=0,None&lt;br /&gt;
		for l in range(1,len(s)+1):&lt;br /&gt;
			if s[:l] in self.dict:&lt;br /&gt;
				matchlen,obj=l,self.dict[s[:l]]&lt;br /&gt;
			else:&lt;br /&gt;
				break&lt;br /&gt;
		return matchlen,obj&lt;br /&gt;
&lt;br /&gt;
def str2num(langnum,s):&lt;br /&gt;
	hi=mid=lo=last=0&lt;br /&gt;
	lastop=None&lt;br /&gt;
	while s:&lt;br /&gt;
		if s[0] in &amp;quot; -\t\n&amp;quot;:&lt;br /&gt;
			s=s[1:]&lt;br /&gt;
		else:&lt;br /&gt;
			ml,obj=langnum.match(s)&lt;br /&gt;
			if obj:&lt;br /&gt;
				if isinstance(obj,num):&lt;br /&gt;
					if isinstance(obj,mul):&lt;br /&gt;
						if isinstance(obj,onemul) and lo == 0:&lt;br /&gt;
							lo = 1&lt;br /&gt;
						if (last &amp;lt;= obj.val or isinstance(lastop,times)) and not isinstance(lastop,plus):&lt;br /&gt;
							hi,mid,lo = (hi+mid+lo)*obj.val,0,0&lt;br /&gt;
						else:&lt;br /&gt;
							hi,mid,lo = hi+(lo+mid)*obj.val,0,0&lt;br /&gt;
						last=obj.val&lt;br /&gt;
					else: &lt;br /&gt;
						if obj.val == 100:&lt;br /&gt;
						 	mid,lo = lo*obj.val if lo else obj.val,0&lt;br /&gt;
						elif obj.val &amp;lt;= lo or isinstance(lastop,plus):&lt;br /&gt;
							lo += obj.val&lt;br /&gt;
						else:&lt;br /&gt;
							lo = lo*obj.val if lo else obj.val&lt;br /&gt;
					lastop=None&lt;br /&gt;
				else:&lt;br /&gt;
					lastop=obj&lt;br /&gt;
#print(s[:ml],hi,mid,lo,last,lastop)&lt;br /&gt;
				s=s[ml:]&lt;br /&gt;
			else:&lt;br /&gt;
				return -1&lt;br /&gt;
	return hi+mid+lo&lt;br /&gt;
&lt;br /&gt;
def num_it():&lt;br /&gt;
	nl=numlanguage()&lt;br /&gt;
	nl[&amp;quot;zero&amp;quot;]=num(0) &lt;br /&gt;
	nl[&amp;quot;uno&amp;quot;]=nl[&amp;quot;un&amp;quot;]=nl[&amp;quot;una&amp;quot;]=num(1) &lt;br /&gt;
	nl[&amp;quot;due&amp;quot;]=num(2) &lt;br /&gt;
	nl[&amp;quot;tre&amp;quot;]=num(3) &lt;br /&gt;
	nl[&amp;quot;quattro&amp;quot;]=num(4) &lt;br /&gt;
	nl[&amp;quot;cinque&amp;quot;]=num(5) &lt;br /&gt;
	nl[&amp;quot;sei&amp;quot;]=num(6) &lt;br /&gt;
	nl[&amp;quot;sette&amp;quot;]=num(7) &lt;br /&gt;
	nl[&amp;quot;otto&amp;quot;]=num(8) &lt;br /&gt;
	nl[&amp;quot;nove&amp;quot;]=num(9) &lt;br /&gt;
	nl[&amp;quot;dieci&amp;quot;]=num(10) &lt;br /&gt;
	nl[&amp;quot;undici&amp;quot;]=num(11) &lt;br /&gt;
	nl[&amp;quot;dodici&amp;quot;]=num(12) &lt;br /&gt;
	nl[&amp;quot;tredici&amp;quot;]=num(13) &lt;br /&gt;
	nl[&amp;quot;quattordici&amp;quot;]=num(14) &lt;br /&gt;
	nl[&amp;quot;quindici&amp;quot;]=num(15) &lt;br /&gt;
	nl[&amp;quot;sedici&amp;quot;]=num(16) &lt;br /&gt;
	nl[&amp;quot;diciassette&amp;quot;]=num(17) &lt;br /&gt;
	nl[&amp;quot;diciotto&amp;quot;]=num(18) &lt;br /&gt;
	nl[&amp;quot;diciannove&amp;quot;]=num(19) &lt;br /&gt;
	nl[&amp;quot;venti&amp;quot;]=nl[&amp;quot;vent&amp;quot;]=num(20) &lt;br /&gt;
	nl[&amp;quot;trenta&amp;quot;]=nl[&amp;quot;trent&amp;quot;]=num(30) &lt;br /&gt;
	nl[&amp;quot;quaranta&amp;quot;]=nl[&amp;quot;quarant&amp;quot;]=num(40) &lt;br /&gt;
	nl[&amp;quot;cinquanta&amp;quot;]=nl[&amp;quot;cinquant&amp;quot;]=num(50) &lt;br /&gt;
	nl[&amp;quot;sessanta&amp;quot;]=nl[&amp;quot;sessant&amp;quot;]=num(60) &lt;br /&gt;
	nl[&amp;quot;settanta&amp;quot;]=nl[&amp;quot;settant&amp;quot;]=num(70) &lt;br /&gt;
	nl[&amp;quot;ottanta&amp;quot;]=nl[&amp;quot;ottant&amp;quot;]=num(80) &lt;br /&gt;
	nl[&amp;quot;novanta&amp;quot;]=nl[&amp;quot;novant&amp;quot;]=num(90) &lt;br /&gt;
	nl[&amp;quot;cento&amp;quot;]=num(100) &lt;br /&gt;
	nl[&amp;quot;mille&amp;quot;]=onemul(10**3) &lt;br /&gt;
	nl[&amp;quot;mila&amp;quot;]=nl[&amp;quot;migliaia&amp;quot;]=mul(10**3) &lt;br /&gt;
	nl[&amp;quot;milioni&amp;quot;]=nl[&amp;quot;milione&amp;quot;]=mul(10**6) &lt;br /&gt;
	nl[&amp;quot;miliardi&amp;quot;]=nl[&amp;quot;miliardo&amp;quot;]=mul(10**9) &lt;br /&gt;
	nl[&amp;quot;dozzine&amp;quot;]=nl[&amp;quot;dozzina&amp;quot;]=mul(12) &lt;br /&gt;
	nl[&amp;quot;decine&amp;quot;]=mul(10) &lt;br /&gt;
	nl[&amp;quot;centinaia&amp;quot;]=mul(100) &lt;br /&gt;
	nl[&amp;quot;di&amp;quot;]=times() &lt;br /&gt;
	nl[&amp;quot;e&amp;quot;]=plus() &lt;br /&gt;
	return nl&lt;br /&gt;
&lt;br /&gt;
def num_en():&lt;br /&gt;
	nl=numlanguage()&lt;br /&gt;
	nl[&amp;quot;zero&amp;quot;]=nl[&amp;quot;null&amp;quot;]=num(0)&lt;br /&gt;
	nl[&amp;quot;one&amp;quot;]=nl[&amp;quot;a&amp;quot;]=num(1)&lt;br /&gt;
	nl[&amp;quot;two&amp;quot;]=num(2)&lt;br /&gt;
	nl[&amp;quot;three&amp;quot;]=num(3)&lt;br /&gt;
	nl[&amp;quot;four&amp;quot;]=num(4)&lt;br /&gt;
	nl[&amp;quot;five&amp;quot;]=num(5)&lt;br /&gt;
	nl[&amp;quot;six&amp;quot;]=num(6)&lt;br /&gt;
	nl[&amp;quot;seven&amp;quot;]=num(7)&lt;br /&gt;
	nl[&amp;quot;eight&amp;quot;]=num(8)&lt;br /&gt;
	nl[&amp;quot;nine&amp;quot;]=num(9)&lt;br /&gt;
	nl[&amp;quot;ten&amp;quot;]=num(10)&lt;br /&gt;
	nl[&amp;quot;eleven&amp;quot;]=num(11)&lt;br /&gt;
	nl[&amp;quot;twelve&amp;quot;]=num(12)&lt;br /&gt;
	nl[&amp;quot;thirteen&amp;quot;]=num(13)&lt;br /&gt;
	nl[&amp;quot;fourteen&amp;quot;]=num(14)&lt;br /&gt;
	nl[&amp;quot;fifteen&amp;quot;]=num(15)&lt;br /&gt;
	nl[&amp;quot;sixteen&amp;quot;]=num(16)&lt;br /&gt;
	nl[&amp;quot;seventeen&amp;quot;]=num(17)&lt;br /&gt;
	nl[&amp;quot;eighteen&amp;quot;]=num(18)&lt;br /&gt;
	nl[&amp;quot;nineteen&amp;quot;]=num(19)&lt;br /&gt;
	nl[&amp;quot;twenty&amp;quot;]=num(20)&lt;br /&gt;
	nl[&amp;quot;thirty&amp;quot;]=num(30)&lt;br /&gt;
	nl[&amp;quot;forty&amp;quot;]=num(40)&lt;br /&gt;
	nl[&amp;quot;fifty&amp;quot;]=num(50)&lt;br /&gt;
	nl[&amp;quot;sixty&amp;quot;]=num(60)&lt;br /&gt;
	nl[&amp;quot;seventy&amp;quot;]=num(70)&lt;br /&gt;
	nl[&amp;quot;eighty&amp;quot;]=num(80)&lt;br /&gt;
	nl[&amp;quot;ninety&amp;quot;]=num(90)&lt;br /&gt;
	nl[&amp;quot;hundred&amp;quot;]=num(100)&lt;br /&gt;
	nl[&amp;quot;thousand&amp;quot;]=mul(10**3)&lt;br /&gt;
	nl[&amp;quot;million&amp;quot;]=mul(10**6)&lt;br /&gt;
	nl[&amp;quot;billion&amp;quot;]=mul(10**9)&lt;br /&gt;
	nl[&amp;quot;trillion&amp;quot;]=mul(10**12)&lt;br /&gt;
	nl[&amp;quot;dozen&amp;quot;]=mul(12)&lt;br /&gt;
	nl[&amp;quot;and&amp;quot;]=plus()&lt;br /&gt;
	nl[&amp;quot;of&amp;quot;]=times()&lt;br /&gt;
	return nl&lt;br /&gt;
	&lt;br /&gt;
def num_fr():&lt;br /&gt;
	nl=numlanguage()&lt;br /&gt;
	nl[&amp;quot;zero&amp;quot;]=num(0)&lt;br /&gt;
	nl[&amp;quot;un&amp;quot;]=num(1)&lt;br /&gt;
	nl[&amp;quot;deux&amp;quot;]=num(2)&lt;br /&gt;
	nl[&amp;quot;trois&amp;quot;]=num(3)&lt;br /&gt;
	nl[&amp;quot;quatre&amp;quot;]=num(4)&lt;br /&gt;
	nl[&amp;quot;cinq&amp;quot;]=num(5)&lt;br /&gt;
	nl[&amp;quot;six&amp;quot;]=num(6)&lt;br /&gt;
	nl[&amp;quot;sept&amp;quot;]=num(7)&lt;br /&gt;
	nl[&amp;quot;huit&amp;quot;]=num(8)&lt;br /&gt;
	nl[&amp;quot;neuf&amp;quot;]=num(9)&lt;br /&gt;
	nl[&amp;quot;dix&amp;quot;]=num(10)&lt;br /&gt;
	nl[&amp;quot;onze&amp;quot;]=num(11)&lt;br /&gt;
	nl[&amp;quot;douze&amp;quot;]=num(12)&lt;br /&gt;
	nl[&amp;quot;treize&amp;quot;]=num(13)&lt;br /&gt;
	nl[&amp;quot;quatorze&amp;quot;]=num(14)&lt;br /&gt;
	nl[&amp;quot;quinze&amp;quot;]=num(15)&lt;br /&gt;
	nl[&amp;quot;seize&amp;quot;]=num(16)&lt;br /&gt;
	nl[&amp;quot;vingt&amp;quot;]=num(20)&lt;br /&gt;
	nl[&amp;quot;trente&amp;quot;]=num(30)&lt;br /&gt;
	nl[&amp;quot;quarante&amp;quot;]=num(40)&lt;br /&gt;
	nl[&amp;quot;cinquante&amp;quot;]=num(50)&lt;br /&gt;
	nl[&amp;quot;soixante&amp;quot;]=num(60)&lt;br /&gt;
	nl[&amp;quot;cent&amp;quot;]=num(100)&lt;br /&gt;
	nl[&amp;quot;mille&amp;quot;]=onemul(10**3)&lt;br /&gt;
	nl[&amp;quot;million&amp;quot;]=mul(10**6)&lt;br /&gt;
	nl[&amp;quot;milliard&amp;quot;]=mul(10**9)&lt;br /&gt;
	nl[&amp;quot;douzaine&amp;quot;]=mul(12)&lt;br /&gt;
	nl[&amp;quot;et&amp;quot;]=plus()&lt;br /&gt;
	nl[&amp;quot;de&amp;quot;]=times()&lt;br /&gt;
	return nl&lt;br /&gt;
&lt;br /&gt;
def num_de():&lt;br /&gt;
	nl=numlanguage()&lt;br /&gt;
	nl[&amp;quot;null&amp;quot;]=num(0)&lt;br /&gt;
	nl[&amp;quot;eins&amp;quot;]=nl[&amp;quot;ein&amp;quot;]=num(1)&lt;br /&gt;
	nl[&amp;quot;zwei&amp;quot;]=nl[&amp;quot;zwo&amp;quot;]=num(2)&lt;br /&gt;
	nl[&amp;quot;drei&amp;quot;]=num(3)&lt;br /&gt;
	nl[&amp;quot;vier&amp;quot;]=num(4)&lt;br /&gt;
	nl[&amp;quot;fÃ¼nf&amp;quot;]=num(5)&lt;br /&gt;
	nl[&amp;quot;sechs&amp;quot;]=num(6)&lt;br /&gt;
	nl[&amp;quot;sieben&amp;quot;]=num(7)&lt;br /&gt;
	nl[&amp;quot;acht&amp;quot;]=num(8)&lt;br /&gt;
	nl[&amp;quot;neun&amp;quot;]=num(9)&lt;br /&gt;
	nl[&amp;quot;zehn&amp;quot;]=num(10)&lt;br /&gt;
	nl[&amp;quot;elf&amp;quot;]=num(11)&lt;br /&gt;
	nl[&amp;quot;zwÃ¶lf&amp;quot;]=num(12)&lt;br /&gt;
	nl[&amp;quot;dreizehn&amp;quot;]=num(13)&lt;br /&gt;
	nl[&amp;quot;vierzehn&amp;quot;]=num(14)&lt;br /&gt;
	nl[&amp;quot;fÃ¼nfzehn&amp;quot;]=num(15)&lt;br /&gt;
	nl[&amp;quot;sechzehn&amp;quot;]=num(16)&lt;br /&gt;
	nl[&amp;quot;siebzehn&amp;quot;]=num(17)&lt;br /&gt;
	nl[&amp;quot;achtzehn&amp;quot;]=num(18)&lt;br /&gt;
	nl[&amp;quot;neunzehn&amp;quot;]=num(19)&lt;br /&gt;
	nl[&amp;quot;zwanzig&amp;quot;]=num(20)&lt;br /&gt;
	nl[&amp;quot;dreiÎ²ig&amp;quot;]=num(30)&lt;br /&gt;
	nl[&amp;quot;dreiÃig&amp;quot;]=num(30)&lt;br /&gt;
	nl[&amp;quot;vierzig&amp;quot;]=num(40)&lt;br /&gt;
	nl[&amp;quot;fÃ¼nfzig&amp;quot;]=num(50)&lt;br /&gt;
	nl[&amp;quot;sechzig&amp;quot;]=num(60)&lt;br /&gt;
	nl[&amp;quot;siebzig&amp;quot;]=num(70)&lt;br /&gt;
	nl[&amp;quot;achtzig&amp;quot;]=num(80)&lt;br /&gt;
	nl[&amp;quot;neunzig&amp;quot;]=num(90)&lt;br /&gt;
	nl[&amp;quot;hundert&amp;quot;]=num(100)&lt;br /&gt;
	nl[&amp;quot;tausend&amp;quot;]=mul(10**3)&lt;br /&gt;
	nl[&amp;quot;million&amp;quot;]=mul(10**6)&lt;br /&gt;
	nl[&amp;quot;milliard&amp;quot;]=mul(10**9)&lt;br /&gt;
	nl[&amp;quot;und&amp;quot;]=plus()&lt;br /&gt;
	return nl&lt;br /&gt;
&lt;br /&gt;
def num_ch():&lt;br /&gt;
	nl=numlanguage()&lt;br /&gt;
	'''pinyin senza toni purtroppo T_T'''&lt;br /&gt;
	nl[&amp;quot;ling&amp;quot;]=num(0) &lt;br /&gt;
	nl[&amp;quot;yi&amp;quot;]=num(1) &lt;br /&gt;
	nl[&amp;quot;er&amp;quot;]=nl[&amp;quot;liang&amp;quot;]=num(2) &lt;br /&gt;
	nl[&amp;quot;san&amp;quot;]=num(3) &lt;br /&gt;
	nl[&amp;quot;si&amp;quot;]=num(4) &lt;br /&gt;
	nl[&amp;quot;wu&amp;quot;]=num(5) &lt;br /&gt;
	nl[&amp;quot;liu&amp;quot;]=num(6) &lt;br /&gt;
	nl[&amp;quot;qi&amp;quot;]=num(7) &lt;br /&gt;
	nl[&amp;quot;ba&amp;quot;]=num(8) &lt;br /&gt;
	nl[&amp;quot;jiu&amp;quot;]=num(9) &lt;br /&gt;
	nl[&amp;quot;sci&amp;quot;]=num(10)&lt;br /&gt;
	nl[&amp;quot;bai&amp;quot;]=num(100)&lt;br /&gt;
	nl[&amp;quot;qian&amp;quot;]=mul(10**3)&lt;br /&gt;
	nl[&amp;quot;wan&amp;quot;]=mul(10**4)&lt;br /&gt;
	return nl&lt;br /&gt;
&lt;br /&gt;
def num_es():&lt;br /&gt;
	nl=numlanguage()&lt;br /&gt;
	nl[&amp;quot;cero&amp;quot;]=num(0)&lt;br /&gt;
	nl[&amp;quot;uno&amp;quot;]=num(1)&lt;br /&gt;
	nl[&amp;quot;dos&amp;quot;]=num(2)&lt;br /&gt;
	nl[&amp;quot;tres&amp;quot;]=num(3)&lt;br /&gt;
	nl[&amp;quot;cuatro&amp;quot;]=num(4)&lt;br /&gt;
	nl[&amp;quot;cinco&amp;quot;]=num(5)&lt;br /&gt;
	nl[&amp;quot;seis&amp;quot;]=num(6)&lt;br /&gt;
	nl[&amp;quot;siete&amp;quot;]=num(7)&lt;br /&gt;
	nl[&amp;quot;ocho&amp;quot;]=num(8)&lt;br /&gt;
	nl[&amp;quot;nueve&amp;quot;]=num(9)&lt;br /&gt;
	nl[&amp;quot;diez&amp;quot;]=num(10)&lt;br /&gt;
	nl[&amp;quot;once&amp;quot;]=num(11)&lt;br /&gt;
	nl[&amp;quot;doce&amp;quot;]=num(12)&lt;br /&gt;
	nl[&amp;quot;trece&amp;quot;]=num(13)&lt;br /&gt;
	nl[&amp;quot;catorce&amp;quot;]=num(14)&lt;br /&gt;
	nl[&amp;quot;quince&amp;quot;]=num(15)&lt;br /&gt;
	nl[&amp;quot;diecisÃ©is&amp;quot;]=num(16)&lt;br /&gt;
	nl[&amp;quot;diecisiete&amp;quot;]=num(17)&lt;br /&gt;
	nl[&amp;quot;dieciocho&amp;quot;]=num(18)&lt;br /&gt;
	nl[&amp;quot;diecinueve&amp;quot;]=num(19)&lt;br /&gt;
	nl[&amp;quot;veinte&amp;quot;]=nl[&amp;quot;veinti&amp;quot;]=num(20)&lt;br /&gt;
	nl[&amp;quot;treinta&amp;quot;]=num(30)&lt;br /&gt;
	nl[&amp;quot;cuarenta&amp;quot;]=num(40)&lt;br /&gt;
	nl[&amp;quot;cincuenta&amp;quot;]=num(50)&lt;br /&gt;
	nl[&amp;quot;sesenta&amp;quot;]=num(60)&lt;br /&gt;
	nl[&amp;quot;setenta&amp;quot;]=num(70)&lt;br /&gt;
	nl[&amp;quot;ochenta&amp;quot;]=num(80)&lt;br /&gt;
	nl[&amp;quot;noventa&amp;quot;]=num(90)&lt;br /&gt;
	nl[&amp;quot;cien&amp;quot;]=nl[&amp;quot;cientos&amp;quot;]=num(100)&lt;br /&gt;
	nl[&amp;quot;quinientos&amp;quot;]=num(500)&lt;br /&gt;
	nl[&amp;quot;setecientos &amp;quot;]=num(700)&lt;br /&gt;
	nl[&amp;quot;novecientos&amp;quot;]=num(900)&lt;br /&gt;
	nl[&amp;quot;mil&amp;quot;]=onemul(10**3)&lt;br /&gt;
	nl[&amp;quot;millÃ³n&amp;quot;]=nl[&amp;quot;millones&amp;quot;]=mul(10**6)&lt;br /&gt;
	nl[&amp;quot;billÃ³n&amp;quot;]=nl[&amp;quot;billones&amp;quot;]=mul(10**12)&lt;br /&gt;
	nl[&amp;quot;y&amp;quot;]=plus()&lt;br /&gt;
	return nl&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
	itnum=num_it()&lt;br /&gt;
	print(&amp;quot;it&amp;quot;,str2num(itnum,sys.argv[1]))&lt;br /&gt;
	ennum=num_en()&lt;br /&gt;
	print(&amp;quot;en&amp;quot;,str2num(ennum,sys.argv[1]))&lt;br /&gt;
	frnum=num_fr()&lt;br /&gt;
	print(&amp;quot;fr&amp;quot;,str2num(frnum,sys.argv[1]))&lt;br /&gt;
	denum=num_de()&lt;br /&gt;
	print(&amp;quot;de&amp;quot;,str2num(denum,sys.argv[1]))&lt;br /&gt;
	esnum=num_es()&lt;br /&gt;
	print(&amp;quot;es&amp;quot;,str2num(esnum,sys.argv[1]))&lt;br /&gt;
	chnum=num_ch()&lt;br /&gt;
	print(&amp;quot;ch&amp;quot;,str2num(chnum,sys.argv[1]))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
==20==&lt;br /&gt;
trace.py:&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
def trace(f):&lt;br /&gt;
  f.indent = 0&lt;br /&gt;
  def strtuple(x):&lt;br /&gt;
    return &amp;quot;(&amp;quot;+str(x[0])+&amp;quot;)&amp;quot; if len(x)==1 else str(x)&lt;br /&gt;
  def g(*x):&lt;br /&gt;
    print('| ' * f.indent + '/-- ', f.__name__, strtuple(x), sep='')&lt;br /&gt;
    f.indent += 1&lt;br /&gt;
    value = f(*x)&lt;br /&gt;
    f.indent -= 1&lt;br /&gt;
    print('| ' * f.indent + '\-- ', 'return', repr(value))&lt;br /&gt;
    return value&lt;br /&gt;
  return g&lt;br /&gt;
&lt;br /&gt;
def memoize(f):&lt;br /&gt;
  cache = {}&lt;br /&gt;
  def g(*x):&lt;br /&gt;
    if x not in cache:&lt;br /&gt;
      cache[x] = f(*x)&lt;br /&gt;
    return cache[x]&lt;br /&gt;
  return g&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
main.py:&lt;br /&gt;
&amp;lt;source lang=python&amp;gt;&lt;br /&gt;
#!/usr/bin/env python3&lt;br /&gt;
import sys&lt;br /&gt;
import trace&lt;br /&gt;
&lt;br /&gt;
# try to uncomment the following statements:&lt;br /&gt;
#@trace.trace&lt;br /&gt;
#@trace.memoize&lt;br /&gt;
def fib(i):&lt;br /&gt;
  if i&amp;lt;=0:&lt;br /&gt;
    return 0&lt;br /&gt;
  elif i==1:&lt;br /&gt;
    return 1&lt;br /&gt;
  else:&lt;br /&gt;
    return fib(i-1)+fib(i-2)&lt;br /&gt;
&lt;br /&gt;
if __name__==&amp;quot;__main__&amp;quot;:&lt;br /&gt;
  for i in range(int(sys.argv[1])):&lt;br /&gt;
    print(i,fib(i))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>LiberaL</name></author>
	</entry>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=20220906c2&amp;diff=2800</id>
		<title>20220906c2</title>
		<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php?title=20220906c2&amp;diff=2800"/>
		<updated>2022-10-26T10:07:07Z</updated>

		<summary type="html">&lt;p&gt;LiberaL: /* Correzioni proposte */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;In questa pagina sono presenti alcune soluzioni (possibilmente con errore) per l'esercizio C2 dell'esame 2022/09/06.&lt;br /&gt;
Il lettore è invitato a immedesimare il professore al momento della correzione durante la lettura delle soluzioni.&lt;br /&gt;
&lt;br /&gt;
== Consegna ==&lt;br /&gt;
Usando i semafori implementare un servizio che preveda due funzioni:&lt;br /&gt;
   void sumstop(int v)&lt;br /&gt;
   int sumgo(void) &lt;br /&gt;
La funzione sumstop deve mettere il processo chiamante in attesa.&lt;br /&gt;
La funzione sumgo deve sbloccare tutti i processi messi in attesa con la sumstop e restituire la somma algebrica dei valori passati come parametro alla  sumstop dai processi che sono stati sbloccati (zero se la  sumgo viene richiamata quando non c'è nessun processo bloccato).&lt;br /&gt;
== 1 ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
semaphore sem(1);&lt;br /&gt;
int sum=0;&lt;br /&gt;
queue q;&lt;br /&gt;
&lt;br /&gt;
void sumstop(int v):&lt;br /&gt;
	if i &amp;lt; 0:&lt;br /&gt;
		q.enqueue(v)&lt;br /&gt;
		sem.P()&lt;br /&gt;
	else&lt;br /&gt;
		i--&lt;br /&gt;
&lt;br /&gt;
int sumgo(void):&lt;br /&gt;
	for each elem in q:&lt;br /&gt;
		int val=q.dequeue()&lt;br /&gt;
		sum=sum + val&lt;br /&gt;
	return sum&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
== 2 ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
queue values;&lt;br /&gt;
semaphore s(0);&lt;br /&gt;
int sum=0;&lt;br /&gt;
&lt;br /&gt;
void sumstop(int v):&lt;br /&gt;
	s.P()&lt;br /&gt;
	values.enqueue(v)&lt;br /&gt;
&lt;br /&gt;
int sumgo(void):&lt;br /&gt;
	while !value.isEmpty():&lt;br /&gt;
		s.V()&lt;br /&gt;
		mutex.P()&lt;br /&gt;
		sum=sum+values.dequeue()&lt;br /&gt;
		mutex.v()&lt;br /&gt;
	return sum&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
== 3 ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
shared int sum=0;&lt;br /&gt;
semaphore wait(0);&lt;br /&gt;
semaphore mutex(1);&lt;br /&gt;
&lt;br /&gt;
void sumstop(int v):&lt;br /&gt;
	mutex.P();&lt;br /&gt;
	sum = sum + v;&lt;br /&gt;
	mutex.V();&lt;br /&gt;
	wait.P();&lt;br /&gt;
&lt;br /&gt;
int sumgo(void):&lt;br /&gt;
	wait.V();&lt;br /&gt;
	somma = sum;&lt;br /&gt;
	mutex.P()&lt;br /&gt;
	sum = 0&lt;br /&gt;
	mutex.V()&lt;br /&gt;
	return somma;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
== 4 ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
queue&amp;lt;int&amp;gt; processlist;&lt;br /&gt;
semaphore mutex(1);&lt;br /&gt;
semaphore s(0);&lt;br /&gt;
&lt;br /&gt;
void sumstop(int v):&lt;br /&gt;
	mutex.P();&lt;br /&gt;
	processlist.enqueue(v);&lt;br /&gt;
	mutex.P(); // V non P&lt;br /&gt;
	S.P();&lt;br /&gt;
&lt;br /&gt;
int sumgo(void):&lt;br /&gt;
	int sum = 0;&lt;br /&gt;
	mutex.P();&lt;br /&gt;
	while processlist.top() != NULL:&lt;br /&gt;
		sum += processlist.dequeue();&lt;br /&gt;
		S.V();&lt;br /&gt;
	mutex.V()&lt;br /&gt;
	return sum;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 5 ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
int counter = 0;&lt;br /&gt;
int sum = 0;&lt;br /&gt;
semaphore mutex(1);&lt;br /&gt;
semaphore blocked(0);&lt;br /&gt;
&lt;br /&gt;
void sumstop(int v):&lt;br /&gt;
	mutex.P();&lt;br /&gt;
	sum+=v;&lt;br /&gt;
	counter++;&lt;br /&gt;
	mutex.V();&lt;br /&gt;
	blocked.P();&lt;br /&gt;
&lt;br /&gt;
int sumgo(void):&lt;br /&gt;
	mutex.P();&lt;br /&gt;
	intret = sum;&lt;br /&gt;
	sum = 0;&lt;br /&gt;
	for (int i=0; i&amp;lt;counter; i++)&lt;br /&gt;
		blocked.V()&lt;br /&gt;
	counter = 0;&lt;br /&gt;
	mutex.V()&lt;br /&gt;
	return intret&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 6 ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
int sum = 0;&lt;br /&gt;
mutex = new semaphore(1);&lt;br /&gt;
queue q;&lt;br /&gt;
&lt;br /&gt;
void sumstop(int v):&lt;br /&gt;
	mutex.P();&lt;br /&gt;
	sum += v;&lt;br /&gt;
	sintpid = getpid();&lt;br /&gt;
	suspend(pid);&lt;br /&gt;
	mutex.V();&lt;br /&gt;
&lt;br /&gt;
int sumgo(void):&lt;br /&gt;
	mutex.P();&lt;br /&gt;
	while !q.empty():&lt;br /&gt;
		resume(q.dequeue())&lt;br /&gt;
	int value = sum;&lt;br /&gt;
	sum = 0;&lt;br /&gt;
	return value;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
== 7 ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
int nP, nV = -1, 0;&lt;br /&gt;
int somma = 0&lt;br /&gt;
int val[]&lt;br /&gt;
semaphore mutex(1);&lt;br /&gt;
semaphore s(0);&lt;br /&gt;
&lt;br /&gt;
void sumstop(int v):&lt;br /&gt;
	mutex.P()&lt;br /&gt;
	val[nP++].add[v]&lt;br /&gt;
	s.P()&lt;br /&gt;
	np--&lt;br /&gt;
	v[0].delete&lt;br /&gt;
&lt;br /&gt;
int sumgo(void):&lt;br /&gt;
	mutex.P();&lt;br /&gt;
	nV++&lt;br /&gt;
	if nP &amp;gt; 0:&lt;br /&gt;
		s.V()&lt;br /&gt;
		for (int i=0; i&amp;lt;nV; i++)&lt;br /&gt;
			somma += val[i]&lt;br /&gt;
			nv--&lt;br /&gt;
	else&lt;br /&gt;
		mutex.V()&lt;br /&gt;
	return somma&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
== 8 ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
struct blocked {&lt;br /&gt;
	semaphore sem(0);&lt;br /&gt;
	int value = 0;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
semaphore mutex(1);&lt;br /&gt;
list&amp;lt;blocked&amp;gt; procs = new list&amp;lt;blocked&amp;gt;();&lt;br /&gt;
&lt;br /&gt;
void sumstop(int v):&lt;br /&gt;
	mutex.P()&lt;br /&gt;
	blocked bl = new blocked();&lt;br /&gt;
	bl.value = v&lt;br /&gt;
	procs.add(bl)&lt;br /&gt;
	bl.sem.P()&lt;br /&gt;
	mutex.V()&lt;br /&gt;
&lt;br /&gt;
int sumgo(void):&lt;br /&gt;
	mutex.P();&lt;br /&gt;
	int count = 0;&lt;br /&gt;
	foreach proc in procs:&lt;br /&gt;
		count += proc.value&lt;br /&gt;
		procs.remove(proc)&lt;br /&gt;
		proc.sem.V()&lt;br /&gt;
	mutex.V()&lt;br /&gt;
	return count;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
== 9 ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
semaphore s[] new sem(0)&lt;br /&gt;
semaphore s1 new sem(0)&lt;br /&gt;
int tot, waiting = 0;&lt;br /&gt;
&lt;br /&gt;
void sumstop(int v):&lt;br /&gt;
	waiting++&lt;br /&gt;
	s[waiting - 1].P()&lt;br /&gt;
	waiting--&lt;br /&gt;
	tot = tot + v&lt;br /&gt;
	if waiting == 0:&lt;br /&gt;
		s1.V()&lt;br /&gt;
&lt;br /&gt;
int sumgo(void):&lt;br /&gt;
	if waiting = 0:&lt;br /&gt;
		return 0&lt;br /&gt;
	for (i = waiting -1; i == 0; i--)&lt;br /&gt;
		s[i].V()&lt;br /&gt;
	s1.P() // per aspettare che tutti abbiano fatto la somma&lt;br /&gt;
	return tot&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 10 ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
int nw = 0&lt;br /&gt;
int currsum = 0&lt;br /&gt;
semaphore mutex(1)&lt;br /&gt;
semaphore wait2go(0)&lt;br /&gt;
&lt;br /&gt;
void sumstop(int v):&lt;br /&gt;
	mutex.P()&lt;br /&gt;
	currsum += v;&lt;br /&gt;
	nw++;&lt;br /&gt;
	mutex.V()&lt;br /&gt;
	wait2go.P()&lt;br /&gt;
	if --nw &amp;gt; 0:&lt;br /&gt;
		wait2go.V()&lt;br /&gt;
	else&lt;br /&gt;
		mutex.V()&lt;br /&gt;
&lt;br /&gt;
int sumgo(void):&lt;br /&gt;
	mutex.P();&lt;br /&gt;
	if nw == 0:&lt;br /&gt;
		mutex.V()&lt;br /&gt;
		return 0;&lt;br /&gt;
	int sum = cursum;&lt;br /&gt;
	cursum = 0;&lt;br /&gt;
	wait2go.V();&lt;br /&gt;
	return sum&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
== 11==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
semaphore mutex(1);&lt;br /&gt;
semaphore semwait(0);&lt;br /&gt;
int sum=0;&lt;br /&gt;
int wait=0;&lt;br /&gt;
&lt;br /&gt;
void sumstop(int v):&lt;br /&gt;
	mutex.P()&lt;br /&gt;
	wait++&lt;br /&gt;
	sum += v;&lt;br /&gt;
	mutex.V()&lt;br /&gt;
	semwait.P()&lt;br /&gt;
	mutex.P()&lt;br /&gt;
	wait--;&lt;br /&gt;
	mutex.V()&lt;br /&gt;
	if wait &amp;gt; 0:&lt;br /&gt;
		semwait.V()&lt;br /&gt;
&lt;br /&gt;
int sumgo(void):&lt;br /&gt;
	if wait == 0:&lt;br /&gt;
		return 0&lt;br /&gt;
	semwait.V();&lt;br /&gt;
	while (wait &amp;gt; 0) {}&lt;br /&gt;
	int val = sum&lt;br /&gt;
	mutex.P()&lt;br /&gt;
	sum = 0;&lt;br /&gt;
	mutex.V()&lt;br /&gt;
	return val;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
== 12 ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
semaphore mutex(0)&lt;br /&gt;
volatile int counter = 0&lt;br /&gt;
&lt;br /&gt;
void sumstop(int v):&lt;br /&gt;
	counter = counter + v;&lt;br /&gt;
	mutex.P()&lt;br /&gt;
&lt;br /&gt;
int sumgo(void):&lt;br /&gt;
	int val = counter;&lt;br /&gt;
	while (mutex.value != 0)&lt;br /&gt;
		mutex.V()&lt;br /&gt;
	counter = 0;&lt;br /&gt;
	return counter&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
== 13 == &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
semaphore mutex(1)&lt;br /&gt;
int sum = 0;&lt;br /&gt;
queue of semaphore q;&lt;br /&gt;
&lt;br /&gt;
void sumstop(int v):&lt;br /&gt;
	mutex.P()&lt;br /&gt;
	sum += v;&lt;br /&gt;
	s = new semaphore(0);&lt;br /&gt;
	q.enqueue(s)&lt;br /&gt;
	mutex.V()&lt;br /&gt;
	s.P()&lt;br /&gt;
	free(s)&lt;br /&gt;
&lt;br /&gt;
int sumgo(void):&lt;br /&gt;
	mutex.P()&lt;br /&gt;
	int lsum = sum&lt;br /&gt;
	sum = 0&lt;br /&gt;
	while (!q.empty()):&lt;br /&gt;
		semaphore s = q.dequeue()&lt;br /&gt;
		s.V()&lt;br /&gt;
	mutex.V()&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
== 14 ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
semaphore mutex(1)&lt;br /&gt;
int sum = 0;&lt;br /&gt;
queue of semaphore q;&lt;br /&gt;
&lt;br /&gt;
void sumstop(int v):&lt;br /&gt;
	mutex.P()&lt;br /&gt;
	sum += v;&lt;br /&gt;
	s = new semaphore(0);&lt;br /&gt;
	q.enqueue(s)&lt;br /&gt;
	mutex.V()&lt;br /&gt;
	s.P()&lt;br /&gt;
	free(s)&lt;br /&gt;
	if(q.empty())&lt;br /&gt;
		mutex.V()&lt;br /&gt;
	else&lt;br /&gt;
		semaphore s = q.dequeue()&lt;br /&gt;
		s.V()&lt;br /&gt;
&lt;br /&gt;
int sumgo(void):&lt;br /&gt;
	mutex.P()&lt;br /&gt;
	int lsum = sum&lt;br /&gt;
	sum = 0&lt;br /&gt;
	if(q.empty())&lt;br /&gt;
		mutex.V()&lt;br /&gt;
	else&lt;br /&gt;
		semaphore s = q.dequeue()&lt;br /&gt;
		s.V()&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 15 (soluzione proposta su telegram) ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
#include &amp;lt;pthread.h&amp;gt;&lt;br /&gt;
#include &amp;quot;semaphore.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
semaphore s; // semaforo che blocca le somme&lt;br /&gt;
semaphore finished; // semaforo che indica che le somme sono state fatte&lt;br /&gt;
semaphore critical_section; // sarà utilizzata per decidere chi entra nella critical section&lt;br /&gt;
&lt;br /&gt;
volatile int sumstops = 0;&lt;br /&gt;
volatile int result;&lt;br /&gt;
&lt;br /&gt;
void *sumstop(int v) {&lt;br /&gt;
    semaphore_P(critical_section);&lt;br /&gt;
    sumstops++;&lt;br /&gt;
    semaphore_V(critical_section);&lt;br /&gt;
&lt;br /&gt;
    semaphore_P(s);&lt;br /&gt;
    printf(&amp;quot;summed %d\n&amp;quot;, v);&lt;br /&gt;
    result += v;&lt;br /&gt;
    semaphore_V(finished);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int sumgo(void) {&lt;br /&gt;
    semaphore_P(critical_section); // così sumstops è costante all'interno di questa section&lt;br /&gt;
    result = 0;&lt;br /&gt;
    for (int i = 0; i &amp;lt; sumstops; i++) {&lt;br /&gt;
        semaphore_V(s); // permetti alla somma di andare&lt;br /&gt;
        semaphore_P(finished); // aspetta che la somma sia finita prima di continuare&lt;br /&gt;
    }&lt;br /&gt;
    sumstops = 0; // reset number of blocked stops.&lt;br /&gt;
    semaphore_V(critical_section);&lt;br /&gt;
    return result;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void *run_sumgo(void) {&lt;br /&gt;
    int res = sumgo();&lt;br /&gt;
    printf(&amp;quot;the result found is %d\n&amp;quot;, res);&lt;br /&gt;
    printf(&amp;quot;the result found is %d\n&amp;quot;, result);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
    srand(time(NULL));&lt;br /&gt;
    s = semaphore_create(0);&lt;br /&gt;
    critical_section = semaphore_create(1);&lt;br /&gt;
    finished = semaphore_create(0);&lt;br /&gt;
&lt;br /&gt;
    int n = rand() % 50;&lt;br /&gt;
    pthread_t sumg, s[n];&lt;br /&gt;
&lt;br /&gt;
    for (int i = 0; i &amp;lt; n; i++) {&lt;br /&gt;
        pthread_create(&amp;amp;s[i], NULL, sumstop, i);&lt;br /&gt;
    }&lt;br /&gt;
    pthread_create(&amp;amp;sumg, NULL, run_sumgo, NULL);&lt;br /&gt;
&lt;br /&gt;
    for (int i = 0; i &amp;lt; 10; i++) {&lt;br /&gt;
        pthread_join(s[i], NULL);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    pthread_join(sumg, NULL);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Correzioni proposte ==&lt;br /&gt;
&lt;br /&gt;
Correzione proposta da [https://t.me/flecarts flecart]&lt;br /&gt;
(e poi modificata successivamente da altri studenti ... tra cui: [https://t.me/LLibera LLibera] )&lt;br /&gt;
&lt;br /&gt;
1. la variabile i non è inizializzata, sum e queue non sono protette in critical sections, inoltre la sem.V() non compare mai nel codice della sumgo.&lt;br /&gt;
&lt;br /&gt;
2. la coda value non è in una critical section, può creare errori nell'update di essa, solo sum viene considerata da proteggere, ma devono essere protette entrambe. La enqueue avrebbe senso farla solo prima di bloccarsi nel semaforo, se viene fatta dopo al momento della chiamata di sumgo non ci sono valori all'interno della coda!&lt;br /&gt;
&lt;br /&gt;
3. sumgo libera solamente un singolo sumstop, perché chiama wait.V() una singola volta anche se ci sono più thread in attesa&lt;br /&gt;
&lt;br /&gt;
4. mutex.P() è chiamata due volte in sumstop(), se il secondo fosse mutex.V() credo sia corretto. &lt;br /&gt;
&lt;br /&gt;
5. mi sembra corretto (ma l'indentazione è poco sensata).&lt;br /&gt;
 &lt;br /&gt;
6. non si possono utilizzare suspend o resume (non si è fatto uso di semafori, e l'implementazione deve essere fatta all'esterno del kernel non all'interno). Oltre a questo pid non è inizializzata e sintpid non è utilizzata. Se anche la suspend fosse una sem.P() e la resume una sem.V() non dovremmo sospendere il processo all'interno della mutua esclusione.&lt;br /&gt;
 &lt;br /&gt;
7. nP e nV mi sembrano superflue, in questo caso sicuramente scorrette perché se chiamo m volte sumstop e una volta sumgo, nV è al massimo 1&lt;br /&gt;
quindi è impossibile che riesca a contare correttamente tutte le somme.&lt;br /&gt;
 &lt;br /&gt;
8. Deadlock perché bl.sem.P() è chiamato prima che ls Critical Section venga rilasciata e sumgo ha bisogno di entrare in una CS.&lt;br /&gt;
 &lt;br /&gt;
9. waiting è una variabile globale modificata senza cs, e tot non è inizializzato.&lt;br /&gt;
 &lt;br /&gt;
10. simile a 3. wait2go è chiamata una volta quindi può liberare solamente un singolo thread di sumstop.&lt;br /&gt;
&lt;br /&gt;
11. busy waiting in sumgo.&lt;br /&gt;
&lt;br /&gt;
12. counter non è protetto da Critical section &lt;br /&gt;
&lt;br /&gt;
13. se sumgo ritornasse il valore  lsum sarebbe tutto apposto.&lt;br /&gt;
&lt;br /&gt;
14. mi sembra corretto, manca solo la return in sumgo&lt;br /&gt;
&lt;br /&gt;
15. mi sembra corretto&lt;/div&gt;</summary>
		<author><name>LiberaL</name></author>
	</entry>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=20220906c2&amp;diff=2792</id>
		<title>20220906c2</title>
		<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php?title=20220906c2&amp;diff=2792"/>
		<updated>2022-10-20T07:47:07Z</updated>

		<summary type="html">&lt;p&gt;LiberaL: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;In questa pagina sono presenti alcune soluzioni (possibilmente con errore) per l'esercizio C2 dell'esame 2022/09/06.&lt;br /&gt;
Il lettore è invitato a immedesimare il professore al momento della correzione durante la lettura delle soluzioni.&lt;br /&gt;
&lt;br /&gt;
== Consegna ==&lt;br /&gt;
Usando i semafori implementare un servizio che preveda due funzioni:&lt;br /&gt;
   void sumstop(int v)&lt;br /&gt;
   int sumgo(void) &lt;br /&gt;
La funzione sumstop deve mettere il processo chiamante in attesa.&lt;br /&gt;
La funzione sumgo deve sbloccare tutti i processi messi in attesa con la sumstop e restituire la somma algebrica dei valori passati come parametro alla  sumstop dai processi che sono stati sbloccati (zero se la  sumgo viene richiamata quando non c'è nessun processo bloccato).&lt;br /&gt;
== 1 ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
semaphore sem(1);&lt;br /&gt;
int sum=0;&lt;br /&gt;
queue q;&lt;br /&gt;
&lt;br /&gt;
void sumstop(int v):&lt;br /&gt;
	if i &amp;lt; 0:&lt;br /&gt;
		q.enqueue(v)&lt;br /&gt;
		sem.P()&lt;br /&gt;
	else&lt;br /&gt;
		i--&lt;br /&gt;
&lt;br /&gt;
int sumgo(void):&lt;br /&gt;
	for each elem in q:&lt;br /&gt;
		int val=q.dequeue()&lt;br /&gt;
		sum=sum + val&lt;br /&gt;
	return sum&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
== 2 ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
queue values;&lt;br /&gt;
semaphore s(0);&lt;br /&gt;
int sum=0;&lt;br /&gt;
&lt;br /&gt;
void sumstop(int v):&lt;br /&gt;
	s.P()&lt;br /&gt;
	values.enqueue(v)&lt;br /&gt;
&lt;br /&gt;
int sumgo(void):&lt;br /&gt;
	while !value.isEmpty():&lt;br /&gt;
		s.V()&lt;br /&gt;
		mutex.P()&lt;br /&gt;
		sum=sum+values.dequeue()&lt;br /&gt;
		mutex.v()&lt;br /&gt;
	return sum&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
== 3 ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
shared int sum=0;&lt;br /&gt;
semaphore wait(0);&lt;br /&gt;
semaphore mutex(1);&lt;br /&gt;
&lt;br /&gt;
void sumstop(int v):&lt;br /&gt;
	mutex.P();&lt;br /&gt;
	sum = sum + v;&lt;br /&gt;
	mutex.V();&lt;br /&gt;
	wait.P();&lt;br /&gt;
&lt;br /&gt;
int sumgo(void):&lt;br /&gt;
	wait.V();&lt;br /&gt;
	somma = sum;&lt;br /&gt;
	mutex.P()&lt;br /&gt;
	sum = 0&lt;br /&gt;
	mutex.V()&lt;br /&gt;
	return somma;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
== 4 ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
queue&amp;lt;int&amp;gt; processlist;&lt;br /&gt;
semaphore mutex(1);&lt;br /&gt;
semaphore s(0);&lt;br /&gt;
&lt;br /&gt;
void sumstop(int v):&lt;br /&gt;
	mutex.P();&lt;br /&gt;
	processlist.enqueue(v);&lt;br /&gt;
	mutex.P();&lt;br /&gt;
	S.P();&lt;br /&gt;
&lt;br /&gt;
int sumgo(void):&lt;br /&gt;
	int sum = 0;&lt;br /&gt;
	mutex.P();&lt;br /&gt;
	while processlist.top() != NULL:&lt;br /&gt;
		sum += processlist.dequeue();&lt;br /&gt;
		S.V();&lt;br /&gt;
	mutex.V()&lt;br /&gt;
	return sum;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
== 5 ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
int counter = 0;&lt;br /&gt;
int sum = 0;&lt;br /&gt;
semaphore mutex(1);&lt;br /&gt;
semaphore blocked(0);&lt;br /&gt;
&lt;br /&gt;
void sumstop(int v):&lt;br /&gt;
	mutex.P();&lt;br /&gt;
	sum+=v;&lt;br /&gt;
	counter++;&lt;br /&gt;
	mutex.V();&lt;br /&gt;
	blocked.P();&lt;br /&gt;
&lt;br /&gt;
int sumgo(void):&lt;br /&gt;
	  mutex.P();&lt;br /&gt;
		intret = sum;&lt;br /&gt;
		sum = 0;&lt;br /&gt;
		for (int i=0; i&amp;lt;counter; i++)&lt;br /&gt;
			blocked.V()&lt;br /&gt;
		counter = 0;&lt;br /&gt;
		mutex.V()&lt;br /&gt;
	return intret&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
== 6 ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
int sum = 0;&lt;br /&gt;
mutex = new semaphore(1);&lt;br /&gt;
queue q;&lt;br /&gt;
&lt;br /&gt;
void sumstop(int v):&lt;br /&gt;
	mutex.P();&lt;br /&gt;
	sum += v;&lt;br /&gt;
	sintpid = getpid();&lt;br /&gt;
	suspend(pid);&lt;br /&gt;
	mutex.V();&lt;br /&gt;
&lt;br /&gt;
int sumgo(void):&lt;br /&gt;
	mutex.P();&lt;br /&gt;
	while !q.empty():&lt;br /&gt;
		resume(q.dequeue())&lt;br /&gt;
	int value = sum;&lt;br /&gt;
	sum = 0;&lt;br /&gt;
	return value;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
== 7 ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
int nP, nV = -1, 0;&lt;br /&gt;
int somma = 0&lt;br /&gt;
int val[]&lt;br /&gt;
semaphore mutex(1);&lt;br /&gt;
semaphore s(0);&lt;br /&gt;
&lt;br /&gt;
void sumstop(int v):&lt;br /&gt;
	mutex.P()&lt;br /&gt;
	val[nP++].add[v]&lt;br /&gt;
	s.P()&lt;br /&gt;
	np--&lt;br /&gt;
	v[0].delete&lt;br /&gt;
&lt;br /&gt;
int sumgo(void):&lt;br /&gt;
	mutex.P();&lt;br /&gt;
	nV++&lt;br /&gt;
	if nP &amp;gt; 0:&lt;br /&gt;
		s.V()&lt;br /&gt;
		for (int i=0; i&amp;lt;nV; i++)&lt;br /&gt;
			somma += val[i]&lt;br /&gt;
			nv--&lt;br /&gt;
	else&lt;br /&gt;
		mutex.V()&lt;br /&gt;
	return somma&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
== 8 ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
struct blocked {&lt;br /&gt;
	semaphore sem(0);&lt;br /&gt;
	int value = 0;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
semaphore mutex(1);&lt;br /&gt;
list&amp;lt;blocked&amp;gt; procs = new list&amp;lt;blocked&amp;gt;();&lt;br /&gt;
&lt;br /&gt;
void sumstop(int v):&lt;br /&gt;
	mutex.P()&lt;br /&gt;
	blocked bl = new blocked();&lt;br /&gt;
	bl.value = v&lt;br /&gt;
	procs.add(bl)&lt;br /&gt;
	bl.sem.P()&lt;br /&gt;
	mutex.V()&lt;br /&gt;
&lt;br /&gt;
int sumgo(void):&lt;br /&gt;
	mutex.P();&lt;br /&gt;
	int count = 0;&lt;br /&gt;
	foreach proc in procs:&lt;br /&gt;
		count += proc.value&lt;br /&gt;
		procs.remove(proc)&lt;br /&gt;
		proc.sem.V()&lt;br /&gt;
	mutex.V()&lt;br /&gt;
	return count;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
== 9 ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
semaphore s[] new sem(0)&lt;br /&gt;
semaphore s1 new sem(0)&lt;br /&gt;
int tot, waiting = 0;&lt;br /&gt;
&lt;br /&gt;
void sumstop(int v):&lt;br /&gt;
	waiting++&lt;br /&gt;
	s[waiting - 1].P()&lt;br /&gt;
	waiting--&lt;br /&gt;
	tot = tot + v&lt;br /&gt;
	if waiting == 0:&lt;br /&gt;
		s1.V()&lt;br /&gt;
&lt;br /&gt;
int sumgo(void):&lt;br /&gt;
	if waiting = 0:&lt;br /&gt;
		return 0&lt;br /&gt;
	for (i = waiting -1; i == 0; i--)&lt;br /&gt;
		s[i].V()&lt;br /&gt;
	s1.P() // per aspettare che tutti abbiano fatto la somma&lt;br /&gt;
	return tot&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 10 ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
int nw = 0&lt;br /&gt;
int currsum = 0&lt;br /&gt;
semaphore mutex(1)&lt;br /&gt;
semaphore wait2go(0)&lt;br /&gt;
&lt;br /&gt;
void sumstop(int v):&lt;br /&gt;
	mutex.P()&lt;br /&gt;
	currsum += v;&lt;br /&gt;
	nw++;&lt;br /&gt;
	mutex.V()&lt;br /&gt;
	wait2go.P()&lt;br /&gt;
	if --nw &amp;gt; 0:&lt;br /&gt;
		wait2go.V()&lt;br /&gt;
	else&lt;br /&gt;
		mutex.V()&lt;br /&gt;
&lt;br /&gt;
int sumgo(void):&lt;br /&gt;
	mutex.P();&lt;br /&gt;
	if nw == 0:&lt;br /&gt;
		mutex.V()&lt;br /&gt;
		return 0;&lt;br /&gt;
	int sum = cursum;&lt;br /&gt;
	cursum = 0;&lt;br /&gt;
	wait2go.V();&lt;br /&gt;
	return sum&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
== 11==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
semaphore mutex(1);&lt;br /&gt;
semaphore semwait(0);&lt;br /&gt;
int sum=0;&lt;br /&gt;
int wait=0;&lt;br /&gt;
&lt;br /&gt;
void sumstop(int v):&lt;br /&gt;
	mutex.P()&lt;br /&gt;
	wait++&lt;br /&gt;
	sum += v;&lt;br /&gt;
	mutex.V()&lt;br /&gt;
	semwait.P()&lt;br /&gt;
	mutex.P()&lt;br /&gt;
	wait--;&lt;br /&gt;
	mutex.V()&lt;br /&gt;
	if wait &amp;gt; 0:&lt;br /&gt;
		semwait.V()&lt;br /&gt;
&lt;br /&gt;
int sumgo(void):&lt;br /&gt;
	if wait == 0:&lt;br /&gt;
		return 0&lt;br /&gt;
	semwait.V();&lt;br /&gt;
	while (wait &amp;gt; 0) {}&lt;br /&gt;
	int val = sum&lt;br /&gt;
	mutex.P()&lt;br /&gt;
	sum = 0;&lt;br /&gt;
	mutex.V()&lt;br /&gt;
	return val;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
== 12 ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
semaphore mutex(0)&lt;br /&gt;
volatile int counter = 0&lt;br /&gt;
&lt;br /&gt;
void sumstop(int v):&lt;br /&gt;
	counter = counter + v;&lt;br /&gt;
	mutex.P()&lt;br /&gt;
&lt;br /&gt;
int sumgo(void):&lt;br /&gt;
	int val = counter;&lt;br /&gt;
	while (mutex.value != 0)&lt;br /&gt;
		mutex.V()&lt;br /&gt;
	counter = 0;&lt;br /&gt;
	return counter&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
== 13 == &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
semaphore mutex(1)&lt;br /&gt;
int sum = 0;&lt;br /&gt;
queue of semaphore q;&lt;br /&gt;
&lt;br /&gt;
void sumstop(int v):&lt;br /&gt;
	mutex.P()&lt;br /&gt;
	sum += v;&lt;br /&gt;
	s = new semaphore(0);&lt;br /&gt;
	q.enqueue(s)&lt;br /&gt;
	mutex.V()&lt;br /&gt;
	s.P()&lt;br /&gt;
	free(s)&lt;br /&gt;
&lt;br /&gt;
int sumgo(void):&lt;br /&gt;
	mutex.P()&lt;br /&gt;
	int lsum = sum&lt;br /&gt;
	sum = 0&lt;br /&gt;
	while (!q.empty()):&lt;br /&gt;
		semaphore s = q.dequeue()&lt;br /&gt;
		s.V()&lt;br /&gt;
	mutex.V()&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
== 14 ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
semaphore mutex(1)&lt;br /&gt;
int sum = 0;&lt;br /&gt;
queue of semaphore q;&lt;br /&gt;
&lt;br /&gt;
void sumstop(int v):&lt;br /&gt;
	mutex.P()&lt;br /&gt;
	sum += v;&lt;br /&gt;
	s = new semaphore(0);&lt;br /&gt;
	q.enqueue(s)&lt;br /&gt;
	mutex.V()&lt;br /&gt;
	s.P()&lt;br /&gt;
	free(s)&lt;br /&gt;
	if(q.empty())&lt;br /&gt;
		mutex.V()&lt;br /&gt;
	else&lt;br /&gt;
		semaphore s = q.dequeue()&lt;br /&gt;
		s.V()&lt;br /&gt;
&lt;br /&gt;
int sumgo(void):&lt;br /&gt;
	mutex.P()&lt;br /&gt;
	int lsum = sum&lt;br /&gt;
	sum = 0&lt;br /&gt;
	if(q.empty())&lt;br /&gt;
		mutex.V()&lt;br /&gt;
	else&lt;br /&gt;
		semaphore s = q.dequeue()&lt;br /&gt;
		s.V()&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 15 (soluzione proposta su telegram) ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
#include &amp;lt;pthread.h&amp;gt;&lt;br /&gt;
#include &amp;quot;semaphore.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
semaphore s; // semaforo che blocca le somme&lt;br /&gt;
semaphore finished; // semaforo che indica che le somme sono state fatte&lt;br /&gt;
semaphore critical_section; // sarà utilizzata per decidere chi entra nella critical section&lt;br /&gt;
&lt;br /&gt;
volatile int sumstops = 0;&lt;br /&gt;
volatile int result;&lt;br /&gt;
&lt;br /&gt;
void *sumstop(int v) {&lt;br /&gt;
    semaphore_P(critical_section);&lt;br /&gt;
    sumstops++;&lt;br /&gt;
    semaphore_V(critical_section);&lt;br /&gt;
&lt;br /&gt;
    semaphore_P(s);&lt;br /&gt;
    printf(&amp;quot;summed %d\n&amp;quot;, v);&lt;br /&gt;
    result += v;&lt;br /&gt;
    semaphore_V(finished);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int sumgo(void) {&lt;br /&gt;
    semaphore_P(critical_section); // così sumstops è costante all'interno di questa section&lt;br /&gt;
    result = 0;&lt;br /&gt;
    for (int i = 0; i &amp;lt; sumstops; i++) {&lt;br /&gt;
        semaphore_V(s); // permetti alla somma di andare&lt;br /&gt;
        semaphore_P(finished); // aspetta che la somma sia finita prima di continuare&lt;br /&gt;
    }&lt;br /&gt;
    sumstops = 0; // reset number of blocked stops.&lt;br /&gt;
    semaphore_V(critical_section);&lt;br /&gt;
    return result;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void *run_sumgo(void) {&lt;br /&gt;
    int res = sumgo();&lt;br /&gt;
    printf(&amp;quot;the result found is %d\n&amp;quot;, res);&lt;br /&gt;
    printf(&amp;quot;the result found is %d\n&amp;quot;, result);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
    srand(time(NULL));&lt;br /&gt;
    s = semaphore_create(0);&lt;br /&gt;
    critical_section = semaphore_create(1);&lt;br /&gt;
    finished = semaphore_create(0);&lt;br /&gt;
&lt;br /&gt;
    int n = rand() % 50;&lt;br /&gt;
    pthread_t sumg, s[n];&lt;br /&gt;
&lt;br /&gt;
    for (int i = 0; i &amp;lt; n; i++) {&lt;br /&gt;
        pthread_create(&amp;amp;s[i], NULL, sumstop, i);&lt;br /&gt;
    }&lt;br /&gt;
    pthread_create(&amp;amp;sumg, NULL, run_sumgo, NULL);&lt;br /&gt;
&lt;br /&gt;
    for (int i = 0; i &amp;lt; 10; i++) {&lt;br /&gt;
        pthread_join(s[i], NULL);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    pthread_join(sumg, NULL);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Correzioni proposte ==&lt;br /&gt;
&lt;br /&gt;
Correzione proposta da [https://t.me/flecarts flecart]&lt;br /&gt;
(e poi modificata successivamente da altri studenti ... tra cui: [https://t.me/LLibera LLibera] )&lt;br /&gt;
&lt;br /&gt;
1. la variabile i non è inizializzata, sum e queue non sono protette in critical sections, inoltre la sem.V() non compare mai nel codice della sumgo.&lt;br /&gt;
&lt;br /&gt;
2. la coda value non è in una critical section, può creare errori nell'update di essa, solo sum viene considerata da proteggere, ma devono essere protette entrambe. La enqueue avrebbe senso farla solo prima di bloccarsi nel semaforo, se viene fatta dopo al momento della chiamata di sumgo non ci sono valori all'interno della coda!&lt;br /&gt;
&lt;br /&gt;
3. sumgo libera solamente un singolo sumstop, perché chiama wait.V() una singola volta anche se ci sono più thread in attesa&lt;br /&gt;
&lt;br /&gt;
4. mutex.P() è chiamata due volte in sumstop(), se il secondo fosse mutex.V() credo sia corretto. &lt;br /&gt;
&lt;br /&gt;
5. mi sembra corretto (ma l'indentazione è poco sensata).&lt;br /&gt;
 &lt;br /&gt;
6. non si possono utilizzare suspend o resume (non si è fatto uso di semafori, e l'implementazione deve essere fatta all'esterno del kernel non all'interno). Oltre a questo pid non è inizializzata e sintpid non è utilizzata. Se anche la suspend fosse una sem.P() e la resume una sem.V() non dovremmo sospendere il processo all'interno della mutua esclusione.&lt;br /&gt;
 &lt;br /&gt;
7. nP e nV mi sembrano superflue, in questo caso sicuramente scorrette perché se chiamo m volte sumstop e una volta sumgo, nV è al massimo 1&lt;br /&gt;
quindi è impossibile che riesca a contare correttamente tutte le somme.&lt;br /&gt;
 &lt;br /&gt;
8. Deadlock perché bl.sem.P() è chiamato prima che ls Critical Section venga rilasciata e sumgo ha bisogno di entrare in una CS.&lt;br /&gt;
 &lt;br /&gt;
9. waiting è una variabile globale modificata senza cs, e tot non è inizializzato.&lt;br /&gt;
 &lt;br /&gt;
10. simile a 3. wait2go è chiamata una volta quindi può liberare solamente un singolo thread di sumstop.&lt;br /&gt;
&lt;br /&gt;
11. busy waiting in sumgo.&lt;br /&gt;
&lt;br /&gt;
12. counter non è protetto da Critical section &lt;br /&gt;
&lt;br /&gt;
13. se sumgo ritornasse il valore  lsum sarebbe tutto apposto.&lt;br /&gt;
&lt;br /&gt;
14. mi sembra corretto&lt;br /&gt;
&lt;br /&gt;
15. mi sembra corretto&lt;/div&gt;</summary>
		<author><name>LiberaL</name></author>
	</entry>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=20220906c2&amp;diff=2791</id>
		<title>20220906c2</title>
		<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php?title=20220906c2&amp;diff=2791"/>
		<updated>2022-10-20T07:45:51Z</updated>

		<summary type="html">&lt;p&gt;LiberaL: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;In questa pagina sono presenti alcune soluzioni (possibilmente con errore) per l'esercizio C2 dell'esame 2022/09/06.&lt;br /&gt;
Il lettore è invitato a immedesimare il professore al momento della correzione durante la lettura delle soluzioni.&lt;br /&gt;
&lt;br /&gt;
== Consegna ==&lt;br /&gt;
Usando i semafori implementare un servizio che preveda due funzioni:&lt;br /&gt;
   void sumstop(int v)&lt;br /&gt;
   int sumgo(void) &lt;br /&gt;
La funzione sumstop deve mettere il processo chiamante in attesa.&lt;br /&gt;
La funzione sumgo deve sbloccare tutti i processi messi in attesa con la sumstop e restituire la somma algebrica dei valori passati come parametro alla  sumstop dai processi che sono stati sbloccati (zero se la  sumgo viene richiamata quando non c'è nessun processo bloccato).&lt;br /&gt;
== 1 ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
semaphore sem(1);&lt;br /&gt;
int sum=0;&lt;br /&gt;
queue q;&lt;br /&gt;
&lt;br /&gt;
void sumstop(int v):&lt;br /&gt;
	if i &amp;lt; 0:&lt;br /&gt;
		q.enqueue(v)&lt;br /&gt;
		sem.P()&lt;br /&gt;
	else&lt;br /&gt;
		i--&lt;br /&gt;
&lt;br /&gt;
int sumgo(void):&lt;br /&gt;
	for each elem in q:&lt;br /&gt;
		int val=q.dequeue()&lt;br /&gt;
		sum=sum + val&lt;br /&gt;
	return sum&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
== 2 ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
queue values;&lt;br /&gt;
semaphore s(0);&lt;br /&gt;
int sum=0;&lt;br /&gt;
&lt;br /&gt;
void sumstop(int v):&lt;br /&gt;
	s.P()&lt;br /&gt;
	values.enqueue(v)&lt;br /&gt;
&lt;br /&gt;
int sumgo(void):&lt;br /&gt;
	while !value.isEmpty():&lt;br /&gt;
		s.V()&lt;br /&gt;
		mutex.P()&lt;br /&gt;
		sum=sum+values.dequeue()&lt;br /&gt;
		mutex.v()&lt;br /&gt;
	return sum&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
== 3 ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
shared int sum=0;&lt;br /&gt;
semaphore wait(0);&lt;br /&gt;
semaphore mutex(1);&lt;br /&gt;
&lt;br /&gt;
void sumstop(int v):&lt;br /&gt;
	mutex.P();&lt;br /&gt;
	sum = sum + v;&lt;br /&gt;
	mutex.V();&lt;br /&gt;
	wait.P();&lt;br /&gt;
&lt;br /&gt;
int sumgo(void):&lt;br /&gt;
	wait.V();&lt;br /&gt;
	somma = sum;&lt;br /&gt;
	mutex.P()&lt;br /&gt;
	sum = 0&lt;br /&gt;
	mutex.V()&lt;br /&gt;
	return somma;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
== 4 ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
queue&amp;lt;int&amp;gt; processlist;&lt;br /&gt;
semaphore mutex(1);&lt;br /&gt;
semaphore s(0);&lt;br /&gt;
&lt;br /&gt;
void sumstop(int v):&lt;br /&gt;
	mutex.P();&lt;br /&gt;
	processlist.enqueue(v);&lt;br /&gt;
	mutex.P();&lt;br /&gt;
	S.P();&lt;br /&gt;
&lt;br /&gt;
int sumgo(void):&lt;br /&gt;
	int sum = 0;&lt;br /&gt;
	mutex.P();&lt;br /&gt;
	while processlist.top() != NULL:&lt;br /&gt;
		sum += processlist.dequeue();&lt;br /&gt;
		S.V();&lt;br /&gt;
	mutex.V()&lt;br /&gt;
	return sum;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
== 5 ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
int counter = 0;&lt;br /&gt;
int sum = 0;&lt;br /&gt;
semaphore mutex(1);&lt;br /&gt;
semaphore blocked(0);&lt;br /&gt;
&lt;br /&gt;
void sumstop(int v):&lt;br /&gt;
	mutex.P();&lt;br /&gt;
	sum+=v;&lt;br /&gt;
	counter++;&lt;br /&gt;
	mutex.V();&lt;br /&gt;
	blocked.P();&lt;br /&gt;
&lt;br /&gt;
int sumgo(void):&lt;br /&gt;
	  mutex.P();&lt;br /&gt;
		intret = sum;&lt;br /&gt;
		sum = 0;&lt;br /&gt;
		for (int i=0; i&amp;lt;counter; i++)&lt;br /&gt;
			blocked.V()&lt;br /&gt;
		counter = 0;&lt;br /&gt;
		mutex.V()&lt;br /&gt;
	return intret&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
== 6 ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
int sum = 0;&lt;br /&gt;
mutex = new semaphore(1);&lt;br /&gt;
queue q;&lt;br /&gt;
&lt;br /&gt;
void sumstop(int v):&lt;br /&gt;
	mutex.P();&lt;br /&gt;
	sum += v;&lt;br /&gt;
	sintpid = getpid();&lt;br /&gt;
	suspend(pid);&lt;br /&gt;
	mutex.V();&lt;br /&gt;
&lt;br /&gt;
int sumgo(void):&lt;br /&gt;
	mutex.P();&lt;br /&gt;
	while !q.empty():&lt;br /&gt;
		resume(q.dequeue())&lt;br /&gt;
	int value = sum;&lt;br /&gt;
	sum = 0;&lt;br /&gt;
	return value;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
== 7 ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
int nP, nV = -1, 0;&lt;br /&gt;
int somma = 0&lt;br /&gt;
int val[]&lt;br /&gt;
semaphore mutex(1);&lt;br /&gt;
semaphore s(0);&lt;br /&gt;
&lt;br /&gt;
void sumstop(int v):&lt;br /&gt;
	mutex.P()&lt;br /&gt;
	val[nP++].add[v]&lt;br /&gt;
	s.P()&lt;br /&gt;
	np--&lt;br /&gt;
	v[0].delete&lt;br /&gt;
&lt;br /&gt;
int sumgo(void):&lt;br /&gt;
	mutex.P();&lt;br /&gt;
	nV++&lt;br /&gt;
	if nP &amp;gt; 0:&lt;br /&gt;
		s.V()&lt;br /&gt;
		for (int i=0; i&amp;lt;nV; i++)&lt;br /&gt;
			somma += val[i]&lt;br /&gt;
			nv--&lt;br /&gt;
	else&lt;br /&gt;
		mutex.V()&lt;br /&gt;
	return somma&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
== 8 ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
struct blocked {&lt;br /&gt;
	semaphore sem(0);&lt;br /&gt;
	int value = 0;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
semaphore mutex(1);&lt;br /&gt;
list&amp;lt;blocked&amp;gt; procs = new list&amp;lt;blocked&amp;gt;();&lt;br /&gt;
&lt;br /&gt;
void sumstop(int v):&lt;br /&gt;
	mutex.P()&lt;br /&gt;
	blocked bl = new blocked();&lt;br /&gt;
	bl.value = v&lt;br /&gt;
	procs.add(bl)&lt;br /&gt;
	bl.sem.P()&lt;br /&gt;
	mutex.V()&lt;br /&gt;
&lt;br /&gt;
int sumgo(void):&lt;br /&gt;
	mutex.P();&lt;br /&gt;
	int count = 0;&lt;br /&gt;
	foreach proc in procs:&lt;br /&gt;
		count += proc.value&lt;br /&gt;
		procs.remove(proc)&lt;br /&gt;
		proc.sem.V()&lt;br /&gt;
	mutex.V()&lt;br /&gt;
	return count;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
== 9 ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
semaphore s[] new sem(0)&lt;br /&gt;
semaphore s1 new sem(0)&lt;br /&gt;
int tot, waiting = 0;&lt;br /&gt;
&lt;br /&gt;
void sumstop(int v):&lt;br /&gt;
	waiting++&lt;br /&gt;
	s[waiting - 1].P()&lt;br /&gt;
	waiting--&lt;br /&gt;
	tot = tot + v&lt;br /&gt;
	if waiting == 0:&lt;br /&gt;
		s1.V()&lt;br /&gt;
&lt;br /&gt;
int sumgo(void):&lt;br /&gt;
	if waiting = 0:&lt;br /&gt;
		return 0&lt;br /&gt;
	for (i = waiting -1; i == 0; i--)&lt;br /&gt;
		s[i].V()&lt;br /&gt;
	s1.P() // per aspettare che tutti abbiano fatto la somma&lt;br /&gt;
	return tot&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 10 ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
int nw = 0&lt;br /&gt;
int currsum = 0&lt;br /&gt;
semaphore mutex(1)&lt;br /&gt;
semaphore wait2go(0)&lt;br /&gt;
&lt;br /&gt;
void sumstop(int v):&lt;br /&gt;
	mutex.P()&lt;br /&gt;
	currsum += v;&lt;br /&gt;
	nw++;&lt;br /&gt;
	mutex.V()&lt;br /&gt;
	wait2go.P()&lt;br /&gt;
	if --nw &amp;gt; 0:&lt;br /&gt;
		wait2go.V()&lt;br /&gt;
	else&lt;br /&gt;
		mutex.V()&lt;br /&gt;
&lt;br /&gt;
int sumgo(void):&lt;br /&gt;
	mutex.P();&lt;br /&gt;
	if nw == 0:&lt;br /&gt;
		mutex.V()&lt;br /&gt;
		return 0;&lt;br /&gt;
	int sum = cursum;&lt;br /&gt;
	cursum = 0;&lt;br /&gt;
	wait2go.V();&lt;br /&gt;
	return sum&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
== 11==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
semaphore mutex(1);&lt;br /&gt;
semaphore semwait(0);&lt;br /&gt;
int sum=0;&lt;br /&gt;
int wait=0;&lt;br /&gt;
&lt;br /&gt;
void sumstop(int v):&lt;br /&gt;
	mutex.P()&lt;br /&gt;
	wait++&lt;br /&gt;
	sum += v;&lt;br /&gt;
	mutex.V()&lt;br /&gt;
	semwait.P()&lt;br /&gt;
	mutex.P()&lt;br /&gt;
	wait--;&lt;br /&gt;
	mutex.V()&lt;br /&gt;
	if wait &amp;gt; 0:&lt;br /&gt;
		semwait.V()&lt;br /&gt;
&lt;br /&gt;
int sumgo(void):&lt;br /&gt;
	if wait == 0:&lt;br /&gt;
		return 0&lt;br /&gt;
	semwait.V();&lt;br /&gt;
	while (wait &amp;gt; 0) {}&lt;br /&gt;
	int val = sum&lt;br /&gt;
	mutex.P()&lt;br /&gt;
	sum = 0;&lt;br /&gt;
	mutex.V()&lt;br /&gt;
	return val;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
== 12 ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
semaphore mutex(0)&lt;br /&gt;
volatile int counter = 0&lt;br /&gt;
&lt;br /&gt;
void sumstop(int v):&lt;br /&gt;
	counter = counter + v;&lt;br /&gt;
	mutex.P()&lt;br /&gt;
&lt;br /&gt;
int sumgo(void):&lt;br /&gt;
	int val = counter;&lt;br /&gt;
	while (mutex.value != 0)&lt;br /&gt;
		mutex.V()&lt;br /&gt;
	counter = 0;&lt;br /&gt;
	return counter&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
== 13 == &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
semaphore mutex(1)&lt;br /&gt;
int sum = 0;&lt;br /&gt;
queue of semaphore q;&lt;br /&gt;
&lt;br /&gt;
void sumstop(int v):&lt;br /&gt;
	mutex.P()&lt;br /&gt;
	sum += v;&lt;br /&gt;
	s = new semaphore(0);&lt;br /&gt;
	q.enqueue(s)&lt;br /&gt;
	mutex.V()&lt;br /&gt;
	s.P()&lt;br /&gt;
	free(s)&lt;br /&gt;
&lt;br /&gt;
int sumgo(void):&lt;br /&gt;
	mutex.P()&lt;br /&gt;
	int lsum = sum&lt;br /&gt;
	sum = 0&lt;br /&gt;
	while (!q.empty()):&lt;br /&gt;
		semaphore s = q.dequeue()&lt;br /&gt;
		s.V()&lt;br /&gt;
	mutex.V()&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
== 14 ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
semaphore mutex(1)&lt;br /&gt;
int sum = 0;&lt;br /&gt;
queue of semaphore q;&lt;br /&gt;
&lt;br /&gt;
void sumstop(int v):&lt;br /&gt;
	mutex.P()&lt;br /&gt;
	sum += v;&lt;br /&gt;
	s = new semaphore(0);&lt;br /&gt;
	q.enqueue(s)&lt;br /&gt;
	mutex.V()&lt;br /&gt;
	s.P()&lt;br /&gt;
	free(s)&lt;br /&gt;
	if(q.empty())&lt;br /&gt;
		mutex.V()&lt;br /&gt;
	else&lt;br /&gt;
		semaphore s = q.dequeue()&lt;br /&gt;
		s.V()&lt;br /&gt;
&lt;br /&gt;
int sumgo(void):&lt;br /&gt;
	mutex.P()&lt;br /&gt;
	int lsum = sum&lt;br /&gt;
	sum = 0&lt;br /&gt;
	if(q.empty())&lt;br /&gt;
		mutex.V()&lt;br /&gt;
	else&lt;br /&gt;
		semaphore s = q.dequeue()&lt;br /&gt;
		s.V()&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 15 (soluzione proposta su telegram) ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
#include &amp;lt;pthread.h&amp;gt;&lt;br /&gt;
#include &amp;quot;semaphore.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
semaphore s; // semaforo che blocca le somme&lt;br /&gt;
semaphore finished; // semaforo che indica che le somme sono state fatte&lt;br /&gt;
semaphore critical_section; // sarà utilizzata per decidere chi entra nella critical section&lt;br /&gt;
&lt;br /&gt;
volatile int sumstops = 0;&lt;br /&gt;
volatile int result;&lt;br /&gt;
&lt;br /&gt;
void *sumstop(int v) {&lt;br /&gt;
    semaphore_P(critical_section);&lt;br /&gt;
    sumstops++;&lt;br /&gt;
    semaphore_V(critical_section);&lt;br /&gt;
&lt;br /&gt;
    semaphore_P(s);&lt;br /&gt;
    printf(&amp;quot;summed %d\n&amp;quot;, v);&lt;br /&gt;
    result += v;&lt;br /&gt;
    semaphore_V(finished);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int sumgo(void) {&lt;br /&gt;
    semaphore_P(critical_section); // così sumstops è costante all'interno di questa section&lt;br /&gt;
    result = 0;&lt;br /&gt;
    for (int i = 0; i &amp;lt; sumstops; i++) {&lt;br /&gt;
        semaphore_V(s); // permetti alla somma di andare&lt;br /&gt;
        semaphore_P(finished); // aspetta che la somma sia finita prima di continuare&lt;br /&gt;
    }&lt;br /&gt;
    sumstops = 0; // reset number of blocked stops.&lt;br /&gt;
    semaphore_V(critical_section);&lt;br /&gt;
    return result;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void *run_sumgo(void) {&lt;br /&gt;
    int res = sumgo();&lt;br /&gt;
    printf(&amp;quot;the result found is %d\n&amp;quot;, res);&lt;br /&gt;
    printf(&amp;quot;the result found is %d\n&amp;quot;, result);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
    srand(time(NULL));&lt;br /&gt;
    s = semaphore_create(0);&lt;br /&gt;
    critical_section = semaphore_create(1);&lt;br /&gt;
    finished = semaphore_create(0);&lt;br /&gt;
&lt;br /&gt;
    int n = rand() % 50;&lt;br /&gt;
    pthread_t sumg, s[n];&lt;br /&gt;
&lt;br /&gt;
    for (int i = 0; i &amp;lt; n; i++) {&lt;br /&gt;
        pthread_create(&amp;amp;s[i], NULL, sumstop, i);&lt;br /&gt;
    }&lt;br /&gt;
    pthread_create(&amp;amp;sumg, NULL, run_sumgo, NULL);&lt;br /&gt;
&lt;br /&gt;
    for (int i = 0; i &amp;lt; 10; i++) {&lt;br /&gt;
        pthread_join(s[i], NULL);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    pthread_join(sumg, NULL);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Correzioni proposte ==&lt;br /&gt;
&lt;br /&gt;
Correzione proposta da [https://t.me/flecarts flecart]&lt;br /&gt;
(e poi modificata successivamente da altri studenti ...&lt;br /&gt;
 tra cui: [https://t.me/LLibera] )&lt;br /&gt;
&lt;br /&gt;
1. la variabile i non è inizializzata, sum e queue non sono protette in critical sections, inoltre la sem.V() non compare mai nel codice della sumgo.&lt;br /&gt;
&lt;br /&gt;
2. la coda value non è in una critical section, può creare errori nell'update di essa, solo sum viene considerata da proteggere, ma devono essere protette entrambe. La enqueue avrebbe senso farla solo prima di bloccarsi nel semaforo, se viene fatta dopo al momento della chiamata di sumgo non ci sono valori all'interno della coda!&lt;br /&gt;
&lt;br /&gt;
3. sumgo libera solamente un singolo sumstop, perché chiama wait.V() una singola volta anche se ci sono più thread in attesa&lt;br /&gt;
&lt;br /&gt;
4. mutex.P() è chiamata due volte in sumstop(), se il secondo fosse mutex.V() credo sia corretto. &lt;br /&gt;
&lt;br /&gt;
5. mi sembra corretto (ma l'indentazione è poco sensata).&lt;br /&gt;
 &lt;br /&gt;
6. non si possono utilizzare suspend o resume (non si è fatto uso di semafori, e l'implementazione deve essere fatta all'esterno del kernel non all'interno). Oltre a questo pid non è inizializzata e sintpid non è utilizzata. Se anche la suspend fosse una sem.P() e la resume una sem.V() non dovremmo sospendere il processo all'interno della mutua esclusione.&lt;br /&gt;
 &lt;br /&gt;
7. nP e nV mi sembrano superflue, in questo caso sicuramente scorrette perché se chiamo m volte sumstop e una volta sumgo, nV è al massimo 1&lt;br /&gt;
quindi è impossibile che riesca a contare correttamente tutte le somme.&lt;br /&gt;
 &lt;br /&gt;
8. Deadlock perché bl.sem.P() è chiamato prima che ls Critical Section venga rilasciata e sumgo ha bisogno di entrare in una CS.&lt;br /&gt;
 &lt;br /&gt;
9. waiting è una variabile globale modificata senza cs, e tot non è inizializzato.&lt;br /&gt;
 &lt;br /&gt;
10. simile a 3. wait2go è chiamata una volta quindi può liberare solamente un singolo thread di sumstop.&lt;br /&gt;
&lt;br /&gt;
11. busy waiting in sumgo.&lt;br /&gt;
&lt;br /&gt;
12. counter non è protetto da Critical section &lt;br /&gt;
&lt;br /&gt;
13. se sumgo ritornasse il valore  lsum sarebbe tutto apposto.&lt;br /&gt;
&lt;br /&gt;
14. mi sembra corretto&lt;br /&gt;
&lt;br /&gt;
15. mi sembra corretto&lt;/div&gt;</summary>
		<author><name>LiberaL</name></author>
	</entry>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=20220906c2&amp;diff=2790</id>
		<title>20220906c2</title>
		<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php?title=20220906c2&amp;diff=2790"/>
		<updated>2022-10-19T23:03:14Z</updated>

		<summary type="html">&lt;p&gt;LiberaL: /* Correzioni aggiunte alle proposte */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;In questa pagina sono presenti alcune soluzioni (possibilmente con errore) per l'esercizio C2 dell'esame 2022/09/06.&lt;br /&gt;
Il lettore è invitato a immedesimare il professore al momento della correzione durante la lettura delle soluzioni.&lt;br /&gt;
&lt;br /&gt;
== Consegna ==&lt;br /&gt;
Usando i semafori implementare un servizio che preveda due funzioni:&lt;br /&gt;
   void sumstop(int v)&lt;br /&gt;
   int sumgo(void) &lt;br /&gt;
La funzione sumstop deve mettere il processo chiamante in attesa.&lt;br /&gt;
La funzione sumgo deve sbloccare tutti i processi messi in attesa con la sumstop e restituire la somma algebrica dei valori passati come parametro alla  sumstop dai processi che sono stati sbloccati (zero se la  sumgo viene richiamata quando non c'è nessun processo bloccato).&lt;br /&gt;
== 1 ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
semaphore sem(1);&lt;br /&gt;
int sum=0;&lt;br /&gt;
queue q;&lt;br /&gt;
&lt;br /&gt;
void sumstop(int v):&lt;br /&gt;
	if i &amp;lt; 0:&lt;br /&gt;
		q.enqueue(v)&lt;br /&gt;
		sem.P()&lt;br /&gt;
	else&lt;br /&gt;
		i--&lt;br /&gt;
&lt;br /&gt;
int sumgo(void):&lt;br /&gt;
	for each elem in q:&lt;br /&gt;
		int val=q.dequeue()&lt;br /&gt;
		sum=sum + val&lt;br /&gt;
	return sum&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
== 2 ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
queue values;&lt;br /&gt;
semaphore s(0);&lt;br /&gt;
int sum=0;&lt;br /&gt;
&lt;br /&gt;
void sumstop(int v):&lt;br /&gt;
	s.P()&lt;br /&gt;
	values.enqueue(v)&lt;br /&gt;
&lt;br /&gt;
int sumgo(void):&lt;br /&gt;
	while !value.isEmpty():&lt;br /&gt;
		s.V()&lt;br /&gt;
		mutex.P()&lt;br /&gt;
		sum=sum+values.dequeue()&lt;br /&gt;
		mutex.v()&lt;br /&gt;
	return sum&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
== 3 ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
shared int sum=0;&lt;br /&gt;
semaphore wait(0);&lt;br /&gt;
semaphore mutex(1);&lt;br /&gt;
&lt;br /&gt;
void sumstop(int v):&lt;br /&gt;
	mutex.P();&lt;br /&gt;
	sum = sum + v;&lt;br /&gt;
	mutex.V();&lt;br /&gt;
	wait.P();&lt;br /&gt;
&lt;br /&gt;
int sumgo(void):&lt;br /&gt;
	wait.V();&lt;br /&gt;
	somma = sum;&lt;br /&gt;
	mutex.P()&lt;br /&gt;
	sum = 0&lt;br /&gt;
	mutex.V()&lt;br /&gt;
	return somma;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
== 4 ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
queue&amp;lt;int&amp;gt; processlist;&lt;br /&gt;
semaphore mutex(1);&lt;br /&gt;
semaphore s(0);&lt;br /&gt;
&lt;br /&gt;
void sumstop(int v):&lt;br /&gt;
	mutex.P();&lt;br /&gt;
	processlist.enqueue(v);&lt;br /&gt;
	mutex.P();&lt;br /&gt;
	S.P();&lt;br /&gt;
&lt;br /&gt;
int sumgo(void):&lt;br /&gt;
	int sum = 0;&lt;br /&gt;
	mutex.P();&lt;br /&gt;
	while processlist.top() != NULL:&lt;br /&gt;
		sum += processlist.dequeue();&lt;br /&gt;
		S.V();&lt;br /&gt;
	mutex.V()&lt;br /&gt;
	return sum;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
== 5 ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
int counter = 0;&lt;br /&gt;
int sum = 0;&lt;br /&gt;
semaphore mutex(1);&lt;br /&gt;
semaphore blocked(0);&lt;br /&gt;
&lt;br /&gt;
void sumstop(int v):&lt;br /&gt;
	mutex.P();&lt;br /&gt;
	sum+=v;&lt;br /&gt;
	counter++;&lt;br /&gt;
	mutex.V();&lt;br /&gt;
	blocked.P();&lt;br /&gt;
&lt;br /&gt;
int sumgo(void):&lt;br /&gt;
	  mutex.P();&lt;br /&gt;
		intret = sum;&lt;br /&gt;
		sum = 0;&lt;br /&gt;
		for (int i=0; i&amp;lt;counter; i++)&lt;br /&gt;
			blocked.V()&lt;br /&gt;
		counter = 0;&lt;br /&gt;
		mutex.V()&lt;br /&gt;
	return intret&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
== 6 ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
int sum = 0;&lt;br /&gt;
mutex = new semaphore(1);&lt;br /&gt;
queue q;&lt;br /&gt;
&lt;br /&gt;
void sumstop(int v):&lt;br /&gt;
	mutex.P();&lt;br /&gt;
	sum += v;&lt;br /&gt;
	sintpid = getpid();&lt;br /&gt;
	suspend(pid);&lt;br /&gt;
	mutex.V();&lt;br /&gt;
&lt;br /&gt;
int sumgo(void):&lt;br /&gt;
	mutex.P();&lt;br /&gt;
	while !q.empty():&lt;br /&gt;
		resume(q.dequeue())&lt;br /&gt;
	int value = sum;&lt;br /&gt;
	sum = 0;&lt;br /&gt;
	return value;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
== 7 ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
int nP, nV = -1, 0;&lt;br /&gt;
int somma = 0&lt;br /&gt;
int val[]&lt;br /&gt;
semaphore mutex(1);&lt;br /&gt;
semaphore s(0);&lt;br /&gt;
&lt;br /&gt;
void sumstop(int v):&lt;br /&gt;
	mutex.P()&lt;br /&gt;
	val[nP++].add[v]&lt;br /&gt;
	s.P()&lt;br /&gt;
	np--&lt;br /&gt;
	v[0].delete&lt;br /&gt;
&lt;br /&gt;
int sumgo(void):&lt;br /&gt;
	mutex.P();&lt;br /&gt;
	nV++&lt;br /&gt;
	if nP &amp;gt; 0:&lt;br /&gt;
		s.V()&lt;br /&gt;
		for (int i=0; i&amp;lt;nV; i++)&lt;br /&gt;
			somma += val[i]&lt;br /&gt;
			nv--&lt;br /&gt;
	else&lt;br /&gt;
		mutex.V()&lt;br /&gt;
	return somma&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
== 8 ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
struct blocked {&lt;br /&gt;
	semaphore sem(0);&lt;br /&gt;
	int value = 0;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
semaphore mutex(1);&lt;br /&gt;
list&amp;lt;blocked&amp;gt; procs = new list&amp;lt;blocked&amp;gt;();&lt;br /&gt;
&lt;br /&gt;
void sumstop(int v):&lt;br /&gt;
	mutex.P()&lt;br /&gt;
	blocked bl = new blocked();&lt;br /&gt;
	bl.value = v&lt;br /&gt;
	procs.add(bl)&lt;br /&gt;
	bl.sem.P()&lt;br /&gt;
	mutex.V()&lt;br /&gt;
&lt;br /&gt;
int sumgo(void):&lt;br /&gt;
	mutex.P();&lt;br /&gt;
	int count = 0;&lt;br /&gt;
	foreach proc in procs:&lt;br /&gt;
		count += proc.value&lt;br /&gt;
		procs.remove(proc)&lt;br /&gt;
		proc.sem.V()&lt;br /&gt;
	mutex.V()&lt;br /&gt;
	return count;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
== 9 ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
semaphore s[] new sem(0)&lt;br /&gt;
semaphore s1 new sem(0)&lt;br /&gt;
int tot, waiting = 0;&lt;br /&gt;
&lt;br /&gt;
void sumstop(int v):&lt;br /&gt;
	waiting++&lt;br /&gt;
	s[waiting - 1].P()&lt;br /&gt;
	waiting--&lt;br /&gt;
	tot = tot + v&lt;br /&gt;
	if waiting == 0:&lt;br /&gt;
		s1.V()&lt;br /&gt;
&lt;br /&gt;
int sumgo(void):&lt;br /&gt;
	if waiting = 0:&lt;br /&gt;
		return 0&lt;br /&gt;
	for (i = waiting -1; i == 0; i--)&lt;br /&gt;
		s[i].V()&lt;br /&gt;
	s1.P() // per aspettare che tutti abbiano fatto la somma&lt;br /&gt;
	return tot&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 10 ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
int nw = 0&lt;br /&gt;
int currsum = 0&lt;br /&gt;
semaphore mutex(1)&lt;br /&gt;
semaphore wait2go(0)&lt;br /&gt;
&lt;br /&gt;
void sumstop(int v):&lt;br /&gt;
	mutex.P()&lt;br /&gt;
	currsum += v;&lt;br /&gt;
	nw++;&lt;br /&gt;
	mutex.V()&lt;br /&gt;
	wait2go.P()&lt;br /&gt;
	if --nw &amp;gt; 0:&lt;br /&gt;
		wait2go.V()&lt;br /&gt;
	else&lt;br /&gt;
		mutex.V()&lt;br /&gt;
&lt;br /&gt;
int sumgo(void):&lt;br /&gt;
	mutex.P();&lt;br /&gt;
	if nw == 0:&lt;br /&gt;
		mutex.V()&lt;br /&gt;
		return 0;&lt;br /&gt;
	int sum = cursum;&lt;br /&gt;
	cursum = 0;&lt;br /&gt;
	wait2go.V();&lt;br /&gt;
	return sum&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
== 11==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
semaphore mutex(1);&lt;br /&gt;
semaphore semwait(0);&lt;br /&gt;
int sum=0;&lt;br /&gt;
int wait=0;&lt;br /&gt;
&lt;br /&gt;
void sumstop(int v):&lt;br /&gt;
	mutex.P()&lt;br /&gt;
	wait++&lt;br /&gt;
	sum += v;&lt;br /&gt;
	mutex.V()&lt;br /&gt;
	semwait.P()&lt;br /&gt;
	mutex.P()&lt;br /&gt;
	wait--;&lt;br /&gt;
	mutex.V()&lt;br /&gt;
	if wait &amp;gt; 0:&lt;br /&gt;
		semwait.V()&lt;br /&gt;
&lt;br /&gt;
int sumgo(void):&lt;br /&gt;
	if wait == 0:&lt;br /&gt;
		return 0&lt;br /&gt;
	semwait.V();&lt;br /&gt;
	while (wait &amp;gt; 0) {}&lt;br /&gt;
	int val = sum&lt;br /&gt;
	mutex.P()&lt;br /&gt;
	sum = 0;&lt;br /&gt;
	mutex.V()&lt;br /&gt;
	return val;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
== 12 ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
semaphore mutex(0)&lt;br /&gt;
volatile int counter = 0&lt;br /&gt;
&lt;br /&gt;
void sumstop(int v):&lt;br /&gt;
	counter = counter + v;&lt;br /&gt;
	mutex.P()&lt;br /&gt;
&lt;br /&gt;
int sumgo(void):&lt;br /&gt;
	int val = counter;&lt;br /&gt;
	while (mutex.value != 0)&lt;br /&gt;
		mutex.V()&lt;br /&gt;
	counter = 0;&lt;br /&gt;
	return counter&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
== 13 == &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
semaphore mutex(1)&lt;br /&gt;
int sum = 0;&lt;br /&gt;
queue of semaphore q;&lt;br /&gt;
&lt;br /&gt;
void sumstop(int v):&lt;br /&gt;
	mutex.P()&lt;br /&gt;
	sum += v;&lt;br /&gt;
	s = new semaphore(0);&lt;br /&gt;
	q.enqueue(s)&lt;br /&gt;
	mutex.V()&lt;br /&gt;
	s.P()&lt;br /&gt;
	free(s)&lt;br /&gt;
&lt;br /&gt;
int sumgo(void):&lt;br /&gt;
	mutex.P()&lt;br /&gt;
	int lsum = sum&lt;br /&gt;
	sum = 0&lt;br /&gt;
	while (!q.empty()):&lt;br /&gt;
		semaphore s = q.dequeue()&lt;br /&gt;
		s.V()&lt;br /&gt;
	mutex.V()&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
== 14 ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
semaphore mutex(1)&lt;br /&gt;
int sum = 0;&lt;br /&gt;
queue of semaphore q;&lt;br /&gt;
&lt;br /&gt;
void sumstop(int v):&lt;br /&gt;
	mutex.P()&lt;br /&gt;
	sum += v;&lt;br /&gt;
	s = new semaphore(0);&lt;br /&gt;
	q.enqueue(s)&lt;br /&gt;
	mutex.V()&lt;br /&gt;
	s.P()&lt;br /&gt;
	free(s)&lt;br /&gt;
	if(q.empty())&lt;br /&gt;
		mutex.V()&lt;br /&gt;
	else&lt;br /&gt;
		semaphore s = q.dequeue()&lt;br /&gt;
		s.V()&lt;br /&gt;
&lt;br /&gt;
int sumgo(void):&lt;br /&gt;
	mutex.P()&lt;br /&gt;
	int lsum = sum&lt;br /&gt;
	sum = 0&lt;br /&gt;
	if(q.empty())&lt;br /&gt;
		mutex.V()&lt;br /&gt;
	else&lt;br /&gt;
		semaphore s = q.dequeue()&lt;br /&gt;
		s.V()&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== 15 (soluzione proposta su telegram) ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
#include &amp;lt;pthread.h&amp;gt;&lt;br /&gt;
#include &amp;quot;semaphore.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
semaphore s; // semaforo che blocca le somme&lt;br /&gt;
semaphore finished; // semaforo che indica che le somme sono state fatte&lt;br /&gt;
semaphore critical_section; // sarà utilizzata per decidere chi entra nella critical section&lt;br /&gt;
&lt;br /&gt;
volatile int sumstops = 0;&lt;br /&gt;
volatile int result;&lt;br /&gt;
&lt;br /&gt;
void *sumstop(int v) {&lt;br /&gt;
    semaphore_P(critical_section);&lt;br /&gt;
    sumstops++;&lt;br /&gt;
    semaphore_V(critical_section);&lt;br /&gt;
&lt;br /&gt;
    semaphore_P(s);&lt;br /&gt;
    printf(&amp;quot;summed %d\n&amp;quot;, v);&lt;br /&gt;
    result += v;&lt;br /&gt;
    semaphore_V(finished);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int sumgo(void) {&lt;br /&gt;
    semaphore_P(critical_section); // così sumstops è costante all'interno di questa section&lt;br /&gt;
    result = 0;&lt;br /&gt;
    for (int i = 0; i &amp;lt; sumstops; i++) {&lt;br /&gt;
        semaphore_V(s); // permetti alla somma di andare&lt;br /&gt;
        semaphore_P(finished); // aspetta che la somma sia finita prima di continuare&lt;br /&gt;
    }&lt;br /&gt;
    sumstops = 0; // reset number of blocked stops.&lt;br /&gt;
    semaphore_V(critical_section);&lt;br /&gt;
    return result;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void *run_sumgo(void) {&lt;br /&gt;
    int res = sumgo();&lt;br /&gt;
    printf(&amp;quot;the result found is %d\n&amp;quot;, res);&lt;br /&gt;
    printf(&amp;quot;the result found is %d\n&amp;quot;, result);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
    srand(time(NULL));&lt;br /&gt;
    s = semaphore_create(0);&lt;br /&gt;
    critical_section = semaphore_create(1);&lt;br /&gt;
    finished = semaphore_create(0);&lt;br /&gt;
&lt;br /&gt;
    int n = rand() % 50;&lt;br /&gt;
    pthread_t sumg, s[n];&lt;br /&gt;
&lt;br /&gt;
    for (int i = 0; i &amp;lt; n; i++) {&lt;br /&gt;
        pthread_create(&amp;amp;s[i], NULL, sumstop, i);&lt;br /&gt;
    }&lt;br /&gt;
    pthread_create(&amp;amp;sumg, NULL, run_sumgo, NULL);&lt;br /&gt;
&lt;br /&gt;
    for (int i = 0; i &amp;lt; 10; i++) {&lt;br /&gt;
        pthread_join(s[i], NULL);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    pthread_join(sumg, NULL);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Correzioni proposte ==&lt;br /&gt;
&lt;br /&gt;
Correzione proposta da [https://t.me/flecarts flecart] (e poi modificata successivamente da altri studenti ...)&lt;br /&gt;
&lt;br /&gt;
1. la variabile i non è inizializzata, sum e queue non sono protette in critical sections, inoltre la sem.V() non compare mai nel codice della sumgo.&lt;br /&gt;
&lt;br /&gt;
2. la coda value non è in una critical section, può creare errori nell'update di essa, solo sum viene considerata da proteggere, ma devono essere protette entrambe. La enqueue avrebbe senso farla solo prima di bloccarsi nel semaforo, se viene fatta dopo al momento della chiamata di sumgo non ci sono valori all'interno della coda!&lt;br /&gt;
&lt;br /&gt;
3. sumgo libera solamente un singolo sumstop, perché chiama wait.V() una singola volta anche se ci sono più thread in attesa&lt;br /&gt;
&lt;br /&gt;
4. mutex.P() è chiamata due volte in sumstop(), se il secondo fosse mutex.V() credo sia corretto. &lt;br /&gt;
&lt;br /&gt;
5. mi sembra corretto (ma l'indentazione è poco sensata).&lt;br /&gt;
 &lt;br /&gt;
6. non si possono utilizzare suspend o resume (non si è fatto uso di semafori, e l'implementazione deve essere fatta all'esterno del kernel non all'interno). Oltre a questo pid non è inizializzata e sintpid non è utilizzata. Se anche la suspend fosse una sem.P() e la resume una sem.V() non dovremmo sospendere il processo all'interno della mutua esclusione.&lt;br /&gt;
 &lt;br /&gt;
7. nP e nV mi sembrano superflue, in questo caso sicuramente scorrette perché se chiamo m volte sumstop e una volta sumgo, nV è al massimo 1&lt;br /&gt;
quindi è impossibile che riesca a contare correttamente tutte le somme.&lt;br /&gt;
 &lt;br /&gt;
8. Deadlock perché bl.sem.P() è chiamato prima che ls Critical Section venga rilasciata e sumgo ha bisogno di entrare in una CS.&lt;br /&gt;
 &lt;br /&gt;
9. waiting è una variabile globale modificata senza cs, e tot non è inizializzato.&lt;br /&gt;
 &lt;br /&gt;
10. simile a 3. wait2go è chiamata una volta quindi può liberare solamente un singolo thread si sumstop.&lt;br /&gt;
&lt;br /&gt;
11. busy waiting in sumgo.&lt;br /&gt;
&lt;br /&gt;
12. counter non è protetto da Critical section &lt;br /&gt;
&lt;br /&gt;
13. se sumgo ritornasse il valore  lsum sarebbe tutto apposto.&lt;br /&gt;
&lt;br /&gt;
14. mi sembra corretto&lt;br /&gt;
&lt;br /&gt;
15. mi sembra corretto&lt;/div&gt;</summary>
		<author><name>LiberaL</name></author>
	</entry>
</feed>