<?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=Gio</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=Gio"/>
	<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php/Special:Contributions/Gio"/>
	<updated>2026-04-30T16:51:14Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.35.5</generator>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=Prove_scritte_2017&amp;diff=2930</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=2930"/>
		<updated>2023-01-18T10:52:57Z</updated>

		<summary type="html">&lt;p&gt;Gio: /* Soluzione proposta 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;
&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, msg_type msg){&lt;br /&gt;
    bsend (&amp;lt;pid_t dst, msg&amp;gt;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
arecv(*){&lt;br /&gt;
  pid_t act = getpid(); \\ act = proprio pid &lt;br /&gt;
  do{&lt;br /&gt;
    &amp;lt;dst, msg&amp;gt; = brecv(*);&lt;br /&gt;
  }while (dst =! act)&lt;br /&gt;
  return msg;&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;
== 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;
&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>Gio</name></author>
	</entry>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=Prove_scritte_2017&amp;diff=2929</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=2929"/>
		<updated>2023-01-18T10:52:04Z</updated>

		<summary type="html">&lt;p&gt;Gio: /* Soluzione proposta 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 (da controllare) ====&lt;br /&gt;
Soluzione proposta da [https://so.v2.cs.unibo.it/wiki/index.php/User:Flecart Flecart]&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;
&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, msg_type msg){&lt;br /&gt;
    bsend (&amp;lt;pid_t dst, msg&amp;gt;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
arecv(*){&lt;br /&gt;
  pid_t act = getpid(); \\ act = proprio pid &lt;br /&gt;
  do{&lt;br /&gt;
    &amp;lt;dst, msg&amp;gt; = brecv(*);&lt;br /&gt;
  }while (dst =! act)&lt;br /&gt;
  return msg;&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;
== 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;
&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>Gio</name></author>
	</entry>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=Prove_scritte_2018&amp;diff=2928</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=2928"/>
		<updated>2023-01-18T10:39:24Z</updated>

		<summary type="html">&lt;p&gt;Gio: /* Esercizio c.2 (ERRATO) */&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;
&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)  {&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>Gio</name></author>
	</entry>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=Prove_scritte_2019&amp;diff=2924</id>
		<title>Prove scritte 2019</title>
		<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php?title=Prove_scritte_2019&amp;diff=2924"/>
		<updated>2023-01-17T16:09:27Z</updated>

		<summary type="html">&lt;p&gt;Gio: /* Esercizio c2 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Esame 18/06/2019 ==&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2019.06.18.tot.pdf 2019.06.18.tot.pdf]&lt;br /&gt;
=== Esercizio c.1 (da controllare) ===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
monitor pg{&lt;br /&gt;
&lt;br /&gt;
  int waitingReader = 0;&lt;br /&gt;
  int waitingWriter = 0;&lt;br /&gt;
&lt;br /&gt;
  condition ok2write;&lt;br /&gt;
  condition ok2read;&lt;br /&gt;
&lt;br /&gt;
  T datobuf;&lt;br /&gt;
&lt;br /&gt;
  entry put (T dato) {&lt;br /&gt;
&lt;br /&gt;
    if (waitingReader &amp;gt; 0)&lt;br /&gt;
      datobuf = dato;&lt;br /&gt;
      while (waitingReader &amp;gt; 0)&lt;br /&gt;
        ok2read.signal();&lt;br /&gt;
    else if (waitingWriter &amp;gt;= 0)&lt;br /&gt;
      waitingWriter++;&lt;br /&gt;
      ok2write.wait();&lt;br /&gt;
      waitingWriter--;&lt;br /&gt;
      datobuf = dato;&lt;br /&gt;
&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  entry T get (void) {&lt;br /&gt;
&lt;br /&gt;
    if (waitingReader &amp;gt; 0 || waitingWriter == 0)&lt;br /&gt;
      waitingReader++;&lt;br /&gt;
      ok2read.wait();&lt;br /&gt;
      waitingReader--;&lt;br /&gt;
    else if (waitingWriter &amp;gt; 0) &lt;br /&gt;
      ok2write.signal();&lt;br /&gt;
      return datobuf;&lt;br /&gt;
    &lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&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;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
monitor taon {&lt;br /&gt;
condition ok2w, ok2r;&lt;br /&gt;
int nw, nr = 0;&lt;br /&gt;
T buf;&lt;br /&gt;
&lt;br /&gt;
entry  void put (T dato){&lt;br /&gt;
	nw++;&lt;br /&gt;
	if( nw != 1 || nr == 0)&lt;br /&gt;
             ok2w.wait();&lt;br /&gt;
	buf = dato;&lt;br /&gt;
	for (i=0, i++, i &amp;lt; nr)&lt;br /&gt;
	     ok2r.signal();&lt;br /&gt;
	nw--;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
entry T get(){&lt;br /&gt;
	nr++;&lt;br /&gt;
	if(nw==0)&lt;br /&gt;
	    ok2r.wait();&lt;br /&gt;
	ok2w.signal();&lt;br /&gt;
	T dato = buf;&lt;br /&gt;
	nr --;&lt;br /&gt;
	return dato;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.2 ===&lt;br /&gt;
**non è l'esercizio corretto**&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
/* MP sincrono dato quello asincrono */&lt;br /&gt;
&lt;br /&gt;
void ssend(obj msg, process q)&lt;br /&gt;
{&lt;br /&gt;
    asend(msg, q);&lt;br /&gt;
    ack = areceive(q);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
obj sreceive(process p)&lt;br /&gt;
{&lt;br /&gt;
    obj msg = areceive(p);&lt;br /&gt;
    asend(ack, p);&lt;br /&gt;
    return msg;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Soluzione:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
dati asend/arecv devo implementare lssend lsrecv&lt;br /&gt;
&lt;br /&gt;
lssend(dst, msg):&lt;br /&gt;
    asend(dst, (MSG, myid(), msg))&lt;br /&gt;
    arecv(dst)&lt;br /&gt;
&lt;br /&gt;
lsrecv(snd):&lt;br /&gt;
    asend(myid(), (TAG, myid(), NULL))    // mi mando un messaggio che riesco a riconoscere&lt;br /&gt;
    while True:&lt;br /&gt;
        (T, s, m) =  arecv(ANY)           // continua a ricevere finchè non ricevi il mio messaggio&lt;br /&gt;
        if (T != TAG) data.push(s, m)&lt;br /&gt;
        else break&lt;br /&gt;
    while (((s,m) = data.pop(snd) == NULL):   // c'è il messaggio di src definito?&lt;br /&gt;
        (T, s, m) =  arecv(ANY)&lt;br /&gt;
        data.push(s, m)&lt;br /&gt;
    asend(s, (ACK, myid(), NULL)&lt;br /&gt;
    return m&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Esercizio g.1 (sbagliato) ===&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
x = long_compute()/short_compute()&lt;br /&gt;
X = io()&lt;br /&gt;
&lt;br /&gt;
   0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3 3 3 3 3 3 3 3 3 4 4 4 4 4 4 4 4 4 4 5 5 5 5 5 5 5 5 5 5 6 6 6 6 6 6 6 6 6 6 7 7 7 7 7 7 7 7 7 7 8 8 8&lt;br /&gt;
   0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2&lt;br /&gt;
P1 |x|x|x|x|x|X|-|-|-|-|-|-|X|X|X|-|-|-|-|-|-|X|x|x|-|-|-|-|-|-|x|x|x|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|X|X|X|-|-|-|-|-|-|X|X|x|-|-|-|-|-|-|x|-|-|&lt;br /&gt;
P2         |-|-|x|x|x|-|-|-|-|-|-|x|x|-|-|-|-|-|-|-|X|X|X|-|-|-|-|-|-|X|X|x|-|-|-|-|-|-|x|x|x|-|-|-|-|-|-|x|-|-|-|-|-|-|-|-|X|X|X|-|-|-|-|-|-|X|X|x|-|-|-|x|-|-|&lt;br /&gt;
P3               |-|-|x|x|x|-|-|-|-|-|-|x|x|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|X|X|X|-|-|-|-|-|-|X|X|x|-|-|-|-|-|-|x|x|x|-|-|-|-|-|-|x|-|-|-|-|-|-|-|-|X|X|X|-|-|-|X|X|x|x|&lt;br /&gt;
 &amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Esercizio g.1 ===&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
P1(start=0): 5ms CPU, 5ms IO, 5ms CPU, 5ms IO, 2ms CPU&lt;br /&gt;
P2(start=4): 5ms CPU, 5ms IO, 5ms CPU, 5ms IO, 2ms CPU&lt;br /&gt;
P3(start=7): 5ms CPU, 5ms IO, 5ms CPU, 5ms IO, 2ms CPU&lt;br /&gt;
&lt;br /&gt;
 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3 3 3 3 3 3 3 3 3 4 4 4 4 4 4 4 4 4 4 5 &lt;br /&gt;
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 &lt;br /&gt;
P|1 1 1|1 1|2 2 2|3 3 3|2 2|1 1 1|3 3|1 1|2 2 2*3 3 3|2 2|3 3|1 1|-|2 2|- - -|3 3|&lt;br /&gt;
I          |1 1 1 1 1|     |2 2 2 2 2|3 3 3 3 3|1 1 1 1 1|2 2 2 2 2|3 3 3 3 3|&lt;br /&gt;
&lt;br /&gt;
r - - - - 2 - - 3 2 2 2 1 1 3 3 3 1 1 2 2 - - - 2 2 2 3 3 1 1&lt;br /&gt;
                      1 3 3&lt;br /&gt;
&lt;br /&gt;
* 3 ha finito input output e 2 è ancora in esecuzione quindi c'è da scegliere&lt;br /&gt;
 &amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Esercizio g.2 (da controllare) ===&lt;br /&gt;
# Può richiedere supporto hardware. Se implementato con contatori o stack questi devono essere aggiornati ad ogni riferimento alla memoria. L'intero sistema viene appesantito e rallentato.&lt;br /&gt;
# Il journaling si assicura che i dati sul filesystem siano consistenti, ma non aggiornati. Assicura la coerenza dei dati, ma non la perdita dei file se il filesystem si danneggia.&lt;br /&gt;
# Si dice che un programma A ha lo stesso potere espressivo di un programma B quando è possibile esprimere ogni programma scritto con B mediante A. Per implementare MP sincrono dato quello asincrono basta aggiungere una libreria. Per implementare MP asincrono dato quello sincrono bisogna aggiungere un processo server.&lt;br /&gt;
# In questi casi tutte le istruzioni vengono eseguite con la massima autorità, con problemi di sicurezza nel caso un utente estraneo prenda il controllo del sistema o rischio di commettere gravi errori semplicemente sbagliando a digitare un comando.&lt;br /&gt;
&lt;br /&gt;
== Esame 18/05/2019 ==&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2019.05.18.tot.pdf 2019.05.18.tot.pdf]&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.1 (da controllare) ===&lt;br /&gt;
&lt;br /&gt;
* Controllato dall'utente ? in data ?&lt;br /&gt;
* ...&lt;br /&gt;
&lt;br /&gt;
Il sorgente seguente può essere eseguito scaricando in una stessa directory il package [[Tool per semafori e monitor|pysm]] del prof. Davoli.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
#!/usr/bin/env python3&lt;br /&gt;
&lt;br /&gt;
import threading&lt;br /&gt;
&lt;br /&gt;
from array import array&lt;br /&gt;
from pysm.monitor import condition, entry, monitor&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class storage(monitor):&lt;br /&gt;
    ELEMS = 16&lt;br /&gt;
&lt;br /&gt;
    def __init__(self):&lt;br /&gt;
        &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
        Implementazione che permette l'avanzamento degli operai in presenza di&lt;br /&gt;
        altri operai in attesa.&lt;br /&gt;
        &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
        monitor.__init__(self)&lt;br /&gt;
        self._v = array('L', self.ELEMS * [0])&lt;br /&gt;
        self._c = tuple(condition(self) for i in self._v)&lt;br /&gt;
        # self._requests[i] = [l1, l2, ..., ln] se per l'attrezzo i ci sono in&lt;br /&gt;
        # attesa n processi che richiedono ciascuno l1, l2, ..., ln unita'&lt;br /&gt;
        self._requests = {i: list() for i in range(self.ELEMS)}&lt;br /&gt;
&lt;br /&gt;
    @entry&lt;br /&gt;
    def add(self, components):&lt;br /&gt;
        if len(components) != self.ELEMS:&lt;br /&gt;
            raise ValueError(&amp;quot;components must contain exactly ELEMS elements&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
        for i, c in enumerate(components):&lt;br /&gt;
            self._v[i] += c&lt;br /&gt;
&lt;br /&gt;
            # Finche' per il componente i ci sono richieste in sospeso che&lt;br /&gt;
            # possono essere soddisfatte, svegliamo il processo in attesa, che&lt;br /&gt;
            # proseguira' col richiedere i componenti successivi&lt;br /&gt;
            while self._requests[i] and self._requests[i][0] &amp;lt;= self._v[i]:&lt;br /&gt;
                self._c[i].signal()&lt;br /&gt;
&lt;br /&gt;
    @entry&lt;br /&gt;
    def get(self, components):&lt;br /&gt;
        if len(components) != self.ELEMS:&lt;br /&gt;
            raise ValueError(&amp;quot;components must contain exactly ELEMS elements&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
        for i in range(len(components)):&lt;br /&gt;
            if components[i] &amp;lt;= self._v[i]:&lt;br /&gt;
                self._v[i] -= components[i]&lt;br /&gt;
            else:&lt;br /&gt;
                components[i] -= self._v[i]&lt;br /&gt;
                self._v[i] = 0&lt;br /&gt;
&lt;br /&gt;
                self._requests[i].append(components[i])&lt;br /&gt;
                self._c[i].wait()&lt;br /&gt;
&lt;br /&gt;
                self._v[i] -= components[i]&lt;br /&gt;
                self._requests[i].pop(0)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def request(m, q):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    Funzione processo che simula la richiesta di un operaio.&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    name = threading.current_thread().name&lt;br /&gt;
&lt;br /&gt;
    print(&amp;quot;[%s] Requesting %s&amp;quot; % (name, q))&lt;br /&gt;
    m.get(q)&lt;br /&gt;
    print(&amp;quot;[%s] Done requesting&amp;quot; % (name))&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def supply(m, s):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    Funzione processo che simula il rifornimento di un magazziniere.&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    name = threading.current_thread().name&lt;br /&gt;
&lt;br /&gt;
    print(&amp;quot;[%s] Supplying %s&amp;quot; % (name, s))&lt;br /&gt;
    m.add(s)&lt;br /&gt;
    print(&amp;quot;[%s] Done supplying&amp;quot; % (name))&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    m = storage()&lt;br /&gt;
    requests = [&lt;br /&gt;
        threading.Thread(name='req1', target=request, args=(m, [4, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])),&lt;br /&gt;
        threading.Thread(name='req2', target=request, args=(m, [0, 0, 2, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])),&lt;br /&gt;
        threading.Thread(name='req3', target=request, args=(m, [4, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])),&lt;br /&gt;
        threading.Thread(name='req4', target=request, args=(m, [4, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])),&lt;br /&gt;
        threading.Thread(name='req5', target=request, args=(m, [4, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])),&lt;br /&gt;
    ]&lt;br /&gt;
    supplies = [&lt;br /&gt;
        threading.Thread(name='supply1', target=supply, args=(m, [4, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])),&lt;br /&gt;
        threading.Thread(name='supply2', target=supply, args=(m, [4, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])),&lt;br /&gt;
        threading.Thread(name='supply3', target=supply, args=(m, [4, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])),&lt;br /&gt;
        threading.Thread(name='supply4', target=supply, args=(m, [4, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])),&lt;br /&gt;
        threading.Thread(name='supply5', target=supply, args=(m, [0, 0, 2, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])),&lt;br /&gt;
    ]&lt;br /&gt;
&lt;br /&gt;
    for t in requests + supplies:&lt;br /&gt;
        t.daemon = True&lt;br /&gt;
        t.start()&lt;br /&gt;
    &lt;br /&gt;
    for t in requests + supplies:&lt;br /&gt;
        t.join()&lt;br /&gt;
&lt;br /&gt;
    return 0&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    exit(main())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.2 (da controllare) ===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
unsigned procs_in = 0;&lt;br /&gt;
semaphore mutex = new binary_semaphore(1);&lt;br /&gt;
queue&amp;lt;semaphore&amp;gt; semaphores = new queue&amp;lt;&amp;gt;();&lt;br /&gt;
&lt;br /&gt;
sau_enter () {&lt;br /&gt;
	mutex.P();&lt;br /&gt;
	procs_in++;&lt;br /&gt;
	mutex.V();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
sau_exit () {&lt;br /&gt;
	mutex.P();&lt;br /&gt;
	procs_in--;&lt;br /&gt;
&lt;br /&gt;
	if (procs_in &amp;gt; 0) {&lt;br /&gt;
		semaphore s = new semaphore(0);&lt;br /&gt;
&lt;br /&gt;
		semaphores.enqueue(s);&lt;br /&gt;
		mutex.V();&lt;br /&gt;
		s.P();&lt;br /&gt;
	} else {&lt;br /&gt;
		while (!sempahores.empty())&lt;br /&gt;
			semaphores.dequeue().V();&lt;br /&gt;
&lt;br /&gt;
		mutex.V();&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Esercizio g.1 (da controllare) ===&lt;br /&gt;
==== Domanda a) ====&lt;br /&gt;
Poiché lo scheduler è non-preemptive, una volta assegnata la CPU ad un dato processo, questi non viene cambiato finché non ha terminato. Visto il vincolo nel testo della consegna, una volta concluso il processo corrente si hanno solo due scelte: selezionare il più recente processo A o il più recente processo B.&lt;br /&gt;
&lt;br /&gt;
Nuovi processi A partono ogni 6ms, nuovi processi B ogni 8ms; gli intervalli di tempo in cui partono sia processi A sia processi B sono multipli di mcm(6, 8) ms = 24ms: cioè ai tempi 0ms, 24ms, 48ms, 72ms, ..., parte sia un processo A sia un processo B.&lt;br /&gt;
&lt;br /&gt;
In ognuno di questi intervalli di 24ms, si susseguono sia processi A sia processi B. I processi A sono 24ms / 6ms = 4, i processi B 24ms / 8ms = 3; i primi richiedono 4 * 3ms = 12ms, i secondi 3 * 4ms = 12ms. È possibile dimostrare induttivamente che ad ogni nuovo intervallo di 24ms, i processi di quello precedente sono stati tutti svolti e che quelli correnti saranno terminati entro 24ms (infatti ad ogni 24ms, è un po' come se le condizioni iniziali venissero ristabilite). Pertanto è possibile eseguire entrambi i processi senza portare a starvation.&lt;br /&gt;
&lt;br /&gt;
==== Domanda b) ====&lt;br /&gt;
Ragionamento analogo al punto precedente, con alcune differenze date dalle permutazioni in cui certi processi vengono schedulati.&lt;br /&gt;
&lt;br /&gt;
==== Domanda c) ====&lt;br /&gt;
Per definizione, uno scheudler round-robin garantisce possibilità di esecuzione a tutti i processi, pertanto è possibile. La figura mostra un intervallamento di scheduling secondo criterio RR che evidenzia come sia possibile completare tutti i processi entro i 24ms.&lt;br /&gt;
&lt;br /&gt;
[[File:Epson 25082020151034.jpg]]&lt;br /&gt;
&lt;br /&gt;
=== Esercizio g.2 (da controllare) ===&lt;br /&gt;
&lt;br /&gt;
# Basso, perché vengono generate molte page trap. Così facendo i processi direttamente interessati devono attendere il caricamento delle pagine di memoria ed essere posti in attesa, riducendo l'utilizzazione della CPU.&lt;br /&gt;
# Sì, ad esempio il MBR (Master Boot Record) e l'area di swap. Il MBR contiene meta-informazioni sul disco stesso e non è adatto a contenere informazioni concrete, mentre l'area di swap può essere considerata un'estensione della memoria centrale del calcolatore.&lt;br /&gt;
# Flessibile, perché se intendo riconfigurare alcuni parametri del sistema non occorre ricompilare il kernel, ma solamente riscrivere/riconfigurare e rilanciare il programma che si fa carico del servizio in questione; affidabile, in quanto i servizi di sistema sono realizzati tramite processi a livello utente, e un loro crash non si ripercuote sull'intero sistema; meno efficiente (di un kernel monolitico) in quanto i vari servizi comunicano con il kernel non tramite chiamate di sistema, ma un vero e proprio servizio di message passing tra processi, che aggiunge overhead.&lt;br /&gt;
# Come voci di una directory che puntano allo stesso inode (laddove il file system sia basato su inode) o più in generale allo stesso FCB (File Control Block). Per determinare se un dato FCB non è più linkato da nessuna voce (entry) si utilizza un contatore che rappresenta il numero corrente di riferimenti; quando questo diventa 0, il FCB può essere eliminato dal file system.&lt;br /&gt;
&lt;br /&gt;
== Esame 14/02/2019 ==&lt;br /&gt;
[https://www.cs.unibo.it/~renzo/so/compiti/2019.02.14.tot.pdf Testo d'esame].&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.1 (da controllare) ===&lt;br /&gt;
&lt;br /&gt;
* Controllato dall'utente [[User:Acsor|Acsor]] ([[User talk:Acsor|talk]]) in data 16:03, 2 September 2020 (CEST). Ritengo sia: corretto&lt;br /&gt;
* Controllato dall'utente ? in data ?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
# Original authors: Mattia Guazzaloca, Paolo Marzolo&lt;br /&gt;
#&lt;br /&gt;
# Contributors: utente Acsor&lt;br /&gt;
&lt;br /&gt;
class monobinarysem(monitor):&lt;br /&gt;
    def __init__(self, val):&lt;br /&gt;
        monitor.__init__(self)&lt;br /&gt;
        self.iszero = condition(self)&lt;br /&gt;
        self.val = val&lt;br /&gt;
        &lt;br /&gt;
    @entry&lt;br /&gt;
    def monoP(self):&lt;br /&gt;
        if self.val == 0:&lt;br /&gt;
            self.iszero.wait()&lt;br /&gt;
        &lt;br /&gt;
        self.val -= 1&lt;br /&gt;
        &lt;br /&gt;
    @entry&lt;br /&gt;
    def monoV(self):&lt;br /&gt;
        if self.val == 0:&lt;br /&gt;
            self.val += 1&lt;br /&gt;
            self.iszero.signal()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.2 (controllato) ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
# Original author: Renzo Davoli (durante la lezione)&lt;br /&gt;
#&lt;br /&gt;
# Contributors:&lt;br /&gt;
&lt;br /&gt;
def pssend(message, destination):&lt;br /&gt;
    asend((self(),message),destination)&lt;br /&gt;
&lt;br /&gt;
    while(1):&lt;br /&gt;
        snd, message = arecv(ANY)&lt;br /&gt;
&lt;br /&gt;
        if (message == ACK):&lt;br /&gt;
            break&lt;br /&gt;
&lt;br /&gt;
        datastruct.add(snd, message)&lt;br /&gt;
   &lt;br /&gt;
&lt;br /&gt;
def psreceive(sender):&lt;br /&gt;
    dummy = Message(null)&lt;br /&gt;
    asend(self(), dummy) # self is my id&lt;br /&gt;
    &lt;br /&gt;
    while(1):&lt;br /&gt;
        snd, message = arecv(ANY)&lt;br /&gt;
&lt;br /&gt;
        if (message == dummy):&lt;br /&gt;
            break&lt;br /&gt;
&lt;br /&gt;
        datastruct.add(snd, message)&lt;br /&gt;
        &lt;br /&gt;
    if (datastruct.match(sender)):&lt;br /&gt;
        src, msg = datastruct.get(sender)&lt;br /&gt;
        asend((self(),ACK), src)&lt;br /&gt;
&lt;br /&gt;
        return msg&lt;br /&gt;
    else:&lt;br /&gt;
        return None&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Esame 28/05/2019 ==&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2019.05.18.tot.pdf 2019.05.18.tot.pdf]&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.1 (da controllare) ===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
monitor storage:&lt;br /&gt;
   &lt;br /&gt;
    [16] int vector&lt;br /&gt;
    [16] condition ok2get&lt;br /&gt;
    [16] bool available = { 1, ..., 1 }&lt;br /&gt;
   &lt;br /&gt;
    entry get([16] int components):&lt;br /&gt;
        for (i from 0 to 15):&lt;br /&gt;
            while ((components[i] &amp;gt; vector[i]) || !available[i]):&lt;br /&gt;
                if (available[i]):&lt;br /&gt;
                    available[i] = false&lt;br /&gt;
                ok2get[i].wait()&lt;br /&gt;
            vector[i] -= components[i]&lt;br /&gt;
            available[i] = true&lt;br /&gt;
            ok2get[i].signal()&lt;br /&gt;
  &lt;br /&gt;
    entry add([16] int components):&lt;br /&gt;
        for (i from 0 to 15):&lt;br /&gt;
            vector[i] += components[i]&lt;br /&gt;
            available[i] = true&lt;br /&gt;
            ok2get[i].signal()&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&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;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
monitor storage{&lt;br /&gt;
	int stored[16]&lt;br /&gt;
	int components[16]&lt;br /&gt;
	condition ok2make[16]&lt;br /&gt;
	boolean required[16] //false&lt;br /&gt;
	&lt;br /&gt;
	void add(components){&lt;br /&gt;
		stored += components;&lt;br /&gt;
		for(i=0; i&amp;lt; 16; i ++){&lt;br /&gt;
			if(required[i] == true)&lt;br /&gt;
				ok2make(i).signal();&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	void get(components){&lt;br /&gt;
		for(i = 0; i&amp;lt; 16; i++){&lt;br /&gt;
			if (stored[i] &amp;gt;= components[i])&lt;br /&gt;
				stored[i] -= components[i]&lt;br /&gt;
			else&lt;br /&gt;
				required[i] = true&lt;br /&gt;
				ok2make(i).wait();&lt;br /&gt;
				required[i] = false&lt;br /&gt;
				i—;&lt;br /&gt;
&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Esame 15/07/2019 ==&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2019.07.15.tot.pdf 2019.07.15.tot.pdf]&lt;br /&gt;
=== Esercizio c.1 ===&lt;br /&gt;
&lt;br /&gt;
# Verifica del 18/05/2020 dell'utente [[User:Acsor|Acsor]]. Ritengo sia: corretto&lt;br /&gt;
# Ritenuta corretta [[User:Flecart|Flecart]] ([[User talk:Flecart|talk]]) 15:30, 17 January 2023 (CET)&lt;br /&gt;
&lt;br /&gt;
Una semplice realizzazione in Python dello pseudocodice seguente è disponibile [https://github.com/pollomarzo/rdso1920/tree/master/2019exams/samepc qui].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
# Original authors: Mattia Guazzaloca, Paolo Marzolo&lt;br /&gt;
#&lt;br /&gt;
# Contributors: utente Acsor&lt;br /&gt;
&lt;br /&gt;
monitor pair_buffer:&lt;br /&gt;
    int nw, nr;&lt;br /&gt;
    queue buffer;&lt;br /&gt;
    condition same_number;&lt;br /&gt;
&lt;br /&gt;
    pair_buffer():&lt;br /&gt;
        nw = nr = 0&lt;br /&gt;
        buffer = queue()&lt;br /&gt;
        same_number = condition()&lt;br /&gt;
    &lt;br /&gt;
    @entry&lt;br /&gt;
    put(T x):&lt;br /&gt;
        nw++;&lt;br /&gt;
        buffer.enqueue(x);&lt;br /&gt;
        &lt;br /&gt;
        if nw != nr:&lt;br /&gt;
            same_number.wait();&lt;br /&gt;
            &lt;br /&gt;
        same_number.signal();&lt;br /&gt;
        nw--;&lt;br /&gt;
        &lt;br /&gt;
    @entry&lt;br /&gt;
    T get(void):&lt;br /&gt;
        nr++;&lt;br /&gt;
&lt;br /&gt;
        if nw != nr: &lt;br /&gt;
            same_number.wait();&lt;br /&gt;
        else:&lt;br /&gt;
            same_number.signal();&lt;br /&gt;
        &lt;br /&gt;
        T val = buffer.dequeue();&lt;br /&gt;
        same_number.signal();&lt;br /&gt;
        nr--;&lt;br /&gt;
&lt;br /&gt;
        return val;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.2 (da controllare) ===&lt;br /&gt;
Viene ritornata x stessa, in un numero di iterazioni pari a length(x). Il calcolo viene svolto tramite message passing tra processi client e processo server; [http://www.treccani.it/magazine/lingua_italiana/domande_e_risposte/grammatica/grammatica_030.html quest'ultimo] opera una sorta di iterazione inoltrando a se stesso il messaggio spedito da un client finché x != &amp;quot;&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Se più processi chiamano la funzione dilemma() allo stesso tempo, ciò non causa disagi nel calcolo del risultato finale. Infatti l'identificatore del processo cliente destinatario è memorizzato in pid, e protratto fino alla chiamata in cui x == &amp;quot;&amp;quot;. Inoltre la presenza di molteplici richieste non causa sovrapposizione, posto che asend() memorizzi il contenuto di messaggi in sospeso in una coda FIFO.&lt;br /&gt;
&lt;br /&gt;
== Esame 13/09/2019 ==&lt;br /&gt;
Testo: [https://www.cs.unibo.it/~renzo/so/compiti/2019.09.13.tot.pdf 2019.09.13.tot.pdf].&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.1 (controllato) ===&lt;br /&gt;
* Controllato dal professor Davoli durante la lezione del 19/05/2020.&lt;br /&gt;
* Controllato dall'utente [[User:Acsor|Acsor]] ([[User talk:Acsor|talk]]) in data 19:13, 1 September 2020 (CEST). &lt;br /&gt;
* Controllato [[User:Flecart|Flecart]] ([[User talk:Flecart|talk]]) 16:09, 17 January 2023 (CET) &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
# Original author: Andrea R.&lt;br /&gt;
&lt;br /&gt;
monitor mbuf:&lt;br /&gt;
    waiting = 0&lt;br /&gt;
    queue&amp;lt;pair&amp;lt;T, int&amp;gt;&amp;gt; q    # (dato, molteplicità)&lt;br /&gt;
    condition ok2add         # q.length() &amp;lt; MAXELEM&lt;br /&gt;
    condition ok2get         # q.length() &amp;gt; 0&lt;br /&gt;
    &lt;br /&gt;
&lt;br /&gt;
    entry void add(T data, int n):&lt;br /&gt;
        if q.length() &amp;gt;= MAXELEM:&lt;br /&gt;
            ok2add.wait()&lt;br /&gt;
&lt;br /&gt;
        q.enqueue({data, n})&lt;br /&gt;
&lt;br /&gt;
        if waiting &amp;gt;= q.front().second:&lt;br /&gt;
            ok2get.signal()&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    entry T get():&lt;br /&gt;
        waiting++                                        # vuole ricevere&lt;br /&gt;
        if q.empty() or waiting &amp;lt; q.front().second:      # cortocircuitato&lt;br /&gt;
            ok2get.wait()&lt;br /&gt;
&lt;br /&gt;
        x = q.front().first&lt;br /&gt;
        q.front().second--&lt;br /&gt;
        waiting--                    # riceve&lt;br /&gt;
&lt;br /&gt;
        if q.front().second &amp;gt; 0:     # cascata&lt;br /&gt;
            ok2get.signal()&lt;br /&gt;
        else:                        # ultimo che riceve&lt;br /&gt;
            q.dequeue()&lt;br /&gt;
            ok2add.signal()&lt;br /&gt;
        return x&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.2 ===&lt;br /&gt;
&lt;br /&gt;
* Controllato da [[User:Flecart|Flecart]] ([[User talk:Flecart|talk]]) 16:12, 17 January 2023 (CET) &lt;br /&gt;
* Controllato dall'utente ? in data ?&lt;br /&gt;
* ...&lt;br /&gt;
&lt;br /&gt;
Il programma è composto da due processi, ognuno dei quali stampa all'infinito il proprio identificatore. Perché sia possibile stampare è però necessario attendere il proprio turno, condizione gestita dal monitor bohm: esso possiede due stati (0 o 1) ed è possibile entrarvi quando l'id del processo invocante e il valore dello stato corrispondono; la procedura post() di bohm setta lo stato al valore complementare e sveglia il processo in attesa sulla coda di condizione corrispondente (al nuovo stato). &lt;br /&gt;
&lt;br /&gt;
È possibile implementare il meccanismo di sincronizzazione con semafori tramite il codice seguente&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
binary_sempahore[2] sem = {new binary_semaphore(1), new binary_semaphore(0)};&lt;br /&gt;
&lt;br /&gt;
void pre (int n) {&lt;br /&gt;
    sem[n].P();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void post (int n) {&lt;br /&gt;
    sem[1 - n].V();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.2 (da controllare) ===&lt;br /&gt;
&lt;br /&gt;
L'output dei due processi è printare in modo alterno 0, 1, 0, 1....&lt;br /&gt;
Non rispetta condizione di minimalità di istruzioni e variabili, quindi non sarebbe la soluzione migliore.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int state = 0;&lt;br /&gt;
semaphore turn(0);&lt;br /&gt;
semaphore mutex(1);&lt;br /&gt;
&lt;br /&gt;
void pre(int n) {&lt;br /&gt;
	mutex.P();&lt;br /&gt;
	if (state != n) {&lt;br /&gt;
		mutex.V();&lt;br /&gt;
		turn.P();&lt;br /&gt;
	} else {&lt;br /&gt;
		mutex.V();&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void post(int n) {&lt;br /&gt;
	mutex.P();&lt;br /&gt;
	state = 1 - state;	&lt;br /&gt;
	turn.V();&lt;br /&gt;
	mutex.V();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Esercizio g.1 (da controllare) ===&lt;br /&gt;
* Controllato dall'utente ? in data ?&lt;br /&gt;
* ...&lt;br /&gt;
&lt;br /&gt;
Date le variabili del problema x, y ed m, bisogna avere x &amp;lt; m, x &amp;lt; y e che il tempo di arrivo dei processi P1, P2 e P3 durante lo scheduling RR sia P1, P2 e P3. Per ulteriori informazioni vedere lo svolgimento in figura. (Nota: non è specificata la relazione tra y ed m né sono considerati i casi x = m e x = y.)&lt;br /&gt;
&lt;br /&gt;
[[File:2019-09-13-g1.jpg | 768px]]&lt;br /&gt;
&lt;br /&gt;
=== Esercizio g.2 (da controllare) ===&lt;br /&gt;
&lt;br /&gt;
# Le opzioni per comunicare con le periferiche di IO sono solitamente due: polling (sondaggio) e interrupt. Mediante il polling il sistema verifica costantemente lo stato dei dispositivi di IO prendendo azione quando esso cambia, con gli interrupt sono i dispositivi stessi a notificare il cambiamento del loro stato. Poiché fare polling significa eseguire ciclicamente delle istruzioni che svolgano il controllo, ricevere degli interrupt è più efficiente perché nello stesso tempo è possibile svolgere altro lavoro utile.&lt;br /&gt;
# ''Da svolgere.''&lt;br /&gt;
# Quando bisogna svolgere un'operazione di swap-in (caricamento di una pagina dalla memoria secondaria a quella primaria) e di swap-out (inversa alla precedente). L'algoritmo di rimpiazzamento è invocato durante un'operazione di swap-in che vede la memoria centrale completamente occupata: in tal caso sarà necessario individuare una pagina da spostare in memoria secondaria.&lt;br /&gt;
# Vantaggi: dimensioni del file eseguibile finale ridotte, in quanto non è richiesto mantenere all'interno dello stesso una copia delle procedure di cui ci si serve; risparmio in memoria centrale: per un dato simbolo appartenente ad una data libreria, è possibile riservare un solo spazio in memoria condiviso da più processi che ne hanno bisogno. Svantaggi: versionamento, ovvero l'installazione di versioni più aggiornate della stessa libreria in conflitto con quelle meno recenti: tale problema è risolto mediante la definizione precisa di numeri di versione delle librerie e la specificazione delle dipendenze (rispetto ad un dato numero di versione).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Esame 2019/01/15 = &lt;br /&gt;
&lt;br /&gt;
== Esercizio c1 ==&lt;br /&gt;
&lt;br /&gt;
=== Soluzione proposta 1 ===&lt;br /&gt;
* Proposta [[User:Flecart|Flecart]] ([[User talk:Flecart|talk]]) 14:25, 17 January 2023 (CET)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
monitor wsem {&lt;br /&gt;
		&lt;br /&gt;
	condition cond;&lt;br /&gt;
	queue&amp;lt;int&amp;gt; waiting;&lt;br /&gt;
	&lt;br /&gt;
	wsem(value) {&lt;br /&gt;
		this-&amp;gt;value = value;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	P(int w) {&lt;br /&gt;
		if (w &amp;gt; value || waiting.size() &amp;gt; 0) {&lt;br /&gt;
			waiting.enqueue(w);&lt;br /&gt;
			cond.wait();&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		value -= w;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	V(int w) {&lt;br /&gt;
		value += w;&lt;br /&gt;
&lt;br /&gt;
		while (waiting.size() &amp;gt; 0 &amp;amp;&amp;amp; waiting.front() &amp;lt;= value) {&lt;br /&gt;
			waiting.dequeue();&lt;br /&gt;
			cond.signal();&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 c2 ==&lt;br /&gt;
* Soluzione proposta [[User:Flecart|Flecart]] ([[User talk:Flecart|talk]]) 14:38, 17 January 2023 (CET) &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
ms_send(pid dest, msg_t msg) {&lt;br /&gt;
	asend(dest, &amp;lt;msg, getpid()&amp;gt;);&lt;br /&gt;
	ack = arecv(dest);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ms_recv(int n, pid *senders, msg_t *msgs) {&lt;br /&gt;
	pid_t sender_pid[n];&lt;br /&gt;
	for (int i = 0; i &amp;lt; n; i++) {&lt;br /&gt;
		msgs[i], sender_pid[i] = arecv(senders[i]);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	for (int i = 0; i &amp;lt; n; i++) {&lt;br /&gt;
		asend(senders_pid[i], ACK);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Esempi di deadlock:&lt;br /&gt;
&lt;br /&gt;
* Due processi A, B si aspettano messaggi l'un l'altro. (entrambi chiamano recv sull'altro), questo è un deadlock comune anche al message passing sincrono.&lt;br /&gt;
* L'esempio di sopra si può estendere in un caso più generale quando sia A un ms_recv ed esiste un processo all'interno di senders che stia aspettando un messaggio da A.&lt;br /&gt;
* Altro deadlock che può capitare è quando uno stesso processo è presente più volte all'interno di senders, in questo caso ricevo solo una volta, è impossibile che riesca a ricevere una altra volta.&lt;br /&gt;
* Per esempio basterebbe avere come input un (ANY, 1), e ricevere il primo messaggio da 1, e, nonostante soddisfi le specifiche, si avrebbe un deadlock.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Soluzione proposta [[User:Flecart|Flecart Friend]] cedo, la proprietà intellettuale di questa soluzione a flecart.&lt;br /&gt;
&lt;br /&gt;
Doveri avere risolto gli ultimi due casi di deadlock descritti sopra con questo codice  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
void ms_send(pid dest, msg_t msg){&lt;br /&gt;
  asend(&amp;lt;getpid(),msg&amp;gt;,dest);&lt;br /&gt;
  while(true){&lt;br /&gt;
    &amp;lt;pid,msg&amp;gt;=arecv(dest);&lt;br /&gt;
    if(msg==ACK){&lt;br /&gt;
      break;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
ms_recv(int n, pid *senders, msg_t *msgs){&lt;br /&gt;
  msg_t cached[MAXPID];&lt;br /&gt;
  queue&amp;lt;int&amp;gt; any;&lt;br /&gt;
  for(int i=0;i&amp;lt;MAXPID;i++){&lt;br /&gt;
    cached[i]=NULL;&lt;br /&gt;
  }&lt;br /&gt;
  for(int i=0;i&amp;lt;n;i++){&lt;br /&gt;
    if(senders[i]==ANY)any.push(i);&lt;br /&gt;
    else left++;&lt;br /&gt;
  }&lt;br /&gt;
  while(left&amp;gt;0 &amp;amp;&amp;amp; any.size()&amp;gt;0){&lt;br /&gt;
    &amp;lt;pid,msg&amp;gt;=arecv(ANY);&lt;br /&gt;
    //diamo priorità a quelli non any&lt;br /&gt;
    for(int i=0;i&amp;lt;n;i++){&lt;br /&gt;
      if(senders[i]==ANY)continue;&lt;br /&gt;
      if(msgs[i]==NULL and senders[i]==pid){&lt;br /&gt;
        msgs[i]=msg;&lt;br /&gt;
        asend(&amp;lt;getpid(),ACK&amp;gt;,sender);&lt;br /&gt;
        left--;&lt;br /&gt;
        msg=NULL;&lt;br /&gt;
        break;//break for&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
    if(msg!=NULL){&lt;br /&gt;
      //aggiungiamo agli any&lt;br /&gt;
      if(any.size()&amp;gt;0){&lt;br /&gt;
        current_index=q.pop();&lt;br /&gt;
        msgs[current_index]=msg;&lt;br /&gt;
        asend(&amp;lt;getpid(),ACK&amp;gt;,sender);&lt;br /&gt;
      }else{&lt;br /&gt;
        //se no mettiamo in cached&lt;br /&gt;
        cached[pid]=msg;&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  for(int i=0;i&amp;lt;MAXPID;i++){&lt;br /&gt;
    if(cached[i]!=NULL){&lt;br /&gt;
      asend(&amp;lt;i,cached[i]&amp;gt;,getpid());&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Gio</name></author>
	</entry>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=Prove_scritte_2022&amp;diff=2915</id>
		<title>Prove scritte 2022</title>
		<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php?title=Prove_scritte_2022&amp;diff=2915"/>
		<updated>2023-01-16T21:34:09Z</updated>

		<summary type="html">&lt;p&gt;Gio: /* Soluzione proposta 1 (da controllare) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Prova 2022/09/06 =&lt;br /&gt;
&lt;br /&gt;
== Esercizio c1 == &lt;br /&gt;
&lt;br /&gt;
Esercizio c.1: I bit di un numero intero rappresentano condizioni di un sistema. Se lo stato attuale è 6 (0110) vuole dire&lt;br /&gt;
che attualmente sono vere le condizioni 2 (0010) e 4 (0100).&lt;br /&gt;
Scrivere un monitor bitcond che fornisca le seguenti procedure entry:&lt;br /&gt;
void set(int bit2set); accende nello stato attuale i bit di bit2set&lt;br /&gt;
void unset(int bit2unset) spegne nello stato attuale i bit di bit2unset&lt;br /&gt;
void statuswait(int bit2wait) attende che lo stato attuale soddisfi tutti le condizioni indicate in bit2wait (cioè&lt;br /&gt;
che tutti i bit in bit2wait siano accesi nello stato attuale).&lt;br /&gt;
Le richieste statuswait devono essere servite in ordine FIFO (cioè un processo anche se sono presenti tutte le&lt;br /&gt;
condizioni necessarie deve attendere se un processo che ha chiamato statuswait prima è in attesa).&lt;br /&gt;
Lo stato iniziale è zero (nessuna risorsa disponibile)&lt;br /&gt;
&lt;br /&gt;
=== Soluzione proposta 1 ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class bitcond{&lt;br /&gt;
  int bitmap;&lt;br /&gt;
  int lastBitmask;&lt;br /&gt;
  int has=0;&lt;br /&gt;
  &lt;br /&gt;
  condition waiting;&lt;br /&gt;
  condition c;&lt;br /&gt;
&lt;br /&gt;
  void set(int i){&lt;br /&gt;
    bitmap|=i; &lt;br /&gt;
      if(bitmap&amp;amp;lastBitmask == bitmap) c.signal();&lt;br /&gt;
  }&lt;br /&gt;
  void unset(int i){&lt;br /&gt;
    bitmap&amp;amp;=~i; &lt;br /&gt;
  }&lt;br /&gt;
  void statuswait(int i){&lt;br /&gt;
    has++; &lt;br /&gt;
    if(has&amp;gt;1){&lt;br /&gt;
      waiting.wait();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if(!(bitmap&amp;amp;i==i)){&lt;br /&gt;
      lastBitmask=i;&lt;br /&gt;
      c.wait();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    waiting.signal();&lt;br /&gt;
    has--;&lt;br /&gt;
  }&lt;br /&gt;
  bitcond(){&lt;br /&gt;
    bitmap = 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;
=== Soluzione proposta 2 ===&lt;br /&gt;
Proposta da [[User:Flecart|Flecart]] ([[User talk:Flecart|talk]]) 12:06, 14 January 2023 (CET)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
const int int_size = 32;&lt;br /&gt;
&lt;br /&gt;
class monitor {&lt;br /&gt;
    int value;&lt;br /&gt;
    condition bitset[int_size];&lt;br /&gt;
&lt;br /&gt;
    int numstatuswaiting;&lt;br /&gt;
    condition waiting;&lt;br /&gt;
    &lt;br /&gt;
    monitor() {&lt;br /&gt;
        value = 0;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    /// guarda se il bit n-significativo è settato in from&lt;br /&gt;
    bool nbit(int from, int n) {&lt;br /&gt;
        return (from &amp;amp; (1 &amp;lt;&amp;lt; n)) != 0&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void entry set(int bit2set) {&lt;br /&gt;
        value |= bit2set;&lt;br /&gt;
&lt;br /&gt;
        for (int i = 0; i &amp;lt; 32; i++) {&lt;br /&gt;
            if (nbit(value, i))&lt;br /&gt;
                bitset[i].signal();&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void entry statuswait(int bit2wait) {&lt;br /&gt;
        // in questo modo solamente un singolo processo è dentro ad aspettare&lt;br /&gt;
        // che tutte le condizioni siano rispettate&lt;br /&gt;
        if (numstatuswaiting &amp;gt; 0)&lt;br /&gt;
            waiting.wait();&lt;br /&gt;
        &lt;br /&gt;
        numstatuswaiting++;&lt;br /&gt;
        int i = 0;&lt;br /&gt;
        while(i &amp;lt; 32) {&lt;br /&gt;
            if (nbit(bit2wait, i) &amp;amp;&amp;amp; !nbit(value, i)) {&lt;br /&gt;
                bitset[i].wait();&lt;br /&gt;
&lt;br /&gt;
                // ricomincia a guardare tutti i bit da zero, perché&lt;br /&gt;
                // nel frattempo potrebbero essere cambiati.&lt;br /&gt;
                // -1 così con l'istruzione successiva diventa 0&lt;br /&gt;
                i = -1; &lt;br /&gt;
            }&lt;br /&gt;
            i++;&lt;br /&gt;
        }&lt;br /&gt;
        &lt;br /&gt;
        numstatuswaiting--;&lt;br /&gt;
        waiting.signal();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Soluzione proposta 3 ===&lt;br /&gt;
Proposta da [[User:Flecart|Flecart]] ([[User talk:Flecart|talk]]) 12:07, 14 January 2023 (CET)&lt;br /&gt;
questa è la soluzione più brutta, ma dovrebbe andare.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
const int int_size = 32;&lt;br /&gt;
&lt;br /&gt;
class monitor {&lt;br /&gt;
    int value;&lt;br /&gt;
    condition status;&lt;br /&gt;
&lt;br /&gt;
    int numstatuswaiting;&lt;br /&gt;
    condition waiting;&lt;br /&gt;
    &lt;br /&gt;
    monitor() {&lt;br /&gt;
        value = 0;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    /// guarda se il bit n-significativo è settato in from&lt;br /&gt;
    bool nbit(int from, int n) {&lt;br /&gt;
        return (from &amp;amp; (1 &amp;lt;&amp;lt; n)) != 0&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void entry set(int bit2set) {&lt;br /&gt;
        value |= bit2set;&lt;br /&gt;
        status.signal();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    void entry unset(int bit2unset) {&lt;br /&gt;
        value = (value &amp;amp; ~bit2unset);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void entry statuswait(int bit2wait) {&lt;br /&gt;
        // in questo modo solamente un singolo processo è dentro ad aspettare&lt;br /&gt;
        // che tutte le condizioni siano rispettate&lt;br /&gt;
        if (numstatuswaiting &amp;gt; 0)&lt;br /&gt;
            waiting.wait();&lt;br /&gt;
        &lt;br /&gt;
        numstatuswaiting++;&lt;br /&gt;
        while(true) {&lt;br /&gt;
            if ((value &amp;amp; bit2wait) == bit2wait) &lt;br /&gt;
                break;&lt;br /&gt;
            else &lt;br /&gt;
                status.wait();&lt;br /&gt;
        }&lt;br /&gt;
        numstatuswaiting--;&lt;br /&gt;
        waiting.signal();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Prova 2022/06/21 =&lt;br /&gt;
&lt;br /&gt;
== Esercizio c1 ==&lt;br /&gt;
Scrivere il monitor collocamento:&lt;br /&gt;
  void cercolavoro(char *nome, char *skill)&lt;br /&gt;
  void char *assumo(char * skill)&lt;br /&gt;
Quando un processo chiama la cercolavoro si mette in attesa di una richiesta di lavoro e rimane bloccato nel monitor&lt;br /&gt;
fino a che non è stato assunto. Nella cercolavoro viene indicato il nome dell'aspirante lavoratore la sua capacità (skill).&lt;br /&gt;
Un datore di lavoro con necessità di personale chiama la assumo specificando la capacità richiesta. Se c'è in attesa&lt;br /&gt;
almeno un aspirante lavoratore con quella specifica capacità (uguale valore di skill), il datore di lavoro riceve il nome del&lt;br /&gt;
nuovo dipendente ed entrambi i processi escono dal monitor. Nel caso non ci siano richieste compatibili il datore di&lt;br /&gt;
lavoro si blocca nel monitor attendendo un lavoratore con la capacità cercata. Quando arriva il lavoratore che soddisfa&lt;br /&gt;
le richieste si sbloccano entrambi i processi lavoratore e datore di lavoro. La assumo restituisce in ogni caso il nome del&lt;br /&gt;
dipendente da assumere.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Soluzione proposta === &lt;br /&gt;
&lt;br /&gt;
Soluzione proposta da [[User:Flecart|Flecart]] ([[User talk:Flecart|talk]]) 12:08, 14 January 2023 (CET)&lt;br /&gt;
&lt;br /&gt;
ci potrebbe essere un errore in quanto non è specificato il comportamento della struttura dati in alcune situazioni&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
class collocamento{&lt;br /&gt;
&lt;br /&gt;
set&amp;lt;char *, condition&amp;gt; richieste;  // chi assume cerca questa skill&lt;br /&gt;
set&amp;lt;char *, char *, condition&amp;gt; ricerche; // nome e skill di chi cerca&lt;br /&gt;
&lt;br /&gt;
char *last_nome;&lt;br /&gt;
&lt;br /&gt;
collocamento {&lt;br /&gt;
	last_nome = NULL;&lt;br /&gt;
	richieste = set();&lt;br /&gt;
	ricerche = set();	&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void cercolavoro(char *nome, char *skill) {&lt;br /&gt;
	datore = richieste.find(skill);  // cerca valutando la prima come chiave&lt;br /&gt;
	if (datore != NULL) {&lt;br /&gt;
		&amp;lt;skill, cond&amp;gt; = datore;&lt;br /&gt;
		richieste.remove(datore);&lt;br /&gt;
		last_nome = nome;&lt;br /&gt;
		cond.signal();		&lt;br /&gt;
	} else {&lt;br /&gt;
		condition c = new condition();&lt;br /&gt;
		ricerche.insert(nome, skill, c);&lt;br /&gt;
		c.wait();&lt;br /&gt;
		free(c);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void char *assumo(char * skill){&lt;br /&gt;
	lavoratore = ricerche.find2(skill); // cerca valutando la seconda come chiave.&lt;br /&gt;
	if (lavoratore != NULL) {&lt;br /&gt;
		&amp;lt;nome, skill, cond&amp;gt; = lavoratore;&lt;br /&gt;
		ricerche.remove(lavoratore);&lt;br /&gt;
		cond.signal();&lt;br /&gt;
		last_nome = nome;&lt;br /&gt;
	} else {&lt;br /&gt;
		condition c = new condition();&lt;br /&gt;
		richieste.insert(skill, c);&lt;br /&gt;
		c.wait();&lt;br /&gt;
		free(c);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	return last_nome;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
}// class collocamento&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Soluzione proposta === &lt;br /&gt;
&lt;br /&gt;
Soluzione proposta da [[User:Flecart|Flecart Frend]], regalo la proprietà intellettuale di questa soluzione a flecart.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
class workdisptcher{&lt;br /&gt;
&lt;br /&gt;
  // la multi map può storare più di un valore per una chiave&lt;br /&gt;
  // quando viene richiesta una particolare chiave da in maniera LIFO&lt;br /&gt;
  // il risultato&lt;br /&gt;
  // es:&lt;br /&gt;
  // multi_map&amp;lt;char *,int&amp;gt; lavoratori;&lt;br /&gt;
  // lavoratori.insert(&amp;quot;prova&amp;quot;,2);&lt;br /&gt;
  // lavoratori.insert(&amp;quot;prova&amp;quot;,1);&lt;br /&gt;
  // lavoratori.get(&amp;quot;prova&amp;quot;) == 2&lt;br /&gt;
  // lavoratori.remove(&amp;quot;prova&amp;quot;)&lt;br /&gt;
  // lavoratori.get(&amp;quot;prova&amp;quot;) == 1&lt;br /&gt;
  multi_map&amp;lt;char *,(char*,cond)&amp;gt; lavoratori;&lt;br /&gt;
  multi_map&amp;lt;char *,cond&amp;gt; posti_aperti;&lt;br /&gt;
  char* buffer_name;&lt;br /&gt;
  void cercolavoro(char *nome, char *skill){&lt;br /&gt;
    if(posti_aperti.find(skill)){&lt;br /&gt;
      auto entry =posti_aperti.get(skill);&lt;br /&gt;
      posti_aperti.remove(entry);&lt;br /&gt;
      buffer_name=name;&lt;br /&gt;
      entry.1.signal();&lt;br /&gt;
    }else{&lt;br /&gt;
      cond c= new cond();&lt;br /&gt;
      lavoratori.insert(skill,(nome,c)) ;&lt;br /&gt;
      c.wait();&lt;br /&gt;
      free(c);&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  void char *assumo(char * skill){&lt;br /&gt;
    if(lavoratori.find(skill)){&lt;br /&gt;
      auto entry =lavoratori.get(skill);&lt;br /&gt;
      posti_aperti.remove(entry);&lt;br /&gt;
      auto [nome,cnd] = entry.1;&lt;br /&gt;
      cond.signal();&lt;br /&gt;
      return nome;&lt;br /&gt;
    }else{&lt;br /&gt;
      cond c= new cond();&lt;br /&gt;
      posti_aperti.insert(skill,c) ;&lt;br /&gt;
      c.wait();&lt;br /&gt;
      free(c);&lt;br /&gt;
      return buffer_name;&lt;br /&gt;
    }&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 c2 ==&lt;br /&gt;
Un servizio viene fornito in modalità client-server usando message passing asincrono.&lt;br /&gt;
Al fine di aumentare l'efficienza si decide di usare molti server e un processo dispatcher in grado di distribuire le&lt;br /&gt;
richieste agli N server. Quando un processo server è libero riceve dal dispatcher la prossima richiesta da elaborare:&lt;br /&gt;
codice di ogni client (tanti!): .....&lt;br /&gt;
  asend(&amp;lt;getpid(), request&amp;gt;, dispatcher)&lt;br /&gt;
  result = arecv(dispatcher)&lt;br /&gt;
&lt;br /&gt;
server process[i], i = 0, ..., N-1:&lt;br /&gt;
 request = arecv(dispatcher)&lt;br /&gt;
 result = compute(request)&lt;br /&gt;
 asend(&amp;lt;getpid(), result&amp;gt;, dispatcher)&lt;br /&gt;
Scrivere il processo dispatcher. (il dispatcher conosce i pid di tutti i server).&lt;br /&gt;
&lt;br /&gt;
=== Soluzione proposta (sbagliata) === &lt;br /&gt;
&lt;br /&gt;
Soluzione proposta da [https://so.v2.cs.unibo.it/wiki/index.php/User:Flecart Flecart] &lt;br /&gt;
&lt;br /&gt;
Questo esercizio è stato corretto tempo fa in classe dal professore, **non è completamente corretto** se si vuole provare a correggerlo alla fine dell'esercizio c'è scritto cos'è sbagliato.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
extern int N;&lt;br /&gt;
process dispatcher() {&lt;br /&gt;
    // indice che tiene conto a quale server dover mandare&lt;br /&gt;
    // per semplicità supponiamo che i server abbiano PID&lt;br /&gt;
    // da 0 a N - 1&lt;br /&gt;
    int i = 0; &lt;br /&gt;
&lt;br /&gt;
    // mappa server a pid del processo che lo ha richiesto.&lt;br /&gt;
    // chiave: pid del server&lt;br /&gt;
    // value: queue richiesta dispatchata al server in chiave&lt;br /&gt;
    map&amp;lt;int, queue&amp;lt;int&amp;gt;&amp;gt; mapper; &lt;br /&gt;
    while (true) {&lt;br /&gt;
        res = arecv(ANY);&lt;br /&gt;
        &lt;br /&gt;
        // in questa parte l'importante è sapere&lt;br /&gt;
        // se la richiesta proviene dal  server o da un altro&lt;br /&gt;
        // processo, ho assunto che la disambiguazione &lt;br /&gt;
        // fosse immediata, un altro modo per checkare questo&lt;br /&gt;
        // è vedere se il PID del messaggio rientri fra quelli&lt;br /&gt;
        // noti al dispatcher.&lt;br /&gt;
        if (&amp;lt;pid, request&amp;gt; = res) {&lt;br /&gt;
            mapper[i].enqueue(pid);&lt;br /&gt;
            asend(request, i /*il i-esimo server*/);&lt;br /&gt;
            i++;&lt;br /&gt;
            i %= N;&lt;br /&gt;
        } else if (&amp;lt;pid, response&amp;gt; = res) {&lt;br /&gt;
            requester_pid = mapper[pid].dequeue();&lt;br /&gt;
            asend(response, requester_pid);&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;
l'es è sbagliato perchè dovrei mandare ai server liberi, non a round-robin [[User:Flecart|Flecart]] ([[User talk:Flecart|talk]]) 15:52, 14 January 2023 (CET)&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:Gio Giovanni Spadaccini] &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
dispatcher{&lt;br /&gt;
  queue&amp;lt;&amp;lt;pid,request&amp;gt;&amp;gt; work;&lt;br /&gt;
  queue&amp;lt;pid&amp;gt; freeserver;&lt;br /&gt;
  map&amp;lt;pid,pid&amp;gt; map_server_to_client;&lt;br /&gt;
  while(true){&lt;br /&gt;
    &amp;lt;pid,message&amp;gt;=arecv(ANY);&lt;br /&gt;
    if pid in servers{&lt;br /&gt;
      client=map_server_to_client.get(pid);&lt;br /&gt;
      map_client_to_server.remove(pid);&lt;br /&gt;
      freeserver.push(pid);&lt;br /&gt;
      asend(&amp;lt;message&amp;gt;,client);&lt;br /&gt;
    }else{&lt;br /&gt;
      work.push(&amp;lt;pid,message&amp;gt;);&lt;br /&gt;
    }&lt;br /&gt;
    while !freeserver.empty() and !work.emtpy(){&lt;br /&gt;
      server_pid = freeserver.pop();&lt;br /&gt;
      &amp;lt;client,msg&amp;gt; = work.pop();&lt;br /&gt;
      map_server_to_client.insert(server,client);&lt;br /&gt;
      asend(msg,server_pid);&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Prova 2022/06/01 =&lt;br /&gt;
&lt;br /&gt;
== Esercizio c1 ==&lt;br /&gt;
&lt;br /&gt;
Scrivere il monitor delay che fornisce due procedure entry:&lt;br /&gt;
  int wait_tick(int nticks)&lt;br /&gt;
  void tick(void)&lt;br /&gt;
La procedure entry tick è pensata per essere richiamata periodicamente (es. ogni secondo o ora o giorno) da un&lt;br /&gt;
processo.&lt;br /&gt;
Quando un processo chiama la wait_tick deve attendere un numero di chiamate della tick pari al parametro nticks.&lt;br /&gt;
Per esempio se un processo chiama wait_tick(2) deve fermarsi e verrà riattivato alla seconda successiva chiamata di&lt;br /&gt;
tick.&lt;br /&gt;
La funzione wait_tick ha come valore di ritorno il numero di processi che erano bloccati al momento della tick che ha&lt;br /&gt;
sbloccato il chiamante.&lt;br /&gt;
Esempio: P chiama wait_tick(2) e si blocca. Q chiama wait_tick(3) e si blocca. T chiama tick() non succede nulla. R&lt;br /&gt;
chiama wait_tick(2) e si blocca. T chiama tick(), viene sbloccata la wait_tick di P e il valore ritornato è 3. T chiama&lt;br /&gt;
tick(), vengono sbloccate le wait_tick di Q e R e il valore ritornato per entrambi i processi è 2&lt;br /&gt;
&lt;br /&gt;
=== Soluzione proprosta 1 (da controllare) ===&lt;br /&gt;
Soluzione proposta 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;
class MonitorDelay {&lt;br /&gt;
    int curr_time;&lt;br /&gt;
    int waiting_num;&lt;br /&gt;
&lt;br /&gt;
    // min heap con il tempo di sblocco dei processi e la condizione su cui è fermato&lt;br /&gt;
    // il tempo di sblocco minore è messo in cima alla heap&lt;br /&gt;
    // la sintassi con pair è ispirata alla std::pair di c++&lt;br /&gt;
    heap&amp;lt;pair&amp;lt;int, condition&amp;gt;&amp;gt; waiting; &lt;br /&gt;
&lt;br /&gt;
    void init() {&lt;br /&gt;
        curr_time = 0;&lt;br /&gt;
        waiting = heap&amp;lt;pair&amp;lt;int, condition&amp;gt;&amp;gt;();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    int entry wait_tick(int nticks) {&lt;br /&gt;
        if (nticks &amp;lt;= 0) {&lt;br /&gt;
            return waiting.size();&lt;br /&gt;
        } else {&lt;br /&gt;
            condition c = new condition();&lt;br /&gt;
            waiting.insert(make_pair(nticks + curr_time, c));&lt;br /&gt;
            c.wait();&lt;br /&gt;
            free(c);&lt;br /&gt;
        }&lt;br /&gt;
        return waiting_num;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    void entry tick(void) {&lt;br /&gt;
        waiting_num = waiting.size();&lt;br /&gt;
        curr_time++;&lt;br /&gt;
&lt;br /&gt;
        while (waiting.head().first &amp;lt;= curr_time) {&lt;br /&gt;
            condition c = waiting.head().second;&lt;br /&gt;
            waiting.deleteHead();&lt;br /&gt;
            c.signal();&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Esercizio c2 ==&lt;br /&gt;
&lt;br /&gt;
=== Consegna ===&lt;br /&gt;
&lt;br /&gt;
Esercizio c.2: Un servizio di message passing asincrono non fifo (nfasend/nfarecv) consegna in tempo finito tutti i&lt;br /&gt;
messaggi spediti ma non è garantito che i messaggi vengano ricevuti nell'ordine nel quale sono stati spediti.&lt;br /&gt;
  void nfasend(msg_t msg, pid_t dest)&lt;br /&gt;
  msg_t nfarecv(pid_t sender)&lt;br /&gt;
Dato un servizio di message passing asincrono non fifo scrivere una libreria che implementi il servizio di message&lt;br /&gt;
passing asincrono fifo:&lt;br /&gt;
  void asend(msg_t msg, pid_t dest)&lt;br /&gt;
  msg_t arecv(pid_t sender)&lt;br /&gt;
Nota: sia il servizio dato (non fifo) sia quello da implementare (fifo) consentono la ricezione solo da mittente specificato&lt;br /&gt;
(non supportano ANY/*).&lt;br /&gt;
&lt;br /&gt;
=== Soluzione proposta 1 ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void nfasend(msg_t msg, pid_t dest);&lt;br /&gt;
msg_t nfarecv(pid_t sender);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// array di grandezza di massimi numero di processi, inizializzato a 0&lt;br /&gt;
// utilizzato per contare il numero di messaggi inviati a un certo processo.&lt;br /&gt;
int num_sender[MAX_PROC];&lt;br /&gt;
&lt;br /&gt;
//RICORDA che ogni sender ha il suo num_sender[...]&lt;br /&gt;
&lt;br /&gt;
void asend(msg_t msg, pid_t dest) {&lt;br /&gt;
	src = getpid();&lt;br /&gt;
	nfasend(&amp;lt;msg, num_send[dest]&amp;gt;, dest);&lt;br /&gt;
	num_sender[dest]++;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// molto simile a num_sender, ma è utilizzato per contare il numero di messaggi ricevuti, in ordine.&lt;br /&gt;
int num_receiver[MAX_PROC];&lt;br /&gt;
// array heap ordinato sul int (per ogni heap in cima c'è il messaggio col minimo int).&lt;br /&gt;
min_heap&amp;lt;msg, int&amp;gt; messages[MAX_PROC];&lt;br /&gt;
&lt;br /&gt;
//RICORDA che ogni receiver ha il suo proprio num_receiver[...] e messages[...]&lt;br /&gt;
&lt;br /&gt;
msg_t arecv(pid_t sender) {&lt;br /&gt;
	p = getpid();&lt;br /&gt;
	&lt;br /&gt;
	if (messages[sender].size() &amp;gt; 0 &amp;amp;&amp;amp; messages[sender].top() == num_receiver[sender]) {&lt;br /&gt;
		(msg, num_mess) = messages[sender].removeTop();&lt;br /&gt;
		num_receiver[sender]++;&lt;br /&gt;
		return msg;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	(msg, num_mess) = nfarecv(sender);&lt;br /&gt;
&lt;br /&gt;
	while (num_mess != num_receiver[sender]) {&lt;br /&gt;
		messages[sender].insert(msg, num_mess);&lt;br /&gt;
		(msg, num_mess) = nfarecv(sender);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	num_receiver[sender]++;&lt;br /&gt;
	return msg;	&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Prova 2022/02/14 =&lt;br /&gt;
&lt;br /&gt;
== Esercizio c1 ==&lt;br /&gt;
Scrivere il monitor semdata che implementi un semaforo con dato. Questa astrazione prevede due operazioni:&lt;br /&gt;
&lt;br /&gt;
 datatype dP(void);&lt;br /&gt;
 void dV(datatype data);&lt;br /&gt;
&lt;br /&gt;
Non è previsto assegmento di valore iniziale nel costruttore, l'invariante è lo stesso dei semafori (con init = 0): ndP &amp;lt;=&lt;br /&gt;
ndV (dove ndP e ndV rappresentano rispettivamente il numero di operazioni dP e dV completate. I dati passati come&lt;br /&gt;
parametro alla dV devono essere memorizzati in ordine LIFO. L'operazione nP restituisce il valore più recente fra quelli&lt;br /&gt;
memorizzati (e lo cancella dalla struttura dati).&lt;br /&gt;
&lt;br /&gt;
=== Proposta di soluzione 1 ===&lt;br /&gt;
* Proposta da [[User:Flecart|Flecart]] ([[User talk:Flecart|talk]]) 12:06, 16 January 2023 (CET)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
class semdata {&lt;br /&gt;
&lt;br /&gt;
stack&amp;lt;datatype&amp;gt; pila;&lt;br /&gt;
condition p_waiting;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
semdata() {&lt;br /&gt;
	pila = stack();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
datatype dp(void) {&lt;br /&gt;
	if (pila.len() &amp;lt;= 0) {&lt;br /&gt;
		p_waiting.wait();&lt;br /&gt;
	}	&lt;br /&gt;
&lt;br /&gt;
	return pila.pop();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void dV(datatype data) {&lt;br /&gt;
	pila.push(data);&lt;br /&gt;
	p_waiting.signal();&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;
= Prova 2022/01/17 =&lt;br /&gt;
&lt;br /&gt;
== Esercizio c1 ==&lt;br /&gt;
&lt;br /&gt;
Scrivere il monitor multibuf che implementi un buffer limitato (MAX elementi) di oggetti di tipo T che&lt;br /&gt;
implementi le seguenti procedure entry:&lt;br /&gt;
  void add(int n, T objexts[]);&lt;br /&gt;
  void get(int n, T objects[]);&lt;br /&gt;
La funzione add deve aggiungere al buffer gli n oggetti passati col parametro objects. La funzione get deve predere&lt;br /&gt;
dal buffer in modalità FIFO i primi n elementi presenti nel buffer e copiarli negli elementi del vettore objects.&lt;br /&gt;
Entrambe le funzioni devono attendere che vi siano le condizioni per poter essere completate: che ci siano n elementi&lt;br /&gt;
liberi per la add, che ci siano n elementi nel buffer per la get. Non sono ammesse esecuzioni parziali: mentre attendono&lt;br /&gt;
le rispettive condizioni nessun elemento può essere aggiunto o rimosso dal buffer.&lt;br /&gt;
La definizione del problema C.1 presenta casi di possibile deadlock?&lt;br /&gt;
&lt;br /&gt;
=== Soluzione proposta 1 ===&lt;br /&gt;
&lt;br /&gt;
* Proposta [[User:Flecart|Flecart]] ([[User talk:Flecart|talk]]) 12:41, 16 January 2023 (CET)&lt;br /&gt;
&lt;br /&gt;
Una situazione di deadlock è quando un add non ha abbastanza per inserire, e get non ha abbastanza da prendere. Se non utilizzo la coda come ho fatto così&lt;br /&gt;
rischio starvation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
class multibuf {&lt;br /&gt;
	&lt;br /&gt;
T buffer[MAX];&lt;br /&gt;
int i, j;&lt;br /&gt;
int free;&lt;br /&gt;
queue&amp;lt;int,cond&amp;gt; add_queue;&lt;br /&gt;
&lt;br /&gt;
queue&amp;lt;int,cond&amp;gt; get_queue;&lt;br /&gt;
&lt;br /&gt;
multibuf {&lt;br /&gt;
	i = j = 0;&lt;br /&gt;
	free = MAX;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void add(int n, T objects[]) {&lt;br /&gt;
	if (add_queue.size() &amp;gt; 0 || free &amp;lt; n) {&lt;br /&gt;
		condition c = new condition();&lt;br /&gt;
		add_queue.enqueue(n, c);&lt;br /&gt;
		c.wait();&lt;br /&gt;
		free(c);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	for (int k = j; k != (j + n) % MAX; k = (k + 1) % MAX) {&lt;br /&gt;
		int other_idx = (k - i) &amp;lt; 0 ? k + MAX - i : k - i;&lt;br /&gt;
		buffer[k] = objects[other_idx];&lt;br /&gt;
	}&lt;br /&gt;
	free -= n;&lt;br /&gt;
	j = (j + n) % MAX;&lt;br /&gt;
		&lt;br /&gt;
	while (get_queue.size() &amp;gt; 0 &amp;amp;&amp;amp; get_queue.front() &amp;lt;= MAX - free) {&lt;br /&gt;
		n, cond = get_queue.dequeue();&lt;br /&gt;
		cond.signal();&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void get(int n, T objects[]) {&lt;br /&gt;
	if (get_queue.size() &amp;gt; 0 || MAX - free &amp;lt; n) {&lt;br /&gt;
		condition c = new condition();&lt;br /&gt;
		get_queue.enqueue(n, c);&lt;br /&gt;
		c.wait();&lt;br /&gt;
		free(c);&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	for (int k = i; k != (i + n) % MAX; k = (k + 1) % MAX) {&lt;br /&gt;
		int other_idx = (k - i) &amp;lt; 0 ? k + MAX - i : k - i;&lt;br /&gt;
		objects[other_idx] = buffer[k];&lt;br /&gt;
	}&lt;br /&gt;
	free += n;&lt;br /&gt;
	i = (i + n) % MAX;&lt;br /&gt;
&lt;br /&gt;
	while (add_queue.size() &amp;gt; 0 &amp;amp;&amp;amp; add_queue.front() &amp;lt;= free) {&lt;br /&gt;
		n, cond = add_queue.dequeue();&lt;br /&gt;
		cond.signal();&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
} // multibuf&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Esercizio c2 ==&lt;br /&gt;
Un servizio di message passing sincrono senza selezione del mittente prevede una API con due funzioni:&lt;br /&gt;
  sasend(msg_t msg, pid dest);&lt;br /&gt;
  msg_t sarecv(void);&lt;br /&gt;
La funzione sarecv restituisce il primo messaggio ricevuto da qualsiasi mittente ed è bloccante se non ci sono&lt;br /&gt;
messaggi pendenti. la funzione sasend si blocca fino a quando il messaggio msg non viene ricevuto dal processo dest.&lt;br /&gt;
Dato quindi un servizio di message passing sincrono senza selezione del mittente implementare un servizio di&lt;br /&gt;
message passing sincrono (standard, quello definito nel corso) senza fare uso di processi server. &lt;br /&gt;
&lt;br /&gt;
=== Soluzione proposta 1 (da controllare) ===&lt;br /&gt;
* proposta da [[User:Flecart|Flecart]] ([[User talk:Flecart|talk]]) 18:25, 16 January 2023 (CET) &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
ssend(msg_t msg, pid dest) {&lt;br /&gt;
	sasend(&amp;lt;msg, getpid()&amp;gt;, dest);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// variabili interne di srecv&lt;br /&gt;
queue&amp;lt;msg_t&amp;gt; msgs[MAX_PROC];&lt;br /&gt;
&lt;br /&gt;
// suppongo non ci sia il caso in cui sender = ANY.&lt;br /&gt;
// nel caso ci fosse la necessità, si dovrebbe creare una altra struttura di dati&lt;br /&gt;
// che ordini globalmente il messaggio che sia arrivato prima.&lt;br /&gt;
msg_t srecv(pid sender) {&lt;br /&gt;
	if (msgs[sender].len() &amp;gt; 0) {&lt;br /&gt;
		return msgs[sender].dequeue();&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	while (true) {&lt;br /&gt;
		&amp;lt;msg, pid&amp;gt; = sarecv();&lt;br /&gt;
		if (pid == sender) {&lt;br /&gt;
			return msgs[pid].dequeue();&lt;br /&gt;
		} else {&lt;br /&gt;
			msgs[pid].enqueue(msg);&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;
=== Soluzione proposta 2 (da controllare) ===&lt;br /&gt;
&lt;br /&gt;
proposta da [[User:Flecart|Flecart Friend]] 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;
// mem è condivisa tra ssend e srecv di ogni processo&lt;br /&gt;
// essendo che un processo può solo mandare o ricevere alla volta&lt;br /&gt;
// non abbiamo bisogno di cs&lt;br /&gt;
&lt;br /&gt;
// inizializzati tutti a NULL&lt;br /&gt;
msg_t mem[MAXPID];&lt;br /&gt;
// in mem ci basta un messaggio per PID perchè un pid può aver mandato al&lt;br /&gt;
// massimo un messaggio essendo che sono bloccanti la send e la recive&lt;br /&gt;
&lt;br /&gt;
void ssend(msg_t msg, pid dest) {&lt;br /&gt;
  sasend(&amp;lt;getpid(),msg&amp;gt;,dest);&lt;br /&gt;
  while(true){&lt;br /&gt;
    &amp;lt;form_c,msg&amp;gt;=sarecv();&lt;br /&gt;
    // dovrebbe essere ovvio che se è from c allora il msg dovrebbe essere un&lt;br /&gt;
    // ack perchè se c avesse mandato un messaggio diverso vorrebbe dire che&lt;br /&gt;
    // sta facendo una send e se i due processi si fanno una send allora c'è&lt;br /&gt;
    // deadhlock&lt;br /&gt;
    if(from_c == dest &amp;amp;&amp;amp; msg == ACK){&lt;br /&gt;
      break;&lt;br /&gt;
    }else{&lt;br /&gt;
      mem[from_c]=msg;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
msg_t srecv(pid from) {&lt;br /&gt;
  if(mem[from]!=NULL){&lt;br /&gt;
    t=mem[from];&lt;br /&gt;
    mem[from]=NULL;&lt;br /&gt;
    ssend(ACK,from);&lt;br /&gt;
    return t;&lt;br /&gt;
  }&lt;br /&gt;
  while(true){&lt;br /&gt;
    &amp;lt;form_c,msg&amp;gt;=sarecv();&lt;br /&gt;
    if(from_c==from){&lt;br /&gt;
      ssend(ACK,from);&lt;br /&gt;
      return msg;&lt;br /&gt;
    }else{&lt;br /&gt;
      mem[from_c].push(msg);&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Gio</name></author>
	</entry>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=Prove_scritte_2022&amp;diff=2914</id>
		<title>Prove scritte 2022</title>
		<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php?title=Prove_scritte_2022&amp;diff=2914"/>
		<updated>2023-01-16T21:32:59Z</updated>

		<summary type="html">&lt;p&gt;Gio: /* Esercizio c2 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Prova 2022/09/06 =&lt;br /&gt;
&lt;br /&gt;
== Esercizio c1 == &lt;br /&gt;
&lt;br /&gt;
Esercizio c.1: I bit di un numero intero rappresentano condizioni di un sistema. Se lo stato attuale è 6 (0110) vuole dire&lt;br /&gt;
che attualmente sono vere le condizioni 2 (0010) e 4 (0100).&lt;br /&gt;
Scrivere un monitor bitcond che fornisca le seguenti procedure entry:&lt;br /&gt;
void set(int bit2set); accende nello stato attuale i bit di bit2set&lt;br /&gt;
void unset(int bit2unset) spegne nello stato attuale i bit di bit2unset&lt;br /&gt;
void statuswait(int bit2wait) attende che lo stato attuale soddisfi tutti le condizioni indicate in bit2wait (cioè&lt;br /&gt;
che tutti i bit in bit2wait siano accesi nello stato attuale).&lt;br /&gt;
Le richieste statuswait devono essere servite in ordine FIFO (cioè un processo anche se sono presenti tutte le&lt;br /&gt;
condizioni necessarie deve attendere se un processo che ha chiamato statuswait prima è in attesa).&lt;br /&gt;
Lo stato iniziale è zero (nessuna risorsa disponibile)&lt;br /&gt;
&lt;br /&gt;
=== Soluzione proposta 1 ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class bitcond{&lt;br /&gt;
  int bitmap;&lt;br /&gt;
  int lastBitmask;&lt;br /&gt;
  int has=0;&lt;br /&gt;
  &lt;br /&gt;
  condition waiting;&lt;br /&gt;
  condition c;&lt;br /&gt;
&lt;br /&gt;
  void set(int i){&lt;br /&gt;
    bitmap|=i; &lt;br /&gt;
      if(bitmap&amp;amp;lastBitmask == bitmap) c.signal();&lt;br /&gt;
  }&lt;br /&gt;
  void unset(int i){&lt;br /&gt;
    bitmap&amp;amp;=~i; &lt;br /&gt;
  }&lt;br /&gt;
  void statuswait(int i){&lt;br /&gt;
    has++; &lt;br /&gt;
    if(has&amp;gt;1){&lt;br /&gt;
      waiting.wait();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if(!(bitmap&amp;amp;i==i)){&lt;br /&gt;
      lastBitmask=i;&lt;br /&gt;
      c.wait();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    waiting.signal();&lt;br /&gt;
    has--;&lt;br /&gt;
  }&lt;br /&gt;
  bitcond(){&lt;br /&gt;
    bitmap = 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;
=== Soluzione proposta 2 ===&lt;br /&gt;
Proposta da [[User:Flecart|Flecart]] ([[User talk:Flecart|talk]]) 12:06, 14 January 2023 (CET)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
const int int_size = 32;&lt;br /&gt;
&lt;br /&gt;
class monitor {&lt;br /&gt;
    int value;&lt;br /&gt;
    condition bitset[int_size];&lt;br /&gt;
&lt;br /&gt;
    int numstatuswaiting;&lt;br /&gt;
    condition waiting;&lt;br /&gt;
    &lt;br /&gt;
    monitor() {&lt;br /&gt;
        value = 0;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    /// guarda se il bit n-significativo è settato in from&lt;br /&gt;
    bool nbit(int from, int n) {&lt;br /&gt;
        return (from &amp;amp; (1 &amp;lt;&amp;lt; n)) != 0&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void entry set(int bit2set) {&lt;br /&gt;
        value |= bit2set;&lt;br /&gt;
&lt;br /&gt;
        for (int i = 0; i &amp;lt; 32; i++) {&lt;br /&gt;
            if (nbit(value, i))&lt;br /&gt;
                bitset[i].signal();&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void entry statuswait(int bit2wait) {&lt;br /&gt;
        // in questo modo solamente un singolo processo è dentro ad aspettare&lt;br /&gt;
        // che tutte le condizioni siano rispettate&lt;br /&gt;
        if (numstatuswaiting &amp;gt; 0)&lt;br /&gt;
            waiting.wait();&lt;br /&gt;
        &lt;br /&gt;
        numstatuswaiting++;&lt;br /&gt;
        int i = 0;&lt;br /&gt;
        while(i &amp;lt; 32) {&lt;br /&gt;
            if (nbit(bit2wait, i) &amp;amp;&amp;amp; !nbit(value, i)) {&lt;br /&gt;
                bitset[i].wait();&lt;br /&gt;
&lt;br /&gt;
                // ricomincia a guardare tutti i bit da zero, perché&lt;br /&gt;
                // nel frattempo potrebbero essere cambiati.&lt;br /&gt;
                // -1 così con l'istruzione successiva diventa 0&lt;br /&gt;
                i = -1; &lt;br /&gt;
            }&lt;br /&gt;
            i++;&lt;br /&gt;
        }&lt;br /&gt;
        &lt;br /&gt;
        numstatuswaiting--;&lt;br /&gt;
        waiting.signal();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Soluzione proposta 3 ===&lt;br /&gt;
Proposta da [[User:Flecart|Flecart]] ([[User talk:Flecart|talk]]) 12:07, 14 January 2023 (CET)&lt;br /&gt;
questa è la soluzione più brutta, ma dovrebbe andare.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
const int int_size = 32;&lt;br /&gt;
&lt;br /&gt;
class monitor {&lt;br /&gt;
    int value;&lt;br /&gt;
    condition status;&lt;br /&gt;
&lt;br /&gt;
    int numstatuswaiting;&lt;br /&gt;
    condition waiting;&lt;br /&gt;
    &lt;br /&gt;
    monitor() {&lt;br /&gt;
        value = 0;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    /// guarda se il bit n-significativo è settato in from&lt;br /&gt;
    bool nbit(int from, int n) {&lt;br /&gt;
        return (from &amp;amp; (1 &amp;lt;&amp;lt; n)) != 0&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void entry set(int bit2set) {&lt;br /&gt;
        value |= bit2set;&lt;br /&gt;
        status.signal();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    void entry unset(int bit2unset) {&lt;br /&gt;
        value = (value &amp;amp; ~bit2unset);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void entry statuswait(int bit2wait) {&lt;br /&gt;
        // in questo modo solamente un singolo processo è dentro ad aspettare&lt;br /&gt;
        // che tutte le condizioni siano rispettate&lt;br /&gt;
        if (numstatuswaiting &amp;gt; 0)&lt;br /&gt;
            waiting.wait();&lt;br /&gt;
        &lt;br /&gt;
        numstatuswaiting++;&lt;br /&gt;
        while(true) {&lt;br /&gt;
            if ((value &amp;amp; bit2wait) == bit2wait) &lt;br /&gt;
                break;&lt;br /&gt;
            else &lt;br /&gt;
                status.wait();&lt;br /&gt;
        }&lt;br /&gt;
        numstatuswaiting--;&lt;br /&gt;
        waiting.signal();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Prova 2022/06/21 =&lt;br /&gt;
&lt;br /&gt;
== Esercizio c1 ==&lt;br /&gt;
Scrivere il monitor collocamento:&lt;br /&gt;
  void cercolavoro(char *nome, char *skill)&lt;br /&gt;
  void char *assumo(char * skill)&lt;br /&gt;
Quando un processo chiama la cercolavoro si mette in attesa di una richiesta di lavoro e rimane bloccato nel monitor&lt;br /&gt;
fino a che non è stato assunto. Nella cercolavoro viene indicato il nome dell'aspirante lavoratore la sua capacità (skill).&lt;br /&gt;
Un datore di lavoro con necessità di personale chiama la assumo specificando la capacità richiesta. Se c'è in attesa&lt;br /&gt;
almeno un aspirante lavoratore con quella specifica capacità (uguale valore di skill), il datore di lavoro riceve il nome del&lt;br /&gt;
nuovo dipendente ed entrambi i processi escono dal monitor. Nel caso non ci siano richieste compatibili il datore di&lt;br /&gt;
lavoro si blocca nel monitor attendendo un lavoratore con la capacità cercata. Quando arriva il lavoratore che soddisfa&lt;br /&gt;
le richieste si sbloccano entrambi i processi lavoratore e datore di lavoro. La assumo restituisce in ogni caso il nome del&lt;br /&gt;
dipendente da assumere.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Soluzione proposta === &lt;br /&gt;
&lt;br /&gt;
Soluzione proposta da [[User:Flecart|Flecart]] ([[User talk:Flecart|talk]]) 12:08, 14 January 2023 (CET)&lt;br /&gt;
&lt;br /&gt;
ci potrebbe essere un errore in quanto non è specificato il comportamento della struttura dati in alcune situazioni&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
class collocamento{&lt;br /&gt;
&lt;br /&gt;
set&amp;lt;char *, condition&amp;gt; richieste;  // chi assume cerca questa skill&lt;br /&gt;
set&amp;lt;char *, char *, condition&amp;gt; ricerche; // nome e skill di chi cerca&lt;br /&gt;
&lt;br /&gt;
char *last_nome;&lt;br /&gt;
&lt;br /&gt;
collocamento {&lt;br /&gt;
	last_nome = NULL;&lt;br /&gt;
	richieste = set();&lt;br /&gt;
	ricerche = set();	&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void cercolavoro(char *nome, char *skill) {&lt;br /&gt;
	datore = richieste.find(skill);  // cerca valutando la prima come chiave&lt;br /&gt;
	if (datore != NULL) {&lt;br /&gt;
		&amp;lt;skill, cond&amp;gt; = datore;&lt;br /&gt;
		richieste.remove(datore);&lt;br /&gt;
		last_nome = nome;&lt;br /&gt;
		cond.signal();		&lt;br /&gt;
	} else {&lt;br /&gt;
		condition c = new condition();&lt;br /&gt;
		ricerche.insert(nome, skill, c);&lt;br /&gt;
		c.wait();&lt;br /&gt;
		free(c);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void char *assumo(char * skill){&lt;br /&gt;
	lavoratore = ricerche.find2(skill); // cerca valutando la seconda come chiave.&lt;br /&gt;
	if (lavoratore != NULL) {&lt;br /&gt;
		&amp;lt;nome, skill, cond&amp;gt; = lavoratore;&lt;br /&gt;
		ricerche.remove(lavoratore);&lt;br /&gt;
		cond.signal();&lt;br /&gt;
		last_nome = nome;&lt;br /&gt;
	} else {&lt;br /&gt;
		condition c = new condition();&lt;br /&gt;
		richieste.insert(skill, c);&lt;br /&gt;
		c.wait();&lt;br /&gt;
		free(c);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	return last_nome;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
}// class collocamento&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Soluzione proposta === &lt;br /&gt;
&lt;br /&gt;
Soluzione proposta da [[User:Flecart|Flecart Frend]], regalo la proprietà intellettuale di questa soluzione a flecart.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
class workdisptcher{&lt;br /&gt;
&lt;br /&gt;
  // la multi map può storare più di un valore per una chiave&lt;br /&gt;
  // quando viene richiesta una particolare chiave da in maniera LIFO&lt;br /&gt;
  // il risultato&lt;br /&gt;
  // es:&lt;br /&gt;
  // multi_map&amp;lt;char *,int&amp;gt; lavoratori;&lt;br /&gt;
  // lavoratori.insert(&amp;quot;prova&amp;quot;,2);&lt;br /&gt;
  // lavoratori.insert(&amp;quot;prova&amp;quot;,1);&lt;br /&gt;
  // lavoratori.get(&amp;quot;prova&amp;quot;) == 2&lt;br /&gt;
  // lavoratori.remove(&amp;quot;prova&amp;quot;)&lt;br /&gt;
  // lavoratori.get(&amp;quot;prova&amp;quot;) == 1&lt;br /&gt;
  multi_map&amp;lt;char *,(char*,cond)&amp;gt; lavoratori;&lt;br /&gt;
  multi_map&amp;lt;char *,cond&amp;gt; posti_aperti;&lt;br /&gt;
  char* buffer_name;&lt;br /&gt;
  void cercolavoro(char *nome, char *skill){&lt;br /&gt;
    if(posti_aperti.find(skill)){&lt;br /&gt;
      auto entry =posti_aperti.get(skill);&lt;br /&gt;
      posti_aperti.remove(entry);&lt;br /&gt;
      buffer_name=name;&lt;br /&gt;
      entry.1.signal();&lt;br /&gt;
    }else{&lt;br /&gt;
      cond c= new cond();&lt;br /&gt;
      lavoratori.insert(skill,(nome,c)) ;&lt;br /&gt;
      c.wait();&lt;br /&gt;
      free(c);&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  void char *assumo(char * skill){&lt;br /&gt;
    if(lavoratori.find(skill)){&lt;br /&gt;
      auto entry =lavoratori.get(skill);&lt;br /&gt;
      posti_aperti.remove(entry);&lt;br /&gt;
      auto [nome,cnd] = entry.1;&lt;br /&gt;
      cond.signal();&lt;br /&gt;
      return nome;&lt;br /&gt;
    }else{&lt;br /&gt;
      cond c= new cond();&lt;br /&gt;
      posti_aperti.insert(skill,c) ;&lt;br /&gt;
      c.wait();&lt;br /&gt;
      free(c);&lt;br /&gt;
      return buffer_name;&lt;br /&gt;
    }&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 c2 ==&lt;br /&gt;
Un servizio viene fornito in modalità client-server usando message passing asincrono.&lt;br /&gt;
Al fine di aumentare l'efficienza si decide di usare molti server e un processo dispatcher in grado di distribuire le&lt;br /&gt;
richieste agli N server. Quando un processo server è libero riceve dal dispatcher la prossima richiesta da elaborare:&lt;br /&gt;
codice di ogni client (tanti!): .....&lt;br /&gt;
  asend(&amp;lt;getpid(), request&amp;gt;, dispatcher)&lt;br /&gt;
  result = arecv(dispatcher)&lt;br /&gt;
&lt;br /&gt;
server process[i], i = 0, ..., N-1:&lt;br /&gt;
 request = arecv(dispatcher)&lt;br /&gt;
 result = compute(request)&lt;br /&gt;
 asend(&amp;lt;getpid(), result&amp;gt;, dispatcher)&lt;br /&gt;
Scrivere il processo dispatcher. (il dispatcher conosce i pid di tutti i server).&lt;br /&gt;
&lt;br /&gt;
=== Soluzione proposta (sbagliata) === &lt;br /&gt;
&lt;br /&gt;
Soluzione proposta da [https://so.v2.cs.unibo.it/wiki/index.php/User:Flecart Flecart] &lt;br /&gt;
&lt;br /&gt;
Questo esercizio è stato corretto tempo fa in classe dal professore, **non è completamente corretto** se si vuole provare a correggerlo alla fine dell'esercizio c'è scritto cos'è sbagliato.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
extern int N;&lt;br /&gt;
process dispatcher() {&lt;br /&gt;
    // indice che tiene conto a quale server dover mandare&lt;br /&gt;
    // per semplicità supponiamo che i server abbiano PID&lt;br /&gt;
    // da 0 a N - 1&lt;br /&gt;
    int i = 0; &lt;br /&gt;
&lt;br /&gt;
    // mappa server a pid del processo che lo ha richiesto.&lt;br /&gt;
    // chiave: pid del server&lt;br /&gt;
    // value: queue richiesta dispatchata al server in chiave&lt;br /&gt;
    map&amp;lt;int, queue&amp;lt;int&amp;gt;&amp;gt; mapper; &lt;br /&gt;
    while (true) {&lt;br /&gt;
        res = arecv(ANY);&lt;br /&gt;
        &lt;br /&gt;
        // in questa parte l'importante è sapere&lt;br /&gt;
        // se la richiesta proviene dal  server o da un altro&lt;br /&gt;
        // processo, ho assunto che la disambiguazione &lt;br /&gt;
        // fosse immediata, un altro modo per checkare questo&lt;br /&gt;
        // è vedere se il PID del messaggio rientri fra quelli&lt;br /&gt;
        // noti al dispatcher.&lt;br /&gt;
        if (&amp;lt;pid, request&amp;gt; = res) {&lt;br /&gt;
            mapper[i].enqueue(pid);&lt;br /&gt;
            asend(request, i /*il i-esimo server*/);&lt;br /&gt;
            i++;&lt;br /&gt;
            i %= N;&lt;br /&gt;
        } else if (&amp;lt;pid, response&amp;gt; = res) {&lt;br /&gt;
            requester_pid = mapper[pid].dequeue();&lt;br /&gt;
            asend(response, requester_pid);&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;
l'es è sbagliato perchè dovrei mandare ai server liberi, non a round-robin [[User:Flecart|Flecart]] ([[User talk:Flecart|talk]]) 15:52, 14 January 2023 (CET)&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:Gio Giovanni Spadaccini] &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
dispatcher{&lt;br /&gt;
  queue&amp;lt;&amp;lt;pid,request&amp;gt;&amp;gt; work;&lt;br /&gt;
  queue&amp;lt;pid&amp;gt; freeserver;&lt;br /&gt;
  map&amp;lt;pid,pid&amp;gt; map_server_to_client;&lt;br /&gt;
  while(true){&lt;br /&gt;
    &amp;lt;pid,message&amp;gt;=arecv(ANY);&lt;br /&gt;
    if pid in servers{&lt;br /&gt;
      client=map_server_to_client.get(pid);&lt;br /&gt;
      map_client_to_server.remove(pid);&lt;br /&gt;
      freeserver.push(pid);&lt;br /&gt;
      asend(&amp;lt;message&amp;gt;,client);&lt;br /&gt;
    }else{&lt;br /&gt;
      work.push(&amp;lt;pid,message&amp;gt;);&lt;br /&gt;
    }&lt;br /&gt;
    while !freeserver.empty() and !work.emtpy(){&lt;br /&gt;
      server_pid = freeserver.pop();&lt;br /&gt;
      &amp;lt;client,msg&amp;gt; = work.pop();&lt;br /&gt;
      map_server_to_client.insert(server,client);&lt;br /&gt;
      asend(msg,server_pid);&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Prova 2022/06/01 =&lt;br /&gt;
&lt;br /&gt;
== Esercizio c1 ==&lt;br /&gt;
&lt;br /&gt;
Scrivere il monitor delay che fornisce due procedure entry:&lt;br /&gt;
  int wait_tick(int nticks)&lt;br /&gt;
  void tick(void)&lt;br /&gt;
La procedure entry tick è pensata per essere richiamata periodicamente (es. ogni secondo o ora o giorno) da un&lt;br /&gt;
processo.&lt;br /&gt;
Quando un processo chiama la wait_tick deve attendere un numero di chiamate della tick pari al parametro nticks.&lt;br /&gt;
Per esempio se un processo chiama wait_tick(2) deve fermarsi e verrà riattivato alla seconda successiva chiamata di&lt;br /&gt;
tick.&lt;br /&gt;
La funzione wait_tick ha come valore di ritorno il numero di processi che erano bloccati al momento della tick che ha&lt;br /&gt;
sbloccato il chiamante.&lt;br /&gt;
Esempio: P chiama wait_tick(2) e si blocca. Q chiama wait_tick(3) e si blocca. T chiama tick() non succede nulla. R&lt;br /&gt;
chiama wait_tick(2) e si blocca. T chiama tick(), viene sbloccata la wait_tick di P e il valore ritornato è 3. T chiama&lt;br /&gt;
tick(), vengono sbloccate le wait_tick di Q e R e il valore ritornato per entrambi i processi è 2&lt;br /&gt;
&lt;br /&gt;
=== Soluzione proprosta 1 (da controllare) ===&lt;br /&gt;
Soluzione proposta 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;
class MonitorDelay {&lt;br /&gt;
    int curr_time;&lt;br /&gt;
    int waiting_num;&lt;br /&gt;
&lt;br /&gt;
    // min heap con il tempo di sblocco dei processi e la condizione su cui è fermato&lt;br /&gt;
    // il tempo di sblocco minore è messo in cima alla heap&lt;br /&gt;
    // la sintassi con pair è ispirata alla std::pair di c++&lt;br /&gt;
    heap&amp;lt;pair&amp;lt;int, condition&amp;gt;&amp;gt; waiting; &lt;br /&gt;
&lt;br /&gt;
    void init() {&lt;br /&gt;
        curr_time = 0;&lt;br /&gt;
        waiting = heap&amp;lt;pair&amp;lt;int, condition&amp;gt;&amp;gt;();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    int entry wait_tick(int nticks) {&lt;br /&gt;
        if (nticks &amp;lt;= 0) {&lt;br /&gt;
            return waiting.size();&lt;br /&gt;
        } else {&lt;br /&gt;
            condition c = new condition();&lt;br /&gt;
            waiting.insert(make_pair(nticks + curr_time, c));&lt;br /&gt;
            c.wait();&lt;br /&gt;
            free(c);&lt;br /&gt;
        }&lt;br /&gt;
        return waiting_num;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    void entry tick(void) {&lt;br /&gt;
        waiting_num = waiting.size();&lt;br /&gt;
        curr_time++;&lt;br /&gt;
&lt;br /&gt;
        while (waiting.head().first &amp;lt;= curr_time) {&lt;br /&gt;
            condition c = waiting.head().second;&lt;br /&gt;
            waiting.deleteHead();&lt;br /&gt;
            c.signal();&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Esercizio c2 ==&lt;br /&gt;
&lt;br /&gt;
=== Consegna ===&lt;br /&gt;
&lt;br /&gt;
Esercizio c.2: Un servizio di message passing asincrono non fifo (nfasend/nfarecv) consegna in tempo finito tutti i&lt;br /&gt;
messaggi spediti ma non è garantito che i messaggi vengano ricevuti nell'ordine nel quale sono stati spediti.&lt;br /&gt;
  void nfasend(msg_t msg, pid_t dest)&lt;br /&gt;
  msg_t nfarecv(pid_t sender)&lt;br /&gt;
Dato un servizio di message passing asincrono non fifo scrivere una libreria che implementi il servizio di message&lt;br /&gt;
passing asincrono fifo:&lt;br /&gt;
  void asend(msg_t msg, pid_t dest)&lt;br /&gt;
  msg_t arecv(pid_t sender)&lt;br /&gt;
Nota: sia il servizio dato (non fifo) sia quello da implementare (fifo) consentono la ricezione solo da mittente specificato&lt;br /&gt;
(non supportano ANY/*).&lt;br /&gt;
&lt;br /&gt;
=== Soluzione proposta 1 ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void nfasend(msg_t msg, pid_t dest);&lt;br /&gt;
msg_t nfarecv(pid_t sender);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// array di grandezza di massimi numero di processi, inizializzato a 0&lt;br /&gt;
// utilizzato per contare il numero di messaggi inviati a un certo processo.&lt;br /&gt;
int num_sender[MAX_PROC];&lt;br /&gt;
&lt;br /&gt;
//RICORDA che ogni sender ha il suo num_sender[...]&lt;br /&gt;
&lt;br /&gt;
void asend(msg_t msg, pid_t dest) {&lt;br /&gt;
	src = getpid();&lt;br /&gt;
	nfasend(&amp;lt;msg, num_send[dest]&amp;gt;, dest);&lt;br /&gt;
	num_sender[dest]++;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// molto simile a num_sender, ma è utilizzato per contare il numero di messaggi ricevuti, in ordine.&lt;br /&gt;
int num_receiver[MAX_PROC];&lt;br /&gt;
// array heap ordinato sul int (per ogni heap in cima c'è il messaggio col minimo int).&lt;br /&gt;
min_heap&amp;lt;msg, int&amp;gt; messages[MAX_PROC];&lt;br /&gt;
&lt;br /&gt;
//RICORDA che ogni receiver ha il suo proprio num_receiver[...] e messages[...]&lt;br /&gt;
&lt;br /&gt;
msg_t arecv(pid_t sender) {&lt;br /&gt;
	p = getpid();&lt;br /&gt;
	&lt;br /&gt;
	if (messages[sender].size() &amp;gt; 0 &amp;amp;&amp;amp; messages[sender].top() == num_receiver[sender]) {&lt;br /&gt;
		(msg, num_mess) = messages[sender].removeTop();&lt;br /&gt;
		num_receiver[sender]++;&lt;br /&gt;
		return msg;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	(msg, num_mess) = nfarecv(sender);&lt;br /&gt;
&lt;br /&gt;
	while (num_mess != num_receiver[sender]) {&lt;br /&gt;
		messages[sender].insert(msg, num_mess);&lt;br /&gt;
		(msg, num_mess) = nfarecv(sender);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	num_receiver[sender]++;&lt;br /&gt;
	return msg;	&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Prova 2022/02/14 =&lt;br /&gt;
&lt;br /&gt;
== Esercizio c1 ==&lt;br /&gt;
Scrivere il monitor semdata che implementi un semaforo con dato. Questa astrazione prevede due operazioni:&lt;br /&gt;
&lt;br /&gt;
 datatype dP(void);&lt;br /&gt;
 void dV(datatype data);&lt;br /&gt;
&lt;br /&gt;
Non è previsto assegmento di valore iniziale nel costruttore, l'invariante è lo stesso dei semafori (con init = 0): ndP &amp;lt;=&lt;br /&gt;
ndV (dove ndP e ndV rappresentano rispettivamente il numero di operazioni dP e dV completate. I dati passati come&lt;br /&gt;
parametro alla dV devono essere memorizzati in ordine LIFO. L'operazione nP restituisce il valore più recente fra quelli&lt;br /&gt;
memorizzati (e lo cancella dalla struttura dati).&lt;br /&gt;
&lt;br /&gt;
=== Proposta di soluzione 1 ===&lt;br /&gt;
* Proposta da [[User:Flecart|Flecart]] ([[User talk:Flecart|talk]]) 12:06, 16 January 2023 (CET)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
class semdata {&lt;br /&gt;
&lt;br /&gt;
stack&amp;lt;datatype&amp;gt; pila;&lt;br /&gt;
condition p_waiting;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
semdata() {&lt;br /&gt;
	pila = stack();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
datatype dp(void) {&lt;br /&gt;
	if (pila.len() &amp;lt;= 0) {&lt;br /&gt;
		p_waiting.wait();&lt;br /&gt;
	}	&lt;br /&gt;
&lt;br /&gt;
	return pila.pop();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void dV(datatype data) {&lt;br /&gt;
	pila.push(data);&lt;br /&gt;
	p_waiting.signal();&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;
= Prova 2022/01/17 =&lt;br /&gt;
&lt;br /&gt;
== Esercizio c1 ==&lt;br /&gt;
&lt;br /&gt;
Scrivere il monitor multibuf che implementi un buffer limitato (MAX elementi) di oggetti di tipo T che&lt;br /&gt;
implementi le seguenti procedure entry:&lt;br /&gt;
  void add(int n, T objexts[]);&lt;br /&gt;
  void get(int n, T objects[]);&lt;br /&gt;
La funzione add deve aggiungere al buffer gli n oggetti passati col parametro objects. La funzione get deve predere&lt;br /&gt;
dal buffer in modalità FIFO i primi n elementi presenti nel buffer e copiarli negli elementi del vettore objects.&lt;br /&gt;
Entrambe le funzioni devono attendere che vi siano le condizioni per poter essere completate: che ci siano n elementi&lt;br /&gt;
liberi per la add, che ci siano n elementi nel buffer per la get. Non sono ammesse esecuzioni parziali: mentre attendono&lt;br /&gt;
le rispettive condizioni nessun elemento può essere aggiunto o rimosso dal buffer.&lt;br /&gt;
La definizione del problema C.1 presenta casi di possibile deadlock?&lt;br /&gt;
&lt;br /&gt;
=== Soluzione proposta 1 ===&lt;br /&gt;
&lt;br /&gt;
* Proposta [[User:Flecart|Flecart]] ([[User talk:Flecart|talk]]) 12:41, 16 January 2023 (CET)&lt;br /&gt;
&lt;br /&gt;
Una situazione di deadlock è quando un add non ha abbastanza per inserire, e get non ha abbastanza da prendere. Se non utilizzo la coda come ho fatto così&lt;br /&gt;
rischio starvation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
class multibuf {&lt;br /&gt;
	&lt;br /&gt;
T buffer[MAX];&lt;br /&gt;
int i, j;&lt;br /&gt;
int free;&lt;br /&gt;
queue&amp;lt;int,cond&amp;gt; add_queue;&lt;br /&gt;
&lt;br /&gt;
queue&amp;lt;int,cond&amp;gt; get_queue;&lt;br /&gt;
&lt;br /&gt;
multibuf {&lt;br /&gt;
	i = j = 0;&lt;br /&gt;
	free = MAX;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void add(int n, T objects[]) {&lt;br /&gt;
	if (add_queue.size() &amp;gt; 0 || free &amp;lt; n) {&lt;br /&gt;
		condition c = new condition();&lt;br /&gt;
		add_queue.enqueue(n, c);&lt;br /&gt;
		c.wait();&lt;br /&gt;
		free(c);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	for (int k = j; k != (j + n) % MAX; k = (k + 1) % MAX) {&lt;br /&gt;
		int other_idx = (k - i) &amp;lt; 0 ? k + MAX - i : k - i;&lt;br /&gt;
		buffer[k] = objects[other_idx];&lt;br /&gt;
	}&lt;br /&gt;
	free -= n;&lt;br /&gt;
	j = (j + n) % MAX;&lt;br /&gt;
		&lt;br /&gt;
	while (get_queue.size() &amp;gt; 0 &amp;amp;&amp;amp; get_queue.front() &amp;lt;= MAX - free) {&lt;br /&gt;
		n, cond = get_queue.dequeue();&lt;br /&gt;
		cond.signal();&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void get(int n, T objects[]) {&lt;br /&gt;
	if (get_queue.size() &amp;gt; 0 || MAX - free &amp;lt; n) {&lt;br /&gt;
		condition c = new condition();&lt;br /&gt;
		get_queue.enqueue(n, c);&lt;br /&gt;
		c.wait();&lt;br /&gt;
		free(c);&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	for (int k = i; k != (i + n) % MAX; k = (k + 1) % MAX) {&lt;br /&gt;
		int other_idx = (k - i) &amp;lt; 0 ? k + MAX - i : k - i;&lt;br /&gt;
		objects[other_idx] = buffer[k];&lt;br /&gt;
	}&lt;br /&gt;
	free += n;&lt;br /&gt;
	i = (i + n) % MAX;&lt;br /&gt;
&lt;br /&gt;
	while (add_queue.size() &amp;gt; 0 &amp;amp;&amp;amp; add_queue.front() &amp;lt;= free) {&lt;br /&gt;
		n, cond = add_queue.dequeue();&lt;br /&gt;
		cond.signal();&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
} // multibuf&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Esercizio c2 ==&lt;br /&gt;
Un servizio di message passing sincrono senza selezione del mittente prevede una API con due funzioni:&lt;br /&gt;
  sasend(msg_t msg, pid dest);&lt;br /&gt;
  msg_t sarecv(void);&lt;br /&gt;
La funzione sarecv restituisce il primo messaggio ricevuto da qualsiasi mittente ed è bloccante se non ci sono&lt;br /&gt;
messaggi pendenti. la funzione sasend si blocca fino a quando il messaggio msg non viene ricevuto dal processo dest.&lt;br /&gt;
Dato quindi un servizio di message passing sincrono senza selezione del mittente implementare un servizio di&lt;br /&gt;
message passing sincrono (standard, quello definito nel corso) senza fare uso di processi server. &lt;br /&gt;
&lt;br /&gt;
=== Soluzione proposta 1 (da controllare) ===&lt;br /&gt;
* proposta da [[User:Flecart|Flecart]] ([[User talk:Flecart|talk]]) 18:25, 16 January 2023 (CET) &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
ssend(msg_t msg, pid dest) {&lt;br /&gt;
	sasend(&amp;lt;msg, getpid()&amp;gt;, dest);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// variabili interne di srecv&lt;br /&gt;
queue&amp;lt;msg_t&amp;gt; msgs[MAX_PROC];&lt;br /&gt;
&lt;br /&gt;
// suppongo non ci sia il caso in cui sender = ANY.&lt;br /&gt;
// nel caso ci fosse la necessità, si dovrebbe creare una altra struttura di dati&lt;br /&gt;
// che ordini globalmente il messaggio che sia arrivato prima.&lt;br /&gt;
msg_t srecv(pid sender) {&lt;br /&gt;
	if (msgs[sender].len() &amp;gt; 0) {&lt;br /&gt;
		return msgs[sender].dequeue();&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	while (true) {&lt;br /&gt;
		&amp;lt;msg, pid&amp;gt; = sarecv();&lt;br /&gt;
		if (pid == sender) {&lt;br /&gt;
			return msgs[pid].dequeue();&lt;br /&gt;
		} else {&lt;br /&gt;
			msgs[pid].enqueue(msg);&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;
=== Soluzione proposta 1 (da controllare) ===&lt;br /&gt;
&lt;br /&gt;
proposta da [[User:Flecart|Flecart Friend]] 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;
// mem è condivisa tra ssend e srecv di ogni processo&lt;br /&gt;
// essendo che un processo può solo mandare o ricevere alla volta&lt;br /&gt;
// non abbiamo bisogno di cs&lt;br /&gt;
&lt;br /&gt;
// inizializzati tutti a NULL&lt;br /&gt;
msg_t mem[MAXPID];&lt;br /&gt;
// in mem ci basta un messaggio per PID perchè un pid può aver mandato al&lt;br /&gt;
// massimo un messaggio essendo che sono bloccanti la send e la recive&lt;br /&gt;
&lt;br /&gt;
void ssend(msg_t msg, pid dest) {&lt;br /&gt;
  sasend(&amp;lt;getpid(),msg&amp;gt;,dest);&lt;br /&gt;
  while(true){&lt;br /&gt;
    &amp;lt;form_c,msg&amp;gt;=sarecv();&lt;br /&gt;
    // dovrebbe essere ovvio che se è from c allora il msg dovrebbe essere un&lt;br /&gt;
    // ack perchè se c avesse mandato un messaggio diverso vorrebbe dire che&lt;br /&gt;
    // sta facendo una send e se i due processi si fanno una send allora c'è&lt;br /&gt;
    // deadhlock&lt;br /&gt;
    if(from_c == dest &amp;amp;&amp;amp; msg == ACK){&lt;br /&gt;
      break;&lt;br /&gt;
    }else{&lt;br /&gt;
      mem[from_c]=msg;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
msg_t srecv(pid from) {&lt;br /&gt;
  if(mem[from]==NULL){&lt;br /&gt;
    ssend(ACK,from);&lt;br /&gt;
    return mem.pop();&lt;br /&gt;
  }&lt;br /&gt;
  while(true){&lt;br /&gt;
    &amp;lt;form_c,msg&amp;gt;=sarecv();&lt;br /&gt;
    if(from_c==from){&lt;br /&gt;
      ssend(ACK,from);&lt;br /&gt;
      return msg;&lt;br /&gt;
    }else{&lt;br /&gt;
      mem[from_c].push(msg);&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Gio</name></author>
	</entry>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=Prove_scritte_2022&amp;diff=2910</id>
		<title>Prove scritte 2022</title>
		<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php?title=Prove_scritte_2022&amp;diff=2910"/>
		<updated>2023-01-16T17:35:28Z</updated>

		<summary type="html">&lt;p&gt;Gio: /* Soluzione proposta 1 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Prova 2022/09/06 =&lt;br /&gt;
&lt;br /&gt;
== Esercizio c1 == &lt;br /&gt;
&lt;br /&gt;
Esercizio c.1: I bit di un numero intero rappresentano condizioni di un sistema. Se lo stato attuale è 6 (0110) vuole dire&lt;br /&gt;
che attualmente sono vere le condizioni 2 (0010) e 4 (0100).&lt;br /&gt;
Scrivere un monitor bitcond che fornisca le seguenti procedure entry:&lt;br /&gt;
void set(int bit2set); accende nello stato attuale i bit di bit2set&lt;br /&gt;
void unset(int bit2unset) spegne nello stato attuale i bit di bit2unset&lt;br /&gt;
void statuswait(int bit2wait) attende che lo stato attuale soddisfi tutti le condizioni indicate in bit2wait (cioè&lt;br /&gt;
che tutti i bit in bit2wait siano accesi nello stato attuale).&lt;br /&gt;
Le richieste statuswait devono essere servite in ordine FIFO (cioè un processo anche se sono presenti tutte le&lt;br /&gt;
condizioni necessarie deve attendere se un processo che ha chiamato statuswait prima è in attesa).&lt;br /&gt;
Lo stato iniziale è zero (nessuna risorsa disponibile)&lt;br /&gt;
&lt;br /&gt;
=== Soluzione proposta 1 ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class bitcond{&lt;br /&gt;
  int bitmap;&lt;br /&gt;
  int lastBitmask;&lt;br /&gt;
  int has=0;&lt;br /&gt;
  &lt;br /&gt;
  condition waiting;&lt;br /&gt;
  condition c;&lt;br /&gt;
&lt;br /&gt;
  void set(int i){&lt;br /&gt;
    bitmap|=i; &lt;br /&gt;
      if(bitmap&amp;amp;lastBitmask == bitmap) c.signal();&lt;br /&gt;
  }&lt;br /&gt;
  void unset(int i){&lt;br /&gt;
    bitmap&amp;amp;=~i; &lt;br /&gt;
  }&lt;br /&gt;
  void statuswait(int i){&lt;br /&gt;
    has++; &lt;br /&gt;
    if(has&amp;gt;1){&lt;br /&gt;
      waiting.wait();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if(!(bitmap&amp;amp;i==i)){&lt;br /&gt;
      lastBitmask=i;&lt;br /&gt;
      c.wait();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    waiting.signal();&lt;br /&gt;
    has--;&lt;br /&gt;
  }&lt;br /&gt;
  bitcond(){&lt;br /&gt;
    bitmap = 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;
=== Soluzione proposta 2 ===&lt;br /&gt;
Proposta da [[User:Flecart|Flecart]] ([[User talk:Flecart|talk]]) 12:06, 14 January 2023 (CET)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
const int int_size = 32;&lt;br /&gt;
&lt;br /&gt;
class monitor {&lt;br /&gt;
    int value;&lt;br /&gt;
    condition bitset[int_size];&lt;br /&gt;
&lt;br /&gt;
    int numstatuswaiting;&lt;br /&gt;
    condition waiting;&lt;br /&gt;
    &lt;br /&gt;
    monitor() {&lt;br /&gt;
        value = 0;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    /// guarda se il bit n-significativo è settato in from&lt;br /&gt;
    bool nbit(int from, int n) {&lt;br /&gt;
        return (from &amp;amp; (1 &amp;lt;&amp;lt; n)) != 0&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void entry set(int bit2set) {&lt;br /&gt;
        value |= bit2set;&lt;br /&gt;
&lt;br /&gt;
        for (int i = 0; i &amp;lt; 32; i++) {&lt;br /&gt;
            if (nbit(value, i))&lt;br /&gt;
                bitset[i].signal();&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void entry statuswait(int bit2wait) {&lt;br /&gt;
        // in questo modo solamente un singolo processo è dentro ad aspettare&lt;br /&gt;
        // che tutte le condizioni siano rispettate&lt;br /&gt;
        if (numstatuswaiting &amp;gt; 0)&lt;br /&gt;
            waiting.wait();&lt;br /&gt;
        &lt;br /&gt;
        numstatuswaiting++;&lt;br /&gt;
        int i = 0;&lt;br /&gt;
        while(i &amp;lt; 32) {&lt;br /&gt;
            if (nbit(bit2wait, i) &amp;amp;&amp;amp; !nbit(value, i)) {&lt;br /&gt;
                bitset[i].wait();&lt;br /&gt;
&lt;br /&gt;
                // ricomincia a guardare tutti i bit da zero, perché&lt;br /&gt;
                // nel frattempo potrebbero essere cambiati.&lt;br /&gt;
                // -1 così con l'istruzione successiva diventa 0&lt;br /&gt;
                i = -1; &lt;br /&gt;
            }&lt;br /&gt;
            i++;&lt;br /&gt;
        }&lt;br /&gt;
        &lt;br /&gt;
        numstatuswaiting--;&lt;br /&gt;
        waiting.signal();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Soluzione proposta 3 ===&lt;br /&gt;
Proposta da [[User:Flecart|Flecart]] ([[User talk:Flecart|talk]]) 12:07, 14 January 2023 (CET)&lt;br /&gt;
questa è la soluzione più brutta, ma dovrebbe andare.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
const int int_size = 32;&lt;br /&gt;
&lt;br /&gt;
class monitor {&lt;br /&gt;
    int value;&lt;br /&gt;
    condition status;&lt;br /&gt;
&lt;br /&gt;
    int numstatuswaiting;&lt;br /&gt;
    condition waiting;&lt;br /&gt;
    &lt;br /&gt;
    monitor() {&lt;br /&gt;
        value = 0;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    /// guarda se il bit n-significativo è settato in from&lt;br /&gt;
    bool nbit(int from, int n) {&lt;br /&gt;
        return (from &amp;amp; (1 &amp;lt;&amp;lt; n)) != 0&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void entry set(int bit2set) {&lt;br /&gt;
        value |= bit2set;&lt;br /&gt;
        status.signal();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    void entry unset(int bit2unset) {&lt;br /&gt;
        value = (value &amp;amp; ~bit2unset);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void entry statuswait(int bit2wait) {&lt;br /&gt;
        // in questo modo solamente un singolo processo è dentro ad aspettare&lt;br /&gt;
        // che tutte le condizioni siano rispettate&lt;br /&gt;
        if (numstatuswaiting &amp;gt; 0)&lt;br /&gt;
            waiting.wait();&lt;br /&gt;
        &lt;br /&gt;
        numstatuswaiting++;&lt;br /&gt;
        while(true) {&lt;br /&gt;
            if ((value &amp;amp; bit2wait) == bit2wait) &lt;br /&gt;
                break;&lt;br /&gt;
            else &lt;br /&gt;
                status.wait();&lt;br /&gt;
        }&lt;br /&gt;
        numstatuswaiting--;&lt;br /&gt;
        waiting.signal();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Prova 2022/06/21 =&lt;br /&gt;
&lt;br /&gt;
== Esercizio c1 ==&lt;br /&gt;
Scrivere il monitor collocamento:&lt;br /&gt;
  void cercolavoro(char *nome, char *skill)&lt;br /&gt;
  void char *assumo(char * skill)&lt;br /&gt;
Quando un processo chiama la cercolavoro si mette in attesa di una richiesta di lavoro e rimane bloccato nel monitor&lt;br /&gt;
fino a che non è stato assunto. Nella cercolavoro viene indicato il nome dell'aspirante lavoratore la sua capacità (skill).&lt;br /&gt;
Un datore di lavoro con necessità di personale chiama la assumo specificando la capacità richiesta. Se c'è in attesa&lt;br /&gt;
almeno un aspirante lavoratore con quella specifica capacità (uguale valore di skill), il datore di lavoro riceve il nome del&lt;br /&gt;
nuovo dipendente ed entrambi i processi escono dal monitor. Nel caso non ci siano richieste compatibili il datore di&lt;br /&gt;
lavoro si blocca nel monitor attendendo un lavoratore con la capacità cercata. Quando arriva il lavoratore che soddisfa&lt;br /&gt;
le richieste si sbloccano entrambi i processi lavoratore e datore di lavoro. La assumo restituisce in ogni caso il nome del&lt;br /&gt;
dipendente da assumere.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Soluzione proposta === &lt;br /&gt;
&lt;br /&gt;
Soluzione proposta da [[User:Flecart|Flecart]] ([[User talk:Flecart|talk]]) 12:08, 14 January 2023 (CET)&lt;br /&gt;
&lt;br /&gt;
ci potrebbe essere un errore in quanto non è specificato il comportamento della struttura dati in alcune situazioni&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
class collocamento{&lt;br /&gt;
&lt;br /&gt;
set&amp;lt;char *, condition&amp;gt; richieste;  // chi assume cerca questa skill&lt;br /&gt;
set&amp;lt;char *, char *, condition&amp;gt; ricerche; // nome e skill di chi cerca&lt;br /&gt;
&lt;br /&gt;
char *last_nome;&lt;br /&gt;
&lt;br /&gt;
collocamento {&lt;br /&gt;
	last_nome = NULL;&lt;br /&gt;
	richieste = set();&lt;br /&gt;
	ricerche = set();	&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void cercolavoro(char *nome, char *skill) {&lt;br /&gt;
	datore = richieste.find(skill);  // cerca valutando la prima come chiave&lt;br /&gt;
	if (datore != NULL) {&lt;br /&gt;
		&amp;lt;skill, cond&amp;gt; = datore;&lt;br /&gt;
		richieste.remove(datore);&lt;br /&gt;
		last_nome = nome;&lt;br /&gt;
		cond.signal();		&lt;br /&gt;
	} else {&lt;br /&gt;
		condition c = new condition();&lt;br /&gt;
		ricerche.insert(nome, skill, c);&lt;br /&gt;
		c.wait();&lt;br /&gt;
		free(c);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void char *assumo(char * skill){&lt;br /&gt;
	lavoratore = ricerche.find2(skill); // cerca valutando la seconda come chiave.&lt;br /&gt;
	if (lavoratore != NULL) {&lt;br /&gt;
		&amp;lt;nome, skill, cond&amp;gt; = lavoratore;&lt;br /&gt;
		ricerche.remove(lavoratore);&lt;br /&gt;
		cond.signal();&lt;br /&gt;
		last_nome = nome;&lt;br /&gt;
	} else {&lt;br /&gt;
		condition c = new condition();&lt;br /&gt;
		richieste.insert(skill, c);&lt;br /&gt;
		c.wait();&lt;br /&gt;
		free(c);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	return last_nome;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
}// class collocamento&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Soluzione proposta === &lt;br /&gt;
&lt;br /&gt;
Soluzione proposta da [[User:Flecart|Flecart Frend]], regalo la proprietà intellettuale di questa soluzione a flecart.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
class workdisptcher{&lt;br /&gt;
&lt;br /&gt;
  // la multi map può storare più di un valore per una chiave&lt;br /&gt;
  // quando viene richiesta una particolare chiave da in maniera LIFO&lt;br /&gt;
  // il risultato&lt;br /&gt;
  // es:&lt;br /&gt;
  // multi_map&amp;lt;char *,int&amp;gt; lavoratori;&lt;br /&gt;
  // lavoratori.insert(&amp;quot;prova&amp;quot;,2);&lt;br /&gt;
  // lavoratori.insert(&amp;quot;prova&amp;quot;,1);&lt;br /&gt;
  // lavoratori.get(&amp;quot;prova&amp;quot;) == 2&lt;br /&gt;
  // lavoratori.remove(&amp;quot;prova&amp;quot;)&lt;br /&gt;
  // lavoratori.get(&amp;quot;prova&amp;quot;) == 1&lt;br /&gt;
  multi_map&amp;lt;char *,(char*,cond)&amp;gt; lavoratori;&lt;br /&gt;
  multi_map&amp;lt;char *,cond&amp;gt; posti_aperti;&lt;br /&gt;
  char* buffer_name;&lt;br /&gt;
  void cercolavoro(char *nome, char *skill){&lt;br /&gt;
    if(posti_aperti.find(skill)){&lt;br /&gt;
      auto entry =posti_aperti.get(skill);&lt;br /&gt;
      posti_aperti.remove(entry);&lt;br /&gt;
      buffer_name=name;&lt;br /&gt;
      entry.1.signal();&lt;br /&gt;
    }else{&lt;br /&gt;
      cond c= new cond();&lt;br /&gt;
      lavoratori.insert(skill,(nome,c)) ;&lt;br /&gt;
      c.wait();&lt;br /&gt;
      free(c);&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  void char *assumo(char * skill){&lt;br /&gt;
    if(lavoratori.find(skill)){&lt;br /&gt;
      auto entry =lavoratori.get(skill);&lt;br /&gt;
      posti_aperti.remove(entry);&lt;br /&gt;
      auto [nome,cnd] = entry.1;&lt;br /&gt;
      cond.signal();&lt;br /&gt;
      return nome;&lt;br /&gt;
    }else{&lt;br /&gt;
      cond c= new cond();&lt;br /&gt;
      posti_aperti.insert(skill,c) ;&lt;br /&gt;
      c.wait();&lt;br /&gt;
      free(c);&lt;br /&gt;
      return buffer_name;&lt;br /&gt;
    }&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 c2 ==&lt;br /&gt;
Un servizio viene fornito in modalità client-server usando message passing asincrono.&lt;br /&gt;
Al fine di aumentare l'efficienza si decide di usare molti server e un processo dispatcher in grado di distribuire le&lt;br /&gt;
richieste agli N server. Quando un processo server è libero riceve dal dispatcher la prossima richiesta da elaborare:&lt;br /&gt;
codice di ogni client (tanti!): .....&lt;br /&gt;
  asend(&amp;lt;getpid(), request&amp;gt;, dispatcher)&lt;br /&gt;
  result = arecv(dispatcher)&lt;br /&gt;
&lt;br /&gt;
server process[i], i = 0, ..., N-1:&lt;br /&gt;
 request = arecv(dispatcher)&lt;br /&gt;
 result = compute(request)&lt;br /&gt;
 asend(&amp;lt;getpid(), result&amp;gt;, dispatcher)&lt;br /&gt;
Scrivere il processo dispatcher. (il dispatcher conosce i pid di tutti i server).&lt;br /&gt;
&lt;br /&gt;
=== Soluzione proposta (sbagliata) === &lt;br /&gt;
&lt;br /&gt;
Soluzione proposta da [https://so.v2.cs.unibo.it/wiki/index.php/User:Flecart Flecart] &lt;br /&gt;
&lt;br /&gt;
Questo esercizio è stato corretto tempo fa in classe dal professore, **non è completamente corretto** se si vuole provare a correggerlo alla fine dell'esercizio c'è scritto cos'è sbagliato.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
extern int N;&lt;br /&gt;
process dispatcher() {&lt;br /&gt;
    // indice che tiene conto a quale server dover mandare&lt;br /&gt;
    // per semplicità supponiamo che i server abbiano PID&lt;br /&gt;
    // da 0 a N - 1&lt;br /&gt;
    int i = 0; &lt;br /&gt;
&lt;br /&gt;
    // mappa server a pid del processo che lo ha richiesto.&lt;br /&gt;
    // chiave: pid del server&lt;br /&gt;
    // value: queue richiesta dispatchata al server in chiave&lt;br /&gt;
    map&amp;lt;int, queue&amp;lt;int&amp;gt;&amp;gt; mapper; &lt;br /&gt;
    while (true) {&lt;br /&gt;
        res = arecv(ANY);&lt;br /&gt;
        &lt;br /&gt;
        // in questa parte l'importante è sapere&lt;br /&gt;
        // se la richiesta proviene dal  server o da un altro&lt;br /&gt;
        // processo, ho assunto che la disambiguazione &lt;br /&gt;
        // fosse immediata, un altro modo per checkare questo&lt;br /&gt;
        // è vedere se il PID del messaggio rientri fra quelli&lt;br /&gt;
        // noti al dispatcher.&lt;br /&gt;
        if (&amp;lt;pid, request&amp;gt; = res) {&lt;br /&gt;
            mapper[i].enqueue(pid);&lt;br /&gt;
            asend(request, i /*il i-esimo server*/);&lt;br /&gt;
            i++;&lt;br /&gt;
            i %= N;&lt;br /&gt;
        } else if (&amp;lt;pid, response&amp;gt; = res) {&lt;br /&gt;
            requester_pid = mapper[pid].dequeue();&lt;br /&gt;
            asend(response, requester_pid);&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;
l'es è sbagliato perchè dovrei mandare ai server liberi, non a round-robin [[User:Flecart|Flecart]] ([[User talk:Flecart|talk]]) 15:52, 14 January 2023 (CET)&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:Gio Giovanni Spadaccini] &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
dispatcher{&lt;br /&gt;
  queue&amp;lt;&amp;lt;pid,request&amp;gt;&amp;gt; work;&lt;br /&gt;
  queue&amp;lt;pid&amp;gt; freeserver;&lt;br /&gt;
  map&amp;lt;pid,pid&amp;gt; map_server_to_client;&lt;br /&gt;
  while(true){&lt;br /&gt;
    &amp;lt;pid,message&amp;gt;=arecv(ANY);&lt;br /&gt;
    if pid in servers{&lt;br /&gt;
      client=map_server_to_client.get(pid);&lt;br /&gt;
      map_client_to_server.remove(pid);&lt;br /&gt;
      freeserver.push(pid);&lt;br /&gt;
      asend(&amp;lt;message&amp;gt;,client);&lt;br /&gt;
    }else{&lt;br /&gt;
      work.push(&amp;lt;pid,message&amp;gt;);&lt;br /&gt;
    }&lt;br /&gt;
    while !freeserver.empty() and !work.emtpy(){&lt;br /&gt;
      server_pid = freeserver.pop();&lt;br /&gt;
      &amp;lt;client,msg&amp;gt; = work.pop();&lt;br /&gt;
      map_server_to_client.insert(server,client);&lt;br /&gt;
      asend(msg,server_pid);&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Prova 2022/06/01 =&lt;br /&gt;
&lt;br /&gt;
== Esercizio c1 ==&lt;br /&gt;
&lt;br /&gt;
Scrivere il monitor delay che fornisce due procedure entry:&lt;br /&gt;
  int wait_tick(int nticks)&lt;br /&gt;
  void tick(void)&lt;br /&gt;
La procedure entry tick è pensata per essere richiamata periodicamente (es. ogni secondo o ora o giorno) da un&lt;br /&gt;
processo.&lt;br /&gt;
Quando un processo chiama la wait_tick deve attendere un numero di chiamate della tick pari al parametro nticks.&lt;br /&gt;
Per esempio se un processo chiama wait_tick(2) deve fermarsi e verrà riattivato alla seconda successiva chiamata di&lt;br /&gt;
tick.&lt;br /&gt;
La funzione wait_tick ha come valore di ritorno il numero di processi che erano bloccati al momento della tick che ha&lt;br /&gt;
sbloccato il chiamante.&lt;br /&gt;
Esempio: P chiama wait_tick(2) e si blocca. Q chiama wait_tick(3) e si blocca. T chiama tick() non succede nulla. R&lt;br /&gt;
chiama wait_tick(2) e si blocca. T chiama tick(), viene sbloccata la wait_tick di P e il valore ritornato è 3. T chiama&lt;br /&gt;
tick(), vengono sbloccate le wait_tick di Q e R e il valore ritornato per entrambi i processi è 2&lt;br /&gt;
&lt;br /&gt;
=== Soluzione proprosta 1 (da controllare) ===&lt;br /&gt;
Soluzione proposta 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;
class MonitorDelay {&lt;br /&gt;
    int curr_time;&lt;br /&gt;
    int waiting_num;&lt;br /&gt;
&lt;br /&gt;
    // min heap con il tempo di sblocco dei processi e la condizione su cui è fermato&lt;br /&gt;
    // il tempo di sblocco minore è messo in cima alla heap&lt;br /&gt;
    // la sintassi con pair è ispirata alla std::pair di c++&lt;br /&gt;
    heap&amp;lt;pair&amp;lt;int, condition&amp;gt;&amp;gt; waiting; &lt;br /&gt;
&lt;br /&gt;
    void init() {&lt;br /&gt;
        curr_time = 0;&lt;br /&gt;
        waiting = heap&amp;lt;pair&amp;lt;int, condition&amp;gt;&amp;gt;();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    int entry wait_tick(int nticks) {&lt;br /&gt;
        if (nticks &amp;lt;= 0) {&lt;br /&gt;
            return waiting.size();&lt;br /&gt;
        } else {&lt;br /&gt;
            condition c = new condition();&lt;br /&gt;
            waiting.insert(make_pair(nticks + curr_time, c));&lt;br /&gt;
            c.wait();&lt;br /&gt;
            free(c);&lt;br /&gt;
        }&lt;br /&gt;
        return waiting_num;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    void entry tick(void) {&lt;br /&gt;
        waiting_num = waiting.size();&lt;br /&gt;
        curr_time++;&lt;br /&gt;
&lt;br /&gt;
        while (waiting.head().first &amp;lt;= curr_time) {&lt;br /&gt;
            condition c = waiting.head().second;&lt;br /&gt;
            waiting.deleteHead();&lt;br /&gt;
            c.signal();&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Esercizio c2 ==&lt;br /&gt;
&lt;br /&gt;
=== Consegna ===&lt;br /&gt;
&lt;br /&gt;
Esercizio c.2: Un servizio di message passing asincrono non fifo (nfasend/nfarecv) consegna in tempo finito tutti i&lt;br /&gt;
messaggi spediti ma non è garantito che i messaggi vengano ricevuti nell'ordine nel quale sono stati spediti.&lt;br /&gt;
  void nfasend(msg_t msg, pid_t dest)&lt;br /&gt;
  msg_t nfarecv(pid_t sender)&lt;br /&gt;
Dato un servizio di message passing asincrono non fifo scrivere una libreria che implementi il servizio di message&lt;br /&gt;
passing asincrono fifo:&lt;br /&gt;
  void asend(msg_t msg, pid_t dest)&lt;br /&gt;
  msg_t arecv(pid_t sender)&lt;br /&gt;
Nota: sia il servizio dato (non fifo) sia quello da implementare (fifo) consentono la ricezione solo da mittente specificato&lt;br /&gt;
(non supportano ANY/*).&lt;br /&gt;
&lt;br /&gt;
=== Soluzione proposta 1 ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void nfasend(msg_t msg, pid_t dest);&lt;br /&gt;
msg_t nfarecv(pid_t sender);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// array di grandezza di massimi numero di processi, inizializzato a 0&lt;br /&gt;
// utilizzato per contare il numero di messaggi inviati a un certo processo.&lt;br /&gt;
int num_sender[MAX_PROC];&lt;br /&gt;
&lt;br /&gt;
//RICORDA che ogni sender ha il suo num_sender[...]&lt;br /&gt;
&lt;br /&gt;
void asend(msg_t msg, pid_t dest) {&lt;br /&gt;
	src = getpid();&lt;br /&gt;
	nfasend(&amp;lt;msg, num_send[dest]&amp;gt;, dest);&lt;br /&gt;
	num_sender[dest]++;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// molto simile a num_sender, ma è utilizzato per contare il numero di messaggi ricevuti, in ordine.&lt;br /&gt;
int num_receiver[MAX_PROC];&lt;br /&gt;
// array heap ordinato sul int (per ogni heap in cima c'è il messaggio col minimo int).&lt;br /&gt;
min_heap&amp;lt;msg, int&amp;gt; messages[MAX_PROC];&lt;br /&gt;
&lt;br /&gt;
//RICORDA che ogni receiver ha il suo proprio num_receiver[...] e messages[...]&lt;br /&gt;
&lt;br /&gt;
msg_t arecv(pid_t sender) {&lt;br /&gt;
	p = getpid();&lt;br /&gt;
	&lt;br /&gt;
	if (messages[sender].size() &amp;gt; 0 &amp;amp;&amp;amp; messages[sender].top() == num_receiver[sender]) {&lt;br /&gt;
		(msg, num_mess) = messages[sender].removeTop();&lt;br /&gt;
		num_receiver[sender]++;&lt;br /&gt;
		return msg;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	(msg, num_mess) = nfarecv(sender);&lt;br /&gt;
&lt;br /&gt;
	while (num_mess != num_receiver[sender]) {&lt;br /&gt;
		messages[sender].insert(msg, num_mess);&lt;br /&gt;
		(msg, num_mess) = nfarecv(sender);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	num_receiver[sender]++;&lt;br /&gt;
	return msg;	&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Prova 2022/02/14 =&lt;br /&gt;
&lt;br /&gt;
== Esercizio c1 ==&lt;br /&gt;
Scrivere il monitor semdata che implementi un semaforo con dato. Questa astrazione prevede due operazioni:&lt;br /&gt;
&lt;br /&gt;
 datatype dP(void);&lt;br /&gt;
 void dV(datatype data);&lt;br /&gt;
&lt;br /&gt;
Non è previsto assegmento di valore iniziale nel costruttore, l'invariante è lo stesso dei semafori (con init = 0): ndP &amp;lt;=&lt;br /&gt;
ndV (dove ndP e ndV rappresentano rispettivamente il numero di operazioni dP e dV completate. I dati passati come&lt;br /&gt;
parametro alla dV devono essere memorizzati in ordine LIFO. L'operazione nP restituisce il valore più recente fra quelli&lt;br /&gt;
memorizzati (e lo cancella dalla struttura dati).&lt;br /&gt;
&lt;br /&gt;
=== Proposta di soluzione 1 ===&lt;br /&gt;
* Proposta da [[User:Flecart|Flecart]] ([[User talk:Flecart|talk]]) 12:06, 16 January 2023 (CET)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
class semdata {&lt;br /&gt;
&lt;br /&gt;
stack&amp;lt;datatype&amp;gt; pila;&lt;br /&gt;
condition p_waiting;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
semdata() {&lt;br /&gt;
	pila = stack();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
datatype dp(void) {&lt;br /&gt;
	if (pila.len() &amp;lt;= 0) {&lt;br /&gt;
		p_waiting.wait();&lt;br /&gt;
	}	&lt;br /&gt;
&lt;br /&gt;
	return pila.pop();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void dV(datatype data) {&lt;br /&gt;
	pila.push(data);&lt;br /&gt;
	p_waiting.signal();&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;
= Prova 2022/01/17 =&lt;br /&gt;
&lt;br /&gt;
== Esercizio c1 ==&lt;br /&gt;
&lt;br /&gt;
Scrivere il monitor multibuf che implementi un buffer limitato (MAX elementi) di oggetti di tipo T che&lt;br /&gt;
implementi le seguenti procedure entry:&lt;br /&gt;
  void add(int n, T objexts[]);&lt;br /&gt;
  void get(int n, T objects[]);&lt;br /&gt;
La funzione add deve aggiungere al buffer gli n oggetti passati col parametro objects. La funzione get deve predere&lt;br /&gt;
dal buffer in modalità FIFO i primi n elementi presenti nel buffer e copiarli negli elementi del vettore objects.&lt;br /&gt;
Entrambe le funzioni devono attendere che vi siano le condizioni per poter essere completate: che ci siano n elementi&lt;br /&gt;
liberi per la add, che ci siano n elementi nel buffer per la get. Non sono ammesse esecuzioni parziali: mentre attendono&lt;br /&gt;
le rispettive condizioni nessun elemento può essere aggiunto o rimosso dal buffer.&lt;br /&gt;
La definizione del problema C.1 presenta casi di possibile deadlock?&lt;br /&gt;
&lt;br /&gt;
=== Soluzione proposta 1 ===&lt;br /&gt;
&lt;br /&gt;
* Proposta [[User:Flecart|Flecart]] ([[User talk:Flecart|talk]]) 12:41, 16 January 2023 (CET)&lt;br /&gt;
&lt;br /&gt;
Una situazione di deadlock è quando un add non ha abbastanza per inserire, e get non ha abbastanza da prendere. Se non utilizzo la coda come ho fatto così&lt;br /&gt;
rischio starvation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
class multibuf {&lt;br /&gt;
	&lt;br /&gt;
T buffer[MAX];&lt;br /&gt;
int i, j;&lt;br /&gt;
int free;&lt;br /&gt;
queue&amp;lt;int,cond&amp;gt; add_queue;&lt;br /&gt;
&lt;br /&gt;
queue&amp;lt;int,cond&amp;gt; get_queue;&lt;br /&gt;
&lt;br /&gt;
multibuf {&lt;br /&gt;
	i = j = 0;&lt;br /&gt;
	free = MAX;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void add(int n, T objects[]) {&lt;br /&gt;
	if (add_queue.size() &amp;gt; 0 || free &amp;lt; n) {&lt;br /&gt;
		condition c = new condition();&lt;br /&gt;
		add_queue.enqueue(n, c);&lt;br /&gt;
		c.wait();&lt;br /&gt;
		free(c);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	for (int k = j; k != (j + n) % MAX; k = (k + 1) % MAX) {&lt;br /&gt;
		int other_idx = (k - i) &amp;lt; 0 ? k + MAX - i : k - i;&lt;br /&gt;
		buffer[k] = objects[other_idx];&lt;br /&gt;
	}&lt;br /&gt;
	free -= n;&lt;br /&gt;
	j = (j + n) % MAX;&lt;br /&gt;
		&lt;br /&gt;
	while (get_queue.size() &amp;gt; 0 &amp;amp;&amp;amp; get_queue.front() &amp;lt;= MAX - free) {&lt;br /&gt;
		n, cond = get_queue.dequeue();&lt;br /&gt;
		cond.signal();&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void get(int n, T objects[]) {&lt;br /&gt;
	if (get_queue.size() &amp;gt; 0 || MAX - free &amp;lt; n) {&lt;br /&gt;
		condition c = new condition();&lt;br /&gt;
		get_queue.enqueue(n, c);&lt;br /&gt;
		c.wait();&lt;br /&gt;
		free(c);&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	for (int k = i; k != (i + n) % MAX; k = (k + 1) % MAX) {&lt;br /&gt;
		int other_idx = (k - i) &amp;lt; 0 ? k + MAX - i : k - i;&lt;br /&gt;
		objects[other_idx] = buffer[k];&lt;br /&gt;
	}&lt;br /&gt;
	free += n;&lt;br /&gt;
	i = (i + n) % MAX;&lt;br /&gt;
&lt;br /&gt;
	while (add_queue.size() &amp;gt; 0 &amp;amp;&amp;amp; add_queue.front() &amp;lt;= free) {&lt;br /&gt;
		n, cond = add_queue.dequeue();&lt;br /&gt;
		cond.signal();&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
} // multibuf&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Esercizio c2 ==&lt;br /&gt;
Un servizio di message passing sincrono senza selezione del mittente prevede una API con due funzioni:&lt;br /&gt;
  sasend(msg_t msg, pid dest);&lt;br /&gt;
  msg_t sarecv(void);&lt;br /&gt;
La funzione sarecv restituisce il primo messaggio ricevuto da qualsiasi mittente ed è bloccante se non ci sono&lt;br /&gt;
messaggi pendenti. la funzione sasend si blocca fino a quando il messaggio msg non viene ricevuto dal processo dest.&lt;br /&gt;
Dato quindi un servizio di message passing sincrono senza selezione del mittente implementare un servizio di&lt;br /&gt;
message passing sincrono (standard, quello definito nel corso) senza fare uso di processi server. &lt;br /&gt;
&lt;br /&gt;
=== Soluzione proposta 1 (da controllare) ===&lt;br /&gt;
* proposta da [[User:Flecart|Flecart]] ([[User talk:Flecart|talk]]) 18:25, 16 January 2023 (CET) &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
ssend(msg_t msg, pid dest) {&lt;br /&gt;
	sasend(&amp;lt;msg, getpid()&amp;gt;, dest);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// variabili interne di srecv&lt;br /&gt;
queue&amp;lt;msg_t&amp;gt; msgs[MAX_PROC];&lt;br /&gt;
&lt;br /&gt;
// suppongo non ci sia il caso in cui sender = ANY.&lt;br /&gt;
// nel caso ci fosse la necessità, si dovrebbe creare una altra struttura di dati&lt;br /&gt;
// che ordini globalmente il messaggio che sia arrivato prima.&lt;br /&gt;
msg_t srecv(pid sender) {&lt;br /&gt;
	if (msgs[sender].len() &amp;gt; 0) {&lt;br /&gt;
		return msgs[sender].dequeue();&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	while (true) {&lt;br /&gt;
		&amp;lt;msg, pid&amp;gt; = sarecv();&lt;br /&gt;
		if (pid == sender) {&lt;br /&gt;
			return msgs[pid].dequeue();&lt;br /&gt;
		} else {&lt;br /&gt;
			msgs[pid].enqueue(msg);&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Gio</name></author>
	</entry>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=Prove_scritte_2021&amp;diff=2905</id>
		<title>Prove scritte 2021</title>
		<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php?title=Prove_scritte_2021&amp;diff=2905"/>
		<updated>2023-01-16T16:45:24Z</updated>

		<summary type="html">&lt;p&gt;Gio: /* Soluzione proposta 1 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
= Prova 21/07/2021=&lt;br /&gt;
&lt;br /&gt;
== Es C1 (da correggere) == &lt;br /&gt;
&lt;br /&gt;
Soluzione proposta da [https://so.v2.cs.unibo.it/wiki/index.php/User:Flecart Flecart friend],regalo a flecart la proprietà intellettuale di questa soluzione&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
class node{&lt;br /&gt;
  node parent;&lt;br /&gt;
  sq sq1;&lt;br /&gt;
  cond c;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
class BinTree{&lt;br /&gt;
  vector&amp;lt;node&amp;gt; base;&lt;br /&gt;
  void create(int N){&lt;br /&gt;
    base=new vector&amp;lt;node&amp;gt;(2^N);&lt;br /&gt;
    for(int i=0;i&amp;lt;2^N;i++)&lt;br /&gt;
      base[i]=new node(null,0,new cond);&lt;br /&gt;
    for(int i=1;i&amp;lt;=N;i++){&lt;br /&gt;
      for(int j=0;j&amp;lt;2^(N-i);j++){&lt;br /&gt;
        get(j,i-1).parent=get(j+i,i-1).parent=new node(null,0,new cond);&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  node get(int i,int level){&lt;br /&gt;
    return get(base[i],level);&lt;br /&gt;
  }&lt;br /&gt;
  node get(node n,int level){&lt;br /&gt;
    if(level==0){&lt;br /&gt;
      return node;&lt;br /&gt;
    }&lt;br /&gt;
    return get(node.parent,level-1);&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class Torneo{&lt;br /&gt;
  BinTree bin(N);&lt;br /&gt;
  int forma[2^N];&lt;br /&gt;
  bool win;&lt;br /&gt;
&lt;br /&gt;
  bool gioca(int i,int turno,int forma){&lt;br /&gt;
    forma[i]=forma;&lt;br /&gt;
    if null==bin.get(i,turno).sq1{&lt;br /&gt;
      bin.get(i,turno).sq1=i;&lt;br /&gt;
      bin.get(i,turno).c.wait();&lt;br /&gt;
      return !win;&lt;br /&gt;
    }else{&lt;br /&gt;
      sq1= bin.get(i,turno).sq1;&lt;br /&gt;
      if(forma[sq1]==forma[i]){&lt;br /&gt;
        win=random();&lt;br /&gt;
      }else{&lt;br /&gt;
        win=forma[sq1]&amp;lt;forma[i];&lt;br /&gt;
      }&lt;br /&gt;
      bin.get(i,turno).signal();&lt;br /&gt;
    }&lt;br /&gt;
    return win;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Prova 2021/09/15 =&lt;br /&gt;
&lt;br /&gt;
== Esercizio C1 == &lt;br /&gt;
&lt;br /&gt;
=== Consegna === &lt;br /&gt;
Esercizio c.1: Scrivere il monitor alrv (at least rendez-vous) che fornisce una sola procedure entry:&lt;br /&gt;
procedure entry void at_least(int n)&lt;br /&gt;
Quando un processo chiama la funzione at_least vuol dire che vuole sincronizzarsi con un insieme di almeno n&lt;br /&gt;
processi (incluso il chiamante).&lt;br /&gt;
Esempi:&lt;br /&gt;
Se un processo chiama at_least(1) non si blocca.&lt;br /&gt;
Se il processo p chiama at_least(2) si blocca, se poi il processo q chiama at_least(2) oppure at_least(1) si&lt;br /&gt;
sbloccano sia p sia q (la richiesta di p è soddisfatta, ne aspettava almeno 2, p e q)&lt;br /&gt;
Se il processo p chiama at_least(2) si blocca, se poi il processo q chiama at_least(3) si blocca anch'esso perché&lt;br /&gt;
sebbene la richiesta di p possa essere soddisfatta, q non può ancora sbloccarsi: ci sono solo 2 processi in attesa mentre&lt;br /&gt;
q ne vuole 3. Un terzo processo che chiami at_least(x) con x=1,2,3 li sblocca tutti.&lt;br /&gt;
Hint: sia w[k ] il numero dei processi in attesa di essere in almeno k (quelli che hanno chiamato at_least(k) e non&lt;br /&gt;
hanno completato l'esecuzione della funzione). Sia s[n]=∑&lt;br /&gt;
k=1&lt;br /&gt;
n&lt;br /&gt;
w[k ] (rappresenta il numero di processi soddisfacibili:&lt;br /&gt;
e.g. se ci sono 4 processi in attesa, potrebbero essere soddisfatte le richieste dei processi che ne aspettano almeno 2,&lt;br /&gt;
almeno 3 o almeno 4). Preso, se esiste, il massimo indice m tale che s[m]≥m tutti i processi in attesa di essere in n,&lt;br /&gt;
per n≤m possono essere sbloccati.&lt;br /&gt;
&lt;br /&gt;
=== 1. Soluzione proposta ===&lt;br /&gt;
Soluzione proposta da [https://so.v2.cs.unibo.it/wiki/index.php/User:Flecart Flecart]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
extern int MAX;  // il massimo numero di attesa&lt;br /&gt;
monitor alrv {&lt;br /&gt;
	int w[MAX];&lt;br /&gt;
	int s[MAX];&lt;br /&gt;
	condition c[MAX];&lt;br /&gt;
&lt;br /&gt;
	init() {&lt;br /&gt;
		for (int i = 0; i &amp;lt; MAX; i++) {&lt;br /&gt;
			w[i] = s[i] = 0;&lt;br /&gt;
		}&lt;br /&gt;
	}	&lt;br /&gt;
&lt;br /&gt;
procedure entry void at_least(int n) {&lt;br /&gt;
	if (n &amp;gt;= MAX || n &amp;lt;= 0) raise error;&lt;br /&gt;
	&lt;br /&gt;
	int i;&lt;br /&gt;
	for (i = n; i &amp;lt; MAX; i++) s[i]++;&lt;br /&gt;
	&lt;br /&gt;
	for (i = MAX - 1; i &amp;gt; 0; i--) {&lt;br /&gt;
		if (s[i] &amp;gt;= i) break;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	if (i &amp;gt; 0) {&lt;br /&gt;
		for (int j = 0; j &amp;lt;= i; j++) {&lt;br /&gt;
			while (w[j] &amp;gt; 0) {&lt;br /&gt;
				c[j].signal();&lt;br /&gt;
				w[j]--;&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
		&lt;br /&gt;
		s[0] = 0;&lt;br /&gt;
		for (int i = 1; i &amp;lt; MAX; i++) {&lt;br /&gt;
			s[i] = w[i] + s[i - 1];&lt;br /&gt;
		}&lt;br /&gt;
	} else {&lt;br /&gt;
		w[n]++;&lt;br /&gt;
		c[n].wait();&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Soluzione proposta da [https://so.v2.cs.unibo.it/wiki/index.php/User:Flecart Flecart friend],regalo a flecart la proprietà intellettuale di questa soluzione&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
class Monitor{&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
  min_heap&amp;lt;(int,cond)&amp;gt; h;&lt;br /&gt;
&lt;br /&gt;
  void at_least(int n){&lt;br /&gt;
    int sum=0;&lt;br /&gt;
    int max_to_sblock= -INF;&lt;br /&gt;
    cond c = new cond(n);&lt;br /&gt;
    h.push((n,c));&lt;br /&gt;
    // la heap viene visitata in maniera crescente&lt;br /&gt;
    for(auto f=h.begin_iter();null!=f.next();f++) {&lt;br /&gt;
        sum++;&lt;br /&gt;
        if(f.0&amp;lt;=sum){&lt;br /&gt;
          max_to_sblock =f.0;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    for(auto f=h.begin_iter();null!=f.next();f++) {&lt;br /&gt;
        if(f.0&amp;lt;=max_to_sblock){&lt;br /&gt;
          f.1.signal();&lt;br /&gt;
          h.remove(c);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    if(n&amp;gt;max_to_sblock){&lt;br /&gt;
      c.wait();&lt;br /&gt;
    }&lt;br /&gt;
    free(c)&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Prova 2021/06/23 =&lt;br /&gt;
&lt;br /&gt;
== Esercizio C1 == &lt;br /&gt;
&lt;br /&gt;
=== Consegna === &lt;br /&gt;
Esercizio c.1: Scrivere il monitor delayvalue con una sola procedure entry:&lt;br /&gt;
  int delay(int value);&lt;br /&gt;
Il monitor deve sospendere i primi NDELAY processi che chiamano la delay. Le successive chiamate di delay&lt;br /&gt;
devono mantenere costante il numero di processi sospesi, ogni successiva chiamata devo riattivare il primo&lt;br /&gt;
processo in attesa prima di sospendersi, la delay ritorna il valore passato come parametro dal processo che&lt;br /&gt;
ne ha riattivato l'esecuzione. e.g. se NDELAY è 2:&lt;br /&gt;
  P1: delay(44) -&amp;gt; P1 si sospende&lt;br /&gt;
  P2: delay(40) -&amp;gt; P2 si sospende&lt;br /&gt;
  P3: delay(42) -&amp;gt; P1 si riattiva e ritorna 42, P3 si sospende&lt;br /&gt;
  P4: delay(22) -&amp;gt; P2 si riattiva e ritorna 22, P4 si sospende&lt;br /&gt;
&lt;br /&gt;
=== Soluzione proposta 1 ===&lt;br /&gt;
Soluzione proposta 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;
// variabile definita altrove.&lt;br /&gt;
extern int NDELAY;&lt;br /&gt;
&lt;br /&gt;
class Monitor {&lt;br /&gt;
    Queue&amp;lt;condition&amp;gt; stopped;&lt;br /&gt;
    int curr_value;&lt;br /&gt;
    Monitor {&lt;br /&gt;
        stopped = Queue&amp;lt;condition&amp;gt;();&lt;br /&gt;
        curr_value = 0;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    int delay(int value) {&lt;br /&gt;
        curr_value = value;&lt;br /&gt;
        if (stopped.size() == NDELAY) {&lt;br /&gt;
            condition first = stopped.dequeue();&lt;br /&gt;
            first.signal();&lt;br /&gt;
        }&lt;br /&gt;
        condition c = new condition();&lt;br /&gt;
        stopped.enqueue(c);&lt;br /&gt;
        c.wait();    &lt;br /&gt;
&lt;br /&gt;
        return curr_value;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Soluzione proposta 2 ===&lt;br /&gt;
Soluzione proposta da [https://so.v2.cs.unibo.it/wiki/index.php/User:Flecart Flecart friend], regalo la proprietà intellettuale a flecart. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
monitor dalayvalue{&lt;br /&gt;
&lt;br /&gt;
#define NDELAY 22&lt;br /&gt;
  int blocked=0;&lt;br /&gt;
  int lastvalue=0;&lt;br /&gt;
  cond c;&lt;br /&gt;
&lt;br /&gt;
  int dalay(int value){&lt;br /&gt;
    lastvalue=value;&lt;br /&gt;
    if(blocked&amp;lt;NDELAY){&lt;br /&gt;
      blocked++;&lt;br /&gt;
      c.wait();&lt;br /&gt;
    }else if(blocked==NDELAY){&lt;br /&gt;
      c.signal();&lt;br /&gt;
      c.wait();&lt;br /&gt;
    }&lt;br /&gt;
    return lastvalue;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Esercizio c2 ==&lt;br /&gt;
&lt;br /&gt;
=== Consegna ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Esercizio c.2: Implementare usando semafori ordinari (fair, fifo) un servizio di semafori a priorità lifo che&lt;br /&gt;
fornisca le seguenti primitive:&lt;br /&gt;
 void PLP(int prio);&lt;br /&gt;
 void PLV()&lt;br /&gt;
PLP e PLV si devono comportare rispettivamente come P e V. Quando la PLV deve riattivare un processo&lt;br /&gt;
sceglie fra quelli in attesa quello a priorità massima, nel caso siano presenti più processi a priorità massima&lt;br /&gt;
sceglie quello in attesa da meno tempo. &lt;br /&gt;
&lt;br /&gt;
=== Soluzione proposta 1 ===&lt;br /&gt;
&lt;br /&gt;
Esercizio c2  da Flecart.&lt;br /&gt;
&lt;br /&gt;
controllato:&lt;br /&gt;
* [[User:Gio|Gio]] ([[User talk:Gio|talk]]) 17:45, 16 January 2023 (CET)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Stack&amp;lt;semaphore&amp;gt; stack[MAX_PRIORITY];&lt;br /&gt;
int num_V = 0;&lt;br /&gt;
semaphore mutex(1);&lt;br /&gt;
&lt;br /&gt;
void  PLP(int prio) {&lt;br /&gt;
    mutex.P();&lt;br /&gt;
    if (num_V &amp;gt; 0) {&lt;br /&gt;
        num_V--;&lt;br /&gt;
        mutex.V();&lt;br /&gt;
        return;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    semaphore sem = semaphore(0);&lt;br /&gt;
    stack[prio].push(sem);&lt;br /&gt;
    mutex.V();&lt;br /&gt;
    sem.P();&lt;br /&gt;
&lt;br /&gt;
    mutex.V();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void PLV() {&lt;br /&gt;
    mutex.P();&lt;br /&gt;
    &lt;br /&gt;
    for (int i = MAX_PRIORITY - 1; i &amp;gt;= 0; i--) {&lt;br /&gt;
        if (stack[i].size() &amp;gt; 0) {&lt;br /&gt;
            sem = stack[i].pop();&lt;br /&gt;
            sem.V();&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    num_V++;&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;
&lt;br /&gt;
= Prova 2021/05/26 =&lt;br /&gt;
&lt;br /&gt;
== Consegna c1 == &lt;br /&gt;
&lt;br /&gt;
Esercizio c.1: Un buffer sincrono strampalato (bss) ha due procedure entry:&lt;br /&gt;
void put(T value)&lt;br /&gt;
list of T get(void)&lt;br /&gt;
La entry put viene utilizzata per aggiungere un elemento e la entry get per leggere tutti quelli disponibili.&lt;br /&gt;
Se più processi chiamano la put quando nessun processo è in attesa per una get, rimangono tutti bloccati.&lt;br /&gt;
Quando successivamente un processo chiama la get riceve la lista di tutti gli elementi inseriti con le put e&lt;br /&gt;
tutti i processi vengono sbloccati.&lt;br /&gt;
Se il buffer è vuoto tutti i processi che chiamano la get rimangono bloccati. quando un processo chiama&lt;br /&gt;
successivamente la put tutti i processi in attesa per la get si sbloccano e ricevono lo stesso valore di ritorno:&lt;br /&gt;
una lista contenente il solo valore passato come parametro alla put. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Soluzione proposta 1 ===&lt;br /&gt;
&lt;br /&gt;
Soluzione proposta da [https://so.v2.cs.unibo.it/wiki/index.php/User:Flecart Flecart]&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
int num = 0; // se è positiva rappresenta numero di gets che aspettano, se negativa, numero di puts&lt;br /&gt;
semaphore semput(0);&lt;br /&gt;
semaphore semget(0);&lt;br /&gt;
semaphore mutex(1);&lt;br /&gt;
list&amp;lt;T&amp;gt; global_list;&lt;br /&gt;
&lt;br /&gt;
void put(T value) {&lt;br /&gt;
    //&amp;lt; await(num &amp;gt; 0) --&amp;gt; global_list.add(value) &amp;gt;&lt;br /&gt;
    mutex.P();&lt;br /&gt;
    if (num &amp;lt;= 0) {&lt;br /&gt;
        num--;&lt;br /&gt;
        mutex.V();&lt;br /&gt;
        semput.P();&lt;br /&gt;
        num++;&lt;br /&gt;
    }&lt;br /&gt;
    global_list.add(value);&lt;br /&gt;
&lt;br /&gt;
    if (num &amp;lt; 0)&lt;br /&gt;
        semput.V();&lt;br /&gt;
    else &lt;br /&gt;
        semget.V();&lt;br /&gt;
&lt;br /&gt;
    return;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
list of T get() {&lt;br /&gt;
    list&amp;lt;T&amp;gt; local_list;&lt;br /&gt;
&lt;br /&gt;
    mutex.P();&lt;br /&gt;
    if (num &amp;gt;= 0) {&lt;br /&gt;
        num++;&lt;br /&gt;
        mutex.V();&lt;br /&gt;
        semget.P();&lt;br /&gt;
        num--;&lt;br /&gt;
    } else {&lt;br /&gt;
        semput.V();&lt;br /&gt;
        semget.P();&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    local_list = global_list; // fa deep copy&lt;br /&gt;
&lt;br /&gt;
    if (num &amp;gt; 0) {&lt;br /&gt;
        semget.V();&lt;br /&gt;
    } else {&lt;br /&gt;
        global_list = list&amp;lt;T&amp;gt;();&lt;br /&gt;
        mutex.V(); &lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    return local_list;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&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:Gio Gio]&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
class bss{&lt;br /&gt;
  int waiting_put=0;&lt;br /&gt;
  int waiting_get=0;&lt;br /&gt;
  cond cw,cg;&lt;br /&gt;
  queue&amp;lt;T&amp;gt; q;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
  void put(T value){&lt;br /&gt;
    q.push(T);&lt;br /&gt;
    if(waiting_get&amp;gt;0){&lt;br /&gt;
      cg.signal()&lt;br /&gt;
    }else{&lt;br /&gt;
      waiting_put++;&lt;br /&gt;
      cw.wait();&lt;br /&gt;
      waiting_put--;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  list&amp;lt;T&amp;gt; get(){&lt;br /&gt;
    if(waiting_put&amp;gt;0){&lt;br /&gt;
      while(waiting_put&amp;gt;0){&lt;br /&gt;
        cw.signal();&lt;br /&gt;
      }&lt;br /&gt;
    }else{&lt;br /&gt;
      waiting_get++;&lt;br /&gt;
      cg.wait();&lt;br /&gt;
      waiting_get--;&lt;br /&gt;
    }&lt;br /&gt;
    list&amp;lt;T&amp;gt; p= q.tolist();&lt;br /&gt;
    if(waiting_get&amp;gt;0){&lt;br /&gt;
      cg.signal();&lt;br /&gt;
    }&lt;br /&gt;
    q.removeAll();&lt;br /&gt;
    return p;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== esercizio c2 == &lt;br /&gt;
&lt;br /&gt;
Dato un servizio di message passing asincrono implementare un servizio di message passing&lt;br /&gt;
asincrono a selezione di mittenti (samp) senza fare uso di processi server.&lt;br /&gt;
Il servizio samp ha due primitive:&lt;br /&gt;
sasend(message , destination)&lt;br /&gt;
sarecv(senders)&lt;br /&gt;
dove senders è un insieme.&lt;br /&gt;
la sarecv restituisce il primo messaggio che uno dei processi in senders ha spedito al processo ricevente&lt;br /&gt;
usando la sasend (o spedito da qualsiasi processo se senders è vuoto).&lt;br /&gt;
&lt;br /&gt;
=== Soluzione proposta 1 === &lt;br /&gt;
&lt;br /&gt;
Soluzione proposta da [[User:Flecart|Flecart]] ([[User talk:Flecart|talk]]) 15:29, 15 January 2023 (CET)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
sasend(message, destination) {&lt;br /&gt;
	pid t = getpid();&lt;br /&gt;
	asend(&amp;lt;message, t&amp;gt;, destination);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// variabile privata di sarecv&lt;br /&gt;
queue all_messages[MAX_PROC];&lt;br /&gt;
&lt;br /&gt;
// stora tutti i messaggi ricevuti, lo utilizziamo come queue per tutti, con &lt;br /&gt;
// anche la possibilità di rimuovere in un punto a scelta.&lt;br /&gt;
vector&amp;lt;&amp;lt;messages, pid&amp;gt;&amp;gt; msg; &lt;br /&gt;
sarecv(senders) {&lt;br /&gt;
	if (senders.len() == 0) {&lt;br /&gt;
		if (msg.len() == 0) {&lt;br /&gt;
			&amp;lt;message, sender&amp;gt; = arecv(ANY);&lt;br /&gt;
			return message;&lt;br /&gt;
		} else {&lt;br /&gt;
			&amp;lt;message, sender&amp;gt; = msg.pop_back();&lt;br /&gt;
			return message;&lt;br /&gt;
		}&lt;br /&gt;
	} else {&lt;br /&gt;
		do {&lt;br /&gt;
			for (idx in senders) {&lt;br /&gt;
				if (all_messages[idx].size() &amp;gt; 0) {&lt;br /&gt;
					message = all_messages[idx].dequeue();&lt;br /&gt;
					// rimuove il singolo messaggio dal vector, non tutti quelli uguali.&lt;br /&gt;
					msg.remove(&amp;lt;message, idx&amp;gt;);&lt;br /&gt;
					return message;&lt;br /&gt;
				}&lt;br /&gt;
			}	&lt;br /&gt;
			&lt;br /&gt;
			&amp;lt;message, sender&amp;gt; = arecv(ANY);&lt;br /&gt;
			msg.push_back(&amp;lt;message, sender&amp;gt;);&lt;br /&gt;
			all_messages[sender].enqueue(&amp;lt;message&amp;gt;);&lt;br /&gt;
		} while(true);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Gio</name></author>
	</entry>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=Prove_scritte_2021&amp;diff=2904</id>
		<title>Prove scritte 2021</title>
		<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php?title=Prove_scritte_2021&amp;diff=2904"/>
		<updated>2023-01-16T16:45:01Z</updated>

		<summary type="html">&lt;p&gt;Gio: /* Soluzione proposta 1 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
= Prova 21/07/2021=&lt;br /&gt;
&lt;br /&gt;
== Es C1 (da correggere) == &lt;br /&gt;
&lt;br /&gt;
Soluzione proposta da [https://so.v2.cs.unibo.it/wiki/index.php/User:Flecart Flecart friend],regalo a flecart la proprietà intellettuale di questa soluzione&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
class node{&lt;br /&gt;
  node parent;&lt;br /&gt;
  sq sq1;&lt;br /&gt;
  cond c;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
class BinTree{&lt;br /&gt;
  vector&amp;lt;node&amp;gt; base;&lt;br /&gt;
  void create(int N){&lt;br /&gt;
    base=new vector&amp;lt;node&amp;gt;(2^N);&lt;br /&gt;
    for(int i=0;i&amp;lt;2^N;i++)&lt;br /&gt;
      base[i]=new node(null,0,new cond);&lt;br /&gt;
    for(int i=1;i&amp;lt;=N;i++){&lt;br /&gt;
      for(int j=0;j&amp;lt;2^(N-i);j++){&lt;br /&gt;
        get(j,i-1).parent=get(j+i,i-1).parent=new node(null,0,new cond);&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  node get(int i,int level){&lt;br /&gt;
    return get(base[i],level);&lt;br /&gt;
  }&lt;br /&gt;
  node get(node n,int level){&lt;br /&gt;
    if(level==0){&lt;br /&gt;
      return node;&lt;br /&gt;
    }&lt;br /&gt;
    return get(node.parent,level-1);&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class Torneo{&lt;br /&gt;
  BinTree bin(N);&lt;br /&gt;
  int forma[2^N];&lt;br /&gt;
  bool win;&lt;br /&gt;
&lt;br /&gt;
  bool gioca(int i,int turno,int forma){&lt;br /&gt;
    forma[i]=forma;&lt;br /&gt;
    if null==bin.get(i,turno).sq1{&lt;br /&gt;
      bin.get(i,turno).sq1=i;&lt;br /&gt;
      bin.get(i,turno).c.wait();&lt;br /&gt;
      return !win;&lt;br /&gt;
    }else{&lt;br /&gt;
      sq1= bin.get(i,turno).sq1;&lt;br /&gt;
      if(forma[sq1]==forma[i]){&lt;br /&gt;
        win=random();&lt;br /&gt;
      }else{&lt;br /&gt;
        win=forma[sq1]&amp;lt;forma[i];&lt;br /&gt;
      }&lt;br /&gt;
      bin.get(i,turno).signal();&lt;br /&gt;
    }&lt;br /&gt;
    return win;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Prova 2021/09/15 =&lt;br /&gt;
&lt;br /&gt;
== Esercizio C1 == &lt;br /&gt;
&lt;br /&gt;
=== Consegna === &lt;br /&gt;
Esercizio c.1: Scrivere il monitor alrv (at least rendez-vous) che fornisce una sola procedure entry:&lt;br /&gt;
procedure entry void at_least(int n)&lt;br /&gt;
Quando un processo chiama la funzione at_least vuol dire che vuole sincronizzarsi con un insieme di almeno n&lt;br /&gt;
processi (incluso il chiamante).&lt;br /&gt;
Esempi:&lt;br /&gt;
Se un processo chiama at_least(1) non si blocca.&lt;br /&gt;
Se il processo p chiama at_least(2) si blocca, se poi il processo q chiama at_least(2) oppure at_least(1) si&lt;br /&gt;
sbloccano sia p sia q (la richiesta di p è soddisfatta, ne aspettava almeno 2, p e q)&lt;br /&gt;
Se il processo p chiama at_least(2) si blocca, se poi il processo q chiama at_least(3) si blocca anch'esso perché&lt;br /&gt;
sebbene la richiesta di p possa essere soddisfatta, q non può ancora sbloccarsi: ci sono solo 2 processi in attesa mentre&lt;br /&gt;
q ne vuole 3. Un terzo processo che chiami at_least(x) con x=1,2,3 li sblocca tutti.&lt;br /&gt;
Hint: sia w[k ] il numero dei processi in attesa di essere in almeno k (quelli che hanno chiamato at_least(k) e non&lt;br /&gt;
hanno completato l'esecuzione della funzione). Sia s[n]=∑&lt;br /&gt;
k=1&lt;br /&gt;
n&lt;br /&gt;
w[k ] (rappresenta il numero di processi soddisfacibili:&lt;br /&gt;
e.g. se ci sono 4 processi in attesa, potrebbero essere soddisfatte le richieste dei processi che ne aspettano almeno 2,&lt;br /&gt;
almeno 3 o almeno 4). Preso, se esiste, il massimo indice m tale che s[m]≥m tutti i processi in attesa di essere in n,&lt;br /&gt;
per n≤m possono essere sbloccati.&lt;br /&gt;
&lt;br /&gt;
=== 1. Soluzione proposta ===&lt;br /&gt;
Soluzione proposta da [https://so.v2.cs.unibo.it/wiki/index.php/User:Flecart Flecart]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
extern int MAX;  // il massimo numero di attesa&lt;br /&gt;
monitor alrv {&lt;br /&gt;
	int w[MAX];&lt;br /&gt;
	int s[MAX];&lt;br /&gt;
	condition c[MAX];&lt;br /&gt;
&lt;br /&gt;
	init() {&lt;br /&gt;
		for (int i = 0; i &amp;lt; MAX; i++) {&lt;br /&gt;
			w[i] = s[i] = 0;&lt;br /&gt;
		}&lt;br /&gt;
	}	&lt;br /&gt;
&lt;br /&gt;
procedure entry void at_least(int n) {&lt;br /&gt;
	if (n &amp;gt;= MAX || n &amp;lt;= 0) raise error;&lt;br /&gt;
	&lt;br /&gt;
	int i;&lt;br /&gt;
	for (i = n; i &amp;lt; MAX; i++) s[i]++;&lt;br /&gt;
	&lt;br /&gt;
	for (i = MAX - 1; i &amp;gt; 0; i--) {&lt;br /&gt;
		if (s[i] &amp;gt;= i) break;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	if (i &amp;gt; 0) {&lt;br /&gt;
		for (int j = 0; j &amp;lt;= i; j++) {&lt;br /&gt;
			while (w[j] &amp;gt; 0) {&lt;br /&gt;
				c[j].signal();&lt;br /&gt;
				w[j]--;&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
		&lt;br /&gt;
		s[0] = 0;&lt;br /&gt;
		for (int i = 1; i &amp;lt; MAX; i++) {&lt;br /&gt;
			s[i] = w[i] + s[i - 1];&lt;br /&gt;
		}&lt;br /&gt;
	} else {&lt;br /&gt;
		w[n]++;&lt;br /&gt;
		c[n].wait();&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Soluzione proposta da [https://so.v2.cs.unibo.it/wiki/index.php/User:Flecart Flecart friend],regalo a flecart la proprietà intellettuale di questa soluzione&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
class Monitor{&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
  min_heap&amp;lt;(int,cond)&amp;gt; h;&lt;br /&gt;
&lt;br /&gt;
  void at_least(int n){&lt;br /&gt;
    int sum=0;&lt;br /&gt;
    int max_to_sblock= -INF;&lt;br /&gt;
    cond c = new cond(n);&lt;br /&gt;
    h.push((n,c));&lt;br /&gt;
    // la heap viene visitata in maniera crescente&lt;br /&gt;
    for(auto f=h.begin_iter();null!=f.next();f++) {&lt;br /&gt;
        sum++;&lt;br /&gt;
        if(f.0&amp;lt;=sum){&lt;br /&gt;
          max_to_sblock =f.0;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    for(auto f=h.begin_iter();null!=f.next();f++) {&lt;br /&gt;
        if(f.0&amp;lt;=max_to_sblock){&lt;br /&gt;
          f.1.signal();&lt;br /&gt;
          h.remove(c);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    if(n&amp;gt;max_to_sblock){&lt;br /&gt;
      c.wait();&lt;br /&gt;
    }&lt;br /&gt;
    free(c)&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Prova 2021/06/23 =&lt;br /&gt;
&lt;br /&gt;
== Esercizio C1 == &lt;br /&gt;
&lt;br /&gt;
=== Consegna === &lt;br /&gt;
Esercizio c.1: Scrivere il monitor delayvalue con una sola procedure entry:&lt;br /&gt;
  int delay(int value);&lt;br /&gt;
Il monitor deve sospendere i primi NDELAY processi che chiamano la delay. Le successive chiamate di delay&lt;br /&gt;
devono mantenere costante il numero di processi sospesi, ogni successiva chiamata devo riattivare il primo&lt;br /&gt;
processo in attesa prima di sospendersi, la delay ritorna il valore passato come parametro dal processo che&lt;br /&gt;
ne ha riattivato l'esecuzione. e.g. se NDELAY è 2:&lt;br /&gt;
  P1: delay(44) -&amp;gt; P1 si sospende&lt;br /&gt;
  P2: delay(40) -&amp;gt; P2 si sospende&lt;br /&gt;
  P3: delay(42) -&amp;gt; P1 si riattiva e ritorna 42, P3 si sospende&lt;br /&gt;
  P4: delay(22) -&amp;gt; P2 si riattiva e ritorna 22, P4 si sospende&lt;br /&gt;
&lt;br /&gt;
=== Soluzione proposta 1 ===&lt;br /&gt;
Soluzione proposta 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;
// variabile definita altrove.&lt;br /&gt;
extern int NDELAY;&lt;br /&gt;
&lt;br /&gt;
class Monitor {&lt;br /&gt;
    Queue&amp;lt;condition&amp;gt; stopped;&lt;br /&gt;
    int curr_value;&lt;br /&gt;
    Monitor {&lt;br /&gt;
        stopped = Queue&amp;lt;condition&amp;gt;();&lt;br /&gt;
        curr_value = 0;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    int delay(int value) {&lt;br /&gt;
        curr_value = value;&lt;br /&gt;
        if (stopped.size() == NDELAY) {&lt;br /&gt;
            condition first = stopped.dequeue();&lt;br /&gt;
            first.signal();&lt;br /&gt;
        }&lt;br /&gt;
        condition c = new condition();&lt;br /&gt;
        stopped.enqueue(c);&lt;br /&gt;
        c.wait();    &lt;br /&gt;
&lt;br /&gt;
        return curr_value;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Soluzione proposta 2 ===&lt;br /&gt;
Soluzione proposta da [https://so.v2.cs.unibo.it/wiki/index.php/User:Flecart Flecart friend], regalo la proprietà intellettuale a flecart. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
monitor dalayvalue{&lt;br /&gt;
&lt;br /&gt;
#define NDELAY 22&lt;br /&gt;
  int blocked=0;&lt;br /&gt;
  int lastvalue=0;&lt;br /&gt;
  cond c;&lt;br /&gt;
&lt;br /&gt;
  int dalay(int value){&lt;br /&gt;
    lastvalue=value;&lt;br /&gt;
    if(blocked&amp;lt;NDELAY){&lt;br /&gt;
      blocked++;&lt;br /&gt;
      c.wait();&lt;br /&gt;
    }else if(blocked==NDELAY){&lt;br /&gt;
      c.signal();&lt;br /&gt;
      c.wait();&lt;br /&gt;
    }&lt;br /&gt;
    return lastvalue;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Esercizio c2 ==&lt;br /&gt;
&lt;br /&gt;
=== Consegna ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Esercizio c.2: Implementare usando semafori ordinari (fair, fifo) un servizio di semafori a priorità lifo che&lt;br /&gt;
fornisca le seguenti primitive:&lt;br /&gt;
 void PLP(int prio);&lt;br /&gt;
 void PLV()&lt;br /&gt;
PLP e PLV si devono comportare rispettivamente come P e V. Quando la PLV deve riattivare un processo&lt;br /&gt;
sceglie fra quelli in attesa quello a priorità massima, nel caso siano presenti più processi a priorità massima&lt;br /&gt;
sceglie quello in attesa da meno tempo. &lt;br /&gt;
&lt;br /&gt;
=== Soluzione proposta 1 ===&lt;br /&gt;
&lt;br /&gt;
Esercizio c2  da Flecart.&lt;br /&gt;
&lt;br /&gt;
controllato:&lt;br /&gt;
-[[User:Gio|Gio]] ([[User talk:Gio|talk]]) 17:45, 16 January 2023 (CET)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Stack&amp;lt;semaphore&amp;gt; stack[MAX_PRIORITY];&lt;br /&gt;
int num_V = 0;&lt;br /&gt;
semaphore mutex(1);&lt;br /&gt;
&lt;br /&gt;
void  PLP(int prio) {&lt;br /&gt;
    mutex.P();&lt;br /&gt;
    if (num_V &amp;gt; 0) {&lt;br /&gt;
        num_V--;&lt;br /&gt;
        mutex.V();&lt;br /&gt;
        return;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    semaphore sem = semaphore(0);&lt;br /&gt;
    stack[prio].push(sem);&lt;br /&gt;
    mutex.V();&lt;br /&gt;
    sem.P();&lt;br /&gt;
&lt;br /&gt;
    mutex.V();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void PLV() {&lt;br /&gt;
    mutex.P();&lt;br /&gt;
    &lt;br /&gt;
    for (int i = MAX_PRIORITY - 1; i &amp;gt;= 0; i--) {&lt;br /&gt;
        if (stack[i].size() &amp;gt; 0) {&lt;br /&gt;
            sem = stack[i].pop();&lt;br /&gt;
            sem.V();&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    num_V++;&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;
&lt;br /&gt;
= Prova 2021/05/26 =&lt;br /&gt;
&lt;br /&gt;
== Consegna c1 == &lt;br /&gt;
&lt;br /&gt;
Esercizio c.1: Un buffer sincrono strampalato (bss) ha due procedure entry:&lt;br /&gt;
void put(T value)&lt;br /&gt;
list of T get(void)&lt;br /&gt;
La entry put viene utilizzata per aggiungere un elemento e la entry get per leggere tutti quelli disponibili.&lt;br /&gt;
Se più processi chiamano la put quando nessun processo è in attesa per una get, rimangono tutti bloccati.&lt;br /&gt;
Quando successivamente un processo chiama la get riceve la lista di tutti gli elementi inseriti con le put e&lt;br /&gt;
tutti i processi vengono sbloccati.&lt;br /&gt;
Se il buffer è vuoto tutti i processi che chiamano la get rimangono bloccati. quando un processo chiama&lt;br /&gt;
successivamente la put tutti i processi in attesa per la get si sbloccano e ricevono lo stesso valore di ritorno:&lt;br /&gt;
una lista contenente il solo valore passato come parametro alla put. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Soluzione proposta 1 ===&lt;br /&gt;
&lt;br /&gt;
Soluzione proposta da [https://so.v2.cs.unibo.it/wiki/index.php/User:Flecart Flecart]&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
int num = 0; // se è positiva rappresenta numero di gets che aspettano, se negativa, numero di puts&lt;br /&gt;
semaphore semput(0);&lt;br /&gt;
semaphore semget(0);&lt;br /&gt;
semaphore mutex(1);&lt;br /&gt;
list&amp;lt;T&amp;gt; global_list;&lt;br /&gt;
&lt;br /&gt;
void put(T value) {&lt;br /&gt;
    //&amp;lt; await(num &amp;gt; 0) --&amp;gt; global_list.add(value) &amp;gt;&lt;br /&gt;
    mutex.P();&lt;br /&gt;
    if (num &amp;lt;= 0) {&lt;br /&gt;
        num--;&lt;br /&gt;
        mutex.V();&lt;br /&gt;
        semput.P();&lt;br /&gt;
        num++;&lt;br /&gt;
    }&lt;br /&gt;
    global_list.add(value);&lt;br /&gt;
&lt;br /&gt;
    if (num &amp;lt; 0)&lt;br /&gt;
        semput.V();&lt;br /&gt;
    else &lt;br /&gt;
        semget.V();&lt;br /&gt;
&lt;br /&gt;
    return;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
list of T get() {&lt;br /&gt;
    list&amp;lt;T&amp;gt; local_list;&lt;br /&gt;
&lt;br /&gt;
    mutex.P();&lt;br /&gt;
    if (num &amp;gt;= 0) {&lt;br /&gt;
        num++;&lt;br /&gt;
        mutex.V();&lt;br /&gt;
        semget.P();&lt;br /&gt;
        num--;&lt;br /&gt;
    } else {&lt;br /&gt;
        semput.V();&lt;br /&gt;
        semget.P();&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    local_list = global_list; // fa deep copy&lt;br /&gt;
&lt;br /&gt;
    if (num &amp;gt; 0) {&lt;br /&gt;
        semget.V();&lt;br /&gt;
    } else {&lt;br /&gt;
        global_list = list&amp;lt;T&amp;gt;();&lt;br /&gt;
        mutex.V(); &lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    return local_list;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&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:Gio Gio]&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
class bss{&lt;br /&gt;
  int waiting_put=0;&lt;br /&gt;
  int waiting_get=0;&lt;br /&gt;
  cond cw,cg;&lt;br /&gt;
  queue&amp;lt;T&amp;gt; q;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
  void put(T value){&lt;br /&gt;
    q.push(T);&lt;br /&gt;
    if(waiting_get&amp;gt;0){&lt;br /&gt;
      cg.signal()&lt;br /&gt;
    }else{&lt;br /&gt;
      waiting_put++;&lt;br /&gt;
      cw.wait();&lt;br /&gt;
      waiting_put--;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  list&amp;lt;T&amp;gt; get(){&lt;br /&gt;
    if(waiting_put&amp;gt;0){&lt;br /&gt;
      while(waiting_put&amp;gt;0){&lt;br /&gt;
        cw.signal();&lt;br /&gt;
      }&lt;br /&gt;
    }else{&lt;br /&gt;
      waiting_get++;&lt;br /&gt;
      cg.wait();&lt;br /&gt;
      waiting_get--;&lt;br /&gt;
    }&lt;br /&gt;
    list&amp;lt;T&amp;gt; p= q.tolist();&lt;br /&gt;
    if(waiting_get&amp;gt;0){&lt;br /&gt;
      cg.signal();&lt;br /&gt;
    }&lt;br /&gt;
    q.removeAll();&lt;br /&gt;
    return p;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== esercizio c2 == &lt;br /&gt;
&lt;br /&gt;
Dato un servizio di message passing asincrono implementare un servizio di message passing&lt;br /&gt;
asincrono a selezione di mittenti (samp) senza fare uso di processi server.&lt;br /&gt;
Il servizio samp ha due primitive:&lt;br /&gt;
sasend(message , destination)&lt;br /&gt;
sarecv(senders)&lt;br /&gt;
dove senders è un insieme.&lt;br /&gt;
la sarecv restituisce il primo messaggio che uno dei processi in senders ha spedito al processo ricevente&lt;br /&gt;
usando la sasend (o spedito da qualsiasi processo se senders è vuoto).&lt;br /&gt;
&lt;br /&gt;
=== Soluzione proposta 1 === &lt;br /&gt;
&lt;br /&gt;
Soluzione proposta da [[User:Flecart|Flecart]] ([[User talk:Flecart|talk]]) 15:29, 15 January 2023 (CET)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
sasend(message, destination) {&lt;br /&gt;
	pid t = getpid();&lt;br /&gt;
	asend(&amp;lt;message, t&amp;gt;, destination);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// variabile privata di sarecv&lt;br /&gt;
queue all_messages[MAX_PROC];&lt;br /&gt;
&lt;br /&gt;
// stora tutti i messaggi ricevuti, lo utilizziamo come queue per tutti, con &lt;br /&gt;
// anche la possibilità di rimuovere in un punto a scelta.&lt;br /&gt;
vector&amp;lt;&amp;lt;messages, pid&amp;gt;&amp;gt; msg; &lt;br /&gt;
sarecv(senders) {&lt;br /&gt;
	if (senders.len() == 0) {&lt;br /&gt;
		if (msg.len() == 0) {&lt;br /&gt;
			&amp;lt;message, sender&amp;gt; = arecv(ANY);&lt;br /&gt;
			return message;&lt;br /&gt;
		} else {&lt;br /&gt;
			&amp;lt;message, sender&amp;gt; = msg.pop_back();&lt;br /&gt;
			return message;&lt;br /&gt;
		}&lt;br /&gt;
	} else {&lt;br /&gt;
		do {&lt;br /&gt;
			for (idx in senders) {&lt;br /&gt;
				if (all_messages[idx].size() &amp;gt; 0) {&lt;br /&gt;
					message = all_messages[idx].dequeue();&lt;br /&gt;
					// rimuove il singolo messaggio dal vector, non tutti quelli uguali.&lt;br /&gt;
					msg.remove(&amp;lt;message, idx&amp;gt;);&lt;br /&gt;
					return message;&lt;br /&gt;
				}&lt;br /&gt;
			}	&lt;br /&gt;
			&lt;br /&gt;
			&amp;lt;message, sender&amp;gt; = arecv(ANY);&lt;br /&gt;
			msg.push_back(&amp;lt;message, sender&amp;gt;);&lt;br /&gt;
			all_messages[sender].enqueue(&amp;lt;message&amp;gt;);&lt;br /&gt;
		} while(true);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Gio</name></author>
	</entry>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=Prove_scritte_2021&amp;diff=2903</id>
		<title>Prove scritte 2021</title>
		<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php?title=Prove_scritte_2021&amp;diff=2903"/>
		<updated>2023-01-16T16:27:41Z</updated>

		<summary type="html">&lt;p&gt;Gio: /* Esercizio C1 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
= Prova 21/07/2021=&lt;br /&gt;
&lt;br /&gt;
== Es C1 (da correggere) == &lt;br /&gt;
&lt;br /&gt;
Soluzione proposta da [https://so.v2.cs.unibo.it/wiki/index.php/User:Flecart Flecart friend],regalo a flecart la proprietà intellettuale di questa soluzione&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
class node{&lt;br /&gt;
  node parent;&lt;br /&gt;
  sq sq1;&lt;br /&gt;
  cond c;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
class BinTree{&lt;br /&gt;
  vector&amp;lt;node&amp;gt; base;&lt;br /&gt;
  void create(int N){&lt;br /&gt;
    base=new vector&amp;lt;node&amp;gt;(2^N);&lt;br /&gt;
    for(int i=0;i&amp;lt;2^N;i++)&lt;br /&gt;
      base[i]=new node(null,0,new cond);&lt;br /&gt;
    for(int i=1;i&amp;lt;=N;i++){&lt;br /&gt;
      for(int j=0;j&amp;lt;2^(N-i);j++){&lt;br /&gt;
        get(j,i-1).parent=get(j+i,i-1).parent=new node(null,0,new cond);&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  node get(int i,int level){&lt;br /&gt;
    return get(base[i],level);&lt;br /&gt;
  }&lt;br /&gt;
  node get(node n,int level){&lt;br /&gt;
    if(level==0){&lt;br /&gt;
      return node;&lt;br /&gt;
    }&lt;br /&gt;
    return get(node.parent,level-1);&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class Torneo{&lt;br /&gt;
  BinTree bin(N);&lt;br /&gt;
  int forma[2^N];&lt;br /&gt;
  bool win;&lt;br /&gt;
&lt;br /&gt;
  bool gioca(int i,int turno,int forma){&lt;br /&gt;
    forma[i]=forma;&lt;br /&gt;
    if null==bin.get(i,turno).sq1{&lt;br /&gt;
      bin.get(i,turno).sq1=i;&lt;br /&gt;
      bin.get(i,turno).c.wait();&lt;br /&gt;
      return !win;&lt;br /&gt;
    }else{&lt;br /&gt;
      sq1= bin.get(i,turno).sq1;&lt;br /&gt;
      if(forma[sq1]==forma[i]){&lt;br /&gt;
        win=random();&lt;br /&gt;
      }else{&lt;br /&gt;
        win=forma[sq1]&amp;lt;forma[i];&lt;br /&gt;
      }&lt;br /&gt;
      bin.get(i,turno).signal();&lt;br /&gt;
    }&lt;br /&gt;
    return win;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Prova 2021/09/15 =&lt;br /&gt;
&lt;br /&gt;
== Esercizio C1 == &lt;br /&gt;
&lt;br /&gt;
=== Consegna === &lt;br /&gt;
Esercizio c.1: Scrivere il monitor alrv (at least rendez-vous) che fornisce una sola procedure entry:&lt;br /&gt;
procedure entry void at_least(int n)&lt;br /&gt;
Quando un processo chiama la funzione at_least vuol dire che vuole sincronizzarsi con un insieme di almeno n&lt;br /&gt;
processi (incluso il chiamante).&lt;br /&gt;
Esempi:&lt;br /&gt;
Se un processo chiama at_least(1) non si blocca.&lt;br /&gt;
Se il processo p chiama at_least(2) si blocca, se poi il processo q chiama at_least(2) oppure at_least(1) si&lt;br /&gt;
sbloccano sia p sia q (la richiesta di p è soddisfatta, ne aspettava almeno 2, p e q)&lt;br /&gt;
Se il processo p chiama at_least(2) si blocca, se poi il processo q chiama at_least(3) si blocca anch'esso perché&lt;br /&gt;
sebbene la richiesta di p possa essere soddisfatta, q non può ancora sbloccarsi: ci sono solo 2 processi in attesa mentre&lt;br /&gt;
q ne vuole 3. Un terzo processo che chiami at_least(x) con x=1,2,3 li sblocca tutti.&lt;br /&gt;
Hint: sia w[k ] il numero dei processi in attesa di essere in almeno k (quelli che hanno chiamato at_least(k) e non&lt;br /&gt;
hanno completato l'esecuzione della funzione). Sia s[n]=∑&lt;br /&gt;
k=1&lt;br /&gt;
n&lt;br /&gt;
w[k ] (rappresenta il numero di processi soddisfacibili:&lt;br /&gt;
e.g. se ci sono 4 processi in attesa, potrebbero essere soddisfatte le richieste dei processi che ne aspettano almeno 2,&lt;br /&gt;
almeno 3 o almeno 4). Preso, se esiste, il massimo indice m tale che s[m]≥m tutti i processi in attesa di essere in n,&lt;br /&gt;
per n≤m possono essere sbloccati.&lt;br /&gt;
&lt;br /&gt;
=== 1. Soluzione proposta ===&lt;br /&gt;
Soluzione proposta da [https://so.v2.cs.unibo.it/wiki/index.php/User:Flecart Flecart]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
extern int MAX;  // il massimo numero di attesa&lt;br /&gt;
monitor alrv {&lt;br /&gt;
	int w[MAX];&lt;br /&gt;
	int s[MAX];&lt;br /&gt;
	condition c[MAX];&lt;br /&gt;
&lt;br /&gt;
	init() {&lt;br /&gt;
		for (int i = 0; i &amp;lt; MAX; i++) {&lt;br /&gt;
			w[i] = s[i] = 0;&lt;br /&gt;
		}&lt;br /&gt;
	}	&lt;br /&gt;
&lt;br /&gt;
procedure entry void at_least(int n) {&lt;br /&gt;
	if (n &amp;gt;= MAX || n &amp;lt;= 0) raise error;&lt;br /&gt;
	&lt;br /&gt;
	int i;&lt;br /&gt;
	for (i = n; i &amp;lt; MAX; i++) s[i]++;&lt;br /&gt;
	&lt;br /&gt;
	for (i = MAX - 1; i &amp;gt; 0; i--) {&lt;br /&gt;
		if (s[i] &amp;gt;= i) break;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	if (i &amp;gt; 0) {&lt;br /&gt;
		for (int j = 0; j &amp;lt;= i; j++) {&lt;br /&gt;
			while (w[j] &amp;gt; 0) {&lt;br /&gt;
				c[j].signal();&lt;br /&gt;
				w[j]--;&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
		&lt;br /&gt;
		s[0] = 0;&lt;br /&gt;
		for (int i = 1; i &amp;lt; MAX; i++) {&lt;br /&gt;
			s[i] = w[i] + s[i - 1];&lt;br /&gt;
		}&lt;br /&gt;
	} else {&lt;br /&gt;
		w[n]++;&lt;br /&gt;
		c[n].wait();&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Soluzione proposta da [https://so.v2.cs.unibo.it/wiki/index.php/User:Flecart Flecart friend],regalo a flecart la proprietà intellettuale di questa soluzione&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
class Monitor{&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
  min_heap&amp;lt;(int,cond)&amp;gt; h;&lt;br /&gt;
&lt;br /&gt;
  void at_least(int n){&lt;br /&gt;
    int sum=0;&lt;br /&gt;
    int max_to_sblock= -INF;&lt;br /&gt;
    cond c = new cond(n);&lt;br /&gt;
    h.push((n,c));&lt;br /&gt;
    // la heap viene visitata in maniera crescente&lt;br /&gt;
    for(auto f=h.begin_iter();null!=f.next();f++) {&lt;br /&gt;
        sum++;&lt;br /&gt;
        if(f.0&amp;lt;=sum){&lt;br /&gt;
          max_to_sblock =f.0;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    for(auto f=h.begin_iter();null!=f.next();f++) {&lt;br /&gt;
        if(f.0&amp;lt;=max_to_sblock){&lt;br /&gt;
          f.1.signal();&lt;br /&gt;
          h.remove(c);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    if(n&amp;gt;max_to_sblock){&lt;br /&gt;
      c.wait();&lt;br /&gt;
    }&lt;br /&gt;
    free(c)&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Prova 2021/06/23 =&lt;br /&gt;
&lt;br /&gt;
== Esercizio C1 == &lt;br /&gt;
&lt;br /&gt;
=== Consegna === &lt;br /&gt;
Esercizio c.1: Scrivere il monitor delayvalue con una sola procedure entry:&lt;br /&gt;
  int delay(int value);&lt;br /&gt;
Il monitor deve sospendere i primi NDELAY processi che chiamano la delay. Le successive chiamate di delay&lt;br /&gt;
devono mantenere costante il numero di processi sospesi, ogni successiva chiamata devo riattivare il primo&lt;br /&gt;
processo in attesa prima di sospendersi, la delay ritorna il valore passato come parametro dal processo che&lt;br /&gt;
ne ha riattivato l'esecuzione. e.g. se NDELAY è 2:&lt;br /&gt;
  P1: delay(44) -&amp;gt; P1 si sospende&lt;br /&gt;
  P2: delay(40) -&amp;gt; P2 si sospende&lt;br /&gt;
  P3: delay(42) -&amp;gt; P1 si riattiva e ritorna 42, P3 si sospende&lt;br /&gt;
  P4: delay(22) -&amp;gt; P2 si riattiva e ritorna 22, P4 si sospende&lt;br /&gt;
&lt;br /&gt;
=== Soluzione proposta 1 ===&lt;br /&gt;
Soluzione proposta 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;
// variabile definita altrove.&lt;br /&gt;
extern int NDELAY;&lt;br /&gt;
&lt;br /&gt;
class Monitor {&lt;br /&gt;
    Queue&amp;lt;condition&amp;gt; stopped;&lt;br /&gt;
    int curr_value;&lt;br /&gt;
    Monitor {&lt;br /&gt;
        stopped = Queue&amp;lt;condition&amp;gt;();&lt;br /&gt;
        curr_value = 0;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    int delay(int value) {&lt;br /&gt;
        curr_value = value;&lt;br /&gt;
        if (stopped.size() == NDELAY) {&lt;br /&gt;
            condition first = stopped.dequeue();&lt;br /&gt;
            first.signal();&lt;br /&gt;
        }&lt;br /&gt;
        condition c = new condition();&lt;br /&gt;
        stopped.enqueue(c);&lt;br /&gt;
        c.wait();    &lt;br /&gt;
&lt;br /&gt;
        return curr_value;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Soluzione proposta 2 ===&lt;br /&gt;
Soluzione proposta da [https://so.v2.cs.unibo.it/wiki/index.php/User:Flecart Flecart friend], regalo la proprietà intellettuale a flecart. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
monitor dalayvalue{&lt;br /&gt;
&lt;br /&gt;
#define NDELAY 22&lt;br /&gt;
  int blocked=0;&lt;br /&gt;
  int lastvalue=0;&lt;br /&gt;
  cond c;&lt;br /&gt;
&lt;br /&gt;
  int dalay(int value){&lt;br /&gt;
    lastvalue=value;&lt;br /&gt;
    if(blocked&amp;lt;NDELAY){&lt;br /&gt;
      blocked++;&lt;br /&gt;
      c.wait();&lt;br /&gt;
    }else if(blocked==NDELAY){&lt;br /&gt;
      c.signal();&lt;br /&gt;
      c.wait();&lt;br /&gt;
    }&lt;br /&gt;
    return lastvalue;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Esercizio c2 ==&lt;br /&gt;
&lt;br /&gt;
=== Consegna ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Esercizio c.2: Implementare usando semafori ordinari (fair, fifo) un servizio di semafori a priorità lifo che&lt;br /&gt;
fornisca le seguenti primitive:&lt;br /&gt;
 void PLP(int prio);&lt;br /&gt;
 void PLV()&lt;br /&gt;
PLP e PLV si devono comportare rispettivamente come P e V. Quando la PLV deve riattivare un processo&lt;br /&gt;
sceglie fra quelli in attesa quello a priorità massima, nel caso siano presenti più processi a priorità massima&lt;br /&gt;
sceglie quello in attesa da meno tempo. &lt;br /&gt;
&lt;br /&gt;
=== Soluzione proposta 1 ===&lt;br /&gt;
&lt;br /&gt;
Esercizio c2 (da controllare) da Flecart.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Stack&amp;lt;semaphore&amp;gt; stack[MAX_PRIORITY];&lt;br /&gt;
int num_V = 0;&lt;br /&gt;
semaphore mutex(1);&lt;br /&gt;
&lt;br /&gt;
void  PLP(int prio) {&lt;br /&gt;
    mutex.P();&lt;br /&gt;
    if (num_V &amp;gt; 0) {&lt;br /&gt;
        num_V--;&lt;br /&gt;
        mutex.V();&lt;br /&gt;
        return;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    semaphore sem = semaphore(0);&lt;br /&gt;
    stack[prio].push(sem);&lt;br /&gt;
    mutex.V();&lt;br /&gt;
    sem.P();&lt;br /&gt;
&lt;br /&gt;
    mutex.V();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void PLV() {&lt;br /&gt;
    mutex.P();&lt;br /&gt;
    &lt;br /&gt;
    for (int i = MAX_PRIORITY - 1; i &amp;gt;= 0; i--) {&lt;br /&gt;
        if (stack[i].size() &amp;gt; 0) {&lt;br /&gt;
            sem = stack[i].pop();&lt;br /&gt;
            sem.V();&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    num_V++;&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;
&lt;br /&gt;
= Prova 2021/05/26 =&lt;br /&gt;
&lt;br /&gt;
== Consegna c1 == &lt;br /&gt;
&lt;br /&gt;
Esercizio c.1: Un buffer sincrono strampalato (bss) ha due procedure entry:&lt;br /&gt;
void put(T value)&lt;br /&gt;
list of T get(void)&lt;br /&gt;
La entry put viene utilizzata per aggiungere un elemento e la entry get per leggere tutti quelli disponibili.&lt;br /&gt;
Se più processi chiamano la put quando nessun processo è in attesa per una get, rimangono tutti bloccati.&lt;br /&gt;
Quando successivamente un processo chiama la get riceve la lista di tutti gli elementi inseriti con le put e&lt;br /&gt;
tutti i processi vengono sbloccati.&lt;br /&gt;
Se il buffer è vuoto tutti i processi che chiamano la get rimangono bloccati. quando un processo chiama&lt;br /&gt;
successivamente la put tutti i processi in attesa per la get si sbloccano e ricevono lo stesso valore di ritorno:&lt;br /&gt;
una lista contenente il solo valore passato come parametro alla put. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Soluzione proposta 1 ===&lt;br /&gt;
&lt;br /&gt;
Soluzione proposta da [https://so.v2.cs.unibo.it/wiki/index.php/User:Flecart Flecart]&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
int num = 0; // se è positiva rappresenta numero di gets che aspettano, se negativa, numero di puts&lt;br /&gt;
semaphore semput(0);&lt;br /&gt;
semaphore semget(0);&lt;br /&gt;
semaphore mutex(1);&lt;br /&gt;
list&amp;lt;T&amp;gt; global_list;&lt;br /&gt;
&lt;br /&gt;
void put(T value) {&lt;br /&gt;
    //&amp;lt; await(num &amp;gt; 0) --&amp;gt; global_list.add(value) &amp;gt;&lt;br /&gt;
    mutex.P();&lt;br /&gt;
    if (num &amp;lt;= 0) {&lt;br /&gt;
        num--;&lt;br /&gt;
        mutex.V();&lt;br /&gt;
        semput.P();&lt;br /&gt;
        num++;&lt;br /&gt;
    }&lt;br /&gt;
    global_list.add(value);&lt;br /&gt;
&lt;br /&gt;
    if (num &amp;lt; 0)&lt;br /&gt;
        semput.V();&lt;br /&gt;
    else &lt;br /&gt;
        semget.V();&lt;br /&gt;
&lt;br /&gt;
    return;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
list of T get() {&lt;br /&gt;
    list&amp;lt;T&amp;gt; local_list;&lt;br /&gt;
&lt;br /&gt;
    mutex.P();&lt;br /&gt;
    if (num &amp;gt;= 0) {&lt;br /&gt;
        num++;&lt;br /&gt;
        mutex.V();&lt;br /&gt;
        semget.P();&lt;br /&gt;
        num--;&lt;br /&gt;
    } else {&lt;br /&gt;
        semput.V();&lt;br /&gt;
        semget.P();&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    local_list = global_list; // fa deep copy&lt;br /&gt;
&lt;br /&gt;
    if (num &amp;gt; 0) {&lt;br /&gt;
        semget.V();&lt;br /&gt;
    } else {&lt;br /&gt;
        global_list = list&amp;lt;T&amp;gt;();&lt;br /&gt;
        mutex.V(); &lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    return local_list;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&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:Gio Gio]&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
class bss{&lt;br /&gt;
  int waiting_put=0;&lt;br /&gt;
  int waiting_get=0;&lt;br /&gt;
  cond cw,cg;&lt;br /&gt;
  queue&amp;lt;T&amp;gt; q;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
  void put(T value){&lt;br /&gt;
    q.push(T);&lt;br /&gt;
    if(waiting_get&amp;gt;0){&lt;br /&gt;
      cg.signal()&lt;br /&gt;
    }else{&lt;br /&gt;
      waiting_put++;&lt;br /&gt;
      cw.wait();&lt;br /&gt;
      waiting_put--;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  list&amp;lt;T&amp;gt; get(){&lt;br /&gt;
    if(waiting_put&amp;gt;0){&lt;br /&gt;
      while(waiting_put&amp;gt;0){&lt;br /&gt;
        cw.signal();&lt;br /&gt;
      }&lt;br /&gt;
    }else{&lt;br /&gt;
      waiting_get++;&lt;br /&gt;
      cg.wait();&lt;br /&gt;
      waiting_get--;&lt;br /&gt;
    }&lt;br /&gt;
    list&amp;lt;T&amp;gt; p= q.tolist();&lt;br /&gt;
    if(waiting_get&amp;gt;0){&lt;br /&gt;
      cg.signal();&lt;br /&gt;
    }&lt;br /&gt;
    q.removeAll();&lt;br /&gt;
    return p;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== esercizio c2 == &lt;br /&gt;
&lt;br /&gt;
Dato un servizio di message passing asincrono implementare un servizio di message passing&lt;br /&gt;
asincrono a selezione di mittenti (samp) senza fare uso di processi server.&lt;br /&gt;
Il servizio samp ha due primitive:&lt;br /&gt;
sasend(message , destination)&lt;br /&gt;
sarecv(senders)&lt;br /&gt;
dove senders è un insieme.&lt;br /&gt;
la sarecv restituisce il primo messaggio che uno dei processi in senders ha spedito al processo ricevente&lt;br /&gt;
usando la sasend (o spedito da qualsiasi processo se senders è vuoto).&lt;br /&gt;
&lt;br /&gt;
=== Soluzione proposta 1 === &lt;br /&gt;
&lt;br /&gt;
Soluzione proposta da [[User:Flecart|Flecart]] ([[User talk:Flecart|talk]]) 15:29, 15 January 2023 (CET)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
sasend(message, destination) {&lt;br /&gt;
	pid t = getpid();&lt;br /&gt;
	asend(&amp;lt;message, t&amp;gt;, destination);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// variabile privata di sarecv&lt;br /&gt;
queue all_messages[MAX_PROC];&lt;br /&gt;
&lt;br /&gt;
// stora tutti i messaggi ricevuti, lo utilizziamo come queue per tutti, con &lt;br /&gt;
// anche la possibilità di rimuovere in un punto a scelta.&lt;br /&gt;
vector&amp;lt;&amp;lt;messages, pid&amp;gt;&amp;gt; msg; &lt;br /&gt;
sarecv(senders) {&lt;br /&gt;
	if (senders.len() == 0) {&lt;br /&gt;
		if (msg.len() == 0) {&lt;br /&gt;
			&amp;lt;message, sender&amp;gt; = arecv(ANY);&lt;br /&gt;
			return message;&lt;br /&gt;
		} else {&lt;br /&gt;
			&amp;lt;message, sender&amp;gt; = msg.pop_back();&lt;br /&gt;
			return message;&lt;br /&gt;
		}&lt;br /&gt;
	} else {&lt;br /&gt;
		do {&lt;br /&gt;
			for (idx in senders) {&lt;br /&gt;
				if (all_messages[idx].size() &amp;gt; 0) {&lt;br /&gt;
					message = all_messages[idx].dequeue();&lt;br /&gt;
					// rimuove il singolo messaggio dal vector, non tutti quelli uguali.&lt;br /&gt;
					msg.remove(&amp;lt;message, idx&amp;gt;);&lt;br /&gt;
					return message;&lt;br /&gt;
				}&lt;br /&gt;
			}	&lt;br /&gt;
			&lt;br /&gt;
			&amp;lt;message, sender&amp;gt; = arecv(ANY);&lt;br /&gt;
			msg.push_back(&amp;lt;message, sender&amp;gt;);&lt;br /&gt;
			all_messages[sender].enqueue(&amp;lt;message&amp;gt;);&lt;br /&gt;
		} while(true);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Gio</name></author>
	</entry>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=Prove_scritte_2021&amp;diff=2902</id>
		<title>Prove scritte 2021</title>
		<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php?title=Prove_scritte_2021&amp;diff=2902"/>
		<updated>2023-01-16T16:27:15Z</updated>

		<summary type="html">&lt;p&gt;Gio: /* Esercizio C1 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
= Prova 21/07/2021=&lt;br /&gt;
&lt;br /&gt;
== Es C1 (da correggere) == &lt;br /&gt;
&lt;br /&gt;
Soluzione proposta da [https://so.v2.cs.unibo.it/wiki/index.php/User:Flecart Flecart friend],regalo a flecart la proprietà intellettuale di questa soluzione&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
class node{&lt;br /&gt;
  node parent;&lt;br /&gt;
  sq sq1;&lt;br /&gt;
  cond c;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
class BinTree{&lt;br /&gt;
  vector&amp;lt;node&amp;gt; base;&lt;br /&gt;
  void create(int N){&lt;br /&gt;
    base=new vector&amp;lt;node&amp;gt;(2^N);&lt;br /&gt;
    for(int i=0;i&amp;lt;2^N;i++)&lt;br /&gt;
      base[i]=new node(null,0,new cond);&lt;br /&gt;
    for(int i=1;i&amp;lt;=N;i++){&lt;br /&gt;
      for(int j=0;j&amp;lt;2^(N-i);j++){&lt;br /&gt;
        get(j,i-1).parent=get(j+i,i-1).parent=new node(null,0,new cond);&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  node get(int i,int level){&lt;br /&gt;
    return get(base[i],level);&lt;br /&gt;
  }&lt;br /&gt;
  node get(node n,int level){&lt;br /&gt;
    if(level==0){&lt;br /&gt;
      return node;&lt;br /&gt;
    }&lt;br /&gt;
    return get(node.parent,level-1);&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class Torneo{&lt;br /&gt;
  BinTree bin(N);&lt;br /&gt;
  int forma[2^N];&lt;br /&gt;
  bool win;&lt;br /&gt;
&lt;br /&gt;
  bool gioca(int i,int turno,int forma){&lt;br /&gt;
    forma[i]=forma;&lt;br /&gt;
    if null==bin.get(i,turno).sq1{&lt;br /&gt;
      bin.get(i,turno).sq1=i;&lt;br /&gt;
      bin.get(i,turno).c.wait();&lt;br /&gt;
      return !win;&lt;br /&gt;
    }else{&lt;br /&gt;
      sq1= bin.get(i,turno).sq1;&lt;br /&gt;
      if(forma[sq1]==forma[i]){&lt;br /&gt;
        win=random();&lt;br /&gt;
      }else{&lt;br /&gt;
        win=forma[sq1]&amp;lt;forma[i];&lt;br /&gt;
      }&lt;br /&gt;
      bin.get(i,turno).signal();&lt;br /&gt;
    }&lt;br /&gt;
    return win;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Prova 2021/09/15 =&lt;br /&gt;
&lt;br /&gt;
== Esercizio C1 == &lt;br /&gt;
&lt;br /&gt;
=== Consegna === &lt;br /&gt;
Esercizio c.1: Scrivere il monitor alrv (at least rendez-vous) che fornisce una sola procedure entry:&lt;br /&gt;
procedure entry void at_least(int n)&lt;br /&gt;
Quando un processo chiama la funzione at_least vuol dire che vuole sincronizzarsi con un insieme di almeno n&lt;br /&gt;
processi (incluso il chiamante).&lt;br /&gt;
Esempi:&lt;br /&gt;
Se un processo chiama at_least(1) non si blocca.&lt;br /&gt;
Se il processo p chiama at_least(2) si blocca, se poi il processo q chiama at_least(2) oppure at_least(1) si&lt;br /&gt;
sbloccano sia p sia q (la richiesta di p è soddisfatta, ne aspettava almeno 2, p e q)&lt;br /&gt;
Se il processo p chiama at_least(2) si blocca, se poi il processo q chiama at_least(3) si blocca anch'esso perché&lt;br /&gt;
sebbene la richiesta di p possa essere soddisfatta, q non può ancora sbloccarsi: ci sono solo 2 processi in attesa mentre&lt;br /&gt;
q ne vuole 3. Un terzo processo che chiami at_least(x) con x=1,2,3 li sblocca tutti.&lt;br /&gt;
Hint: sia w[k ] il numero dei processi in attesa di essere in almeno k (quelli che hanno chiamato at_least(k) e non&lt;br /&gt;
hanno completato l'esecuzione della funzione). Sia s[n]=∑&lt;br /&gt;
k=1&lt;br /&gt;
n&lt;br /&gt;
w[k ] (rappresenta il numero di processi soddisfacibili:&lt;br /&gt;
e.g. se ci sono 4 processi in attesa, potrebbero essere soddisfatte le richieste dei processi che ne aspettano almeno 2,&lt;br /&gt;
almeno 3 o almeno 4). Preso, se esiste, il massimo indice m tale che s[m]≥m tutti i processi in attesa di essere in n,&lt;br /&gt;
per n≤m possono essere sbloccati.&lt;br /&gt;
&lt;br /&gt;
=== 1. Soluzione proposta ===&lt;br /&gt;
Soluzione proposta da [https://so.v2.cs.unibo.it/wiki/index.php/User:Flecart Flecart]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
extern int MAX;  // il massimo numero di attesa&lt;br /&gt;
monitor alrv {&lt;br /&gt;
	int w[MAX];&lt;br /&gt;
	int s[MAX];&lt;br /&gt;
	condition c[MAX];&lt;br /&gt;
&lt;br /&gt;
	init() {&lt;br /&gt;
		for (int i = 0; i &amp;lt; MAX; i++) {&lt;br /&gt;
			w[i] = s[i] = 0;&lt;br /&gt;
		}&lt;br /&gt;
	}	&lt;br /&gt;
&lt;br /&gt;
procedure entry void at_least(int n) {&lt;br /&gt;
	if (n &amp;gt;= MAX || n &amp;lt;= 0) raise error;&lt;br /&gt;
	&lt;br /&gt;
	int i;&lt;br /&gt;
	for (i = n; i &amp;lt; MAX; i++) s[i]++;&lt;br /&gt;
	&lt;br /&gt;
	for (i = MAX - 1; i &amp;gt; 0; i--) {&lt;br /&gt;
		if (s[i] &amp;gt;= i) break;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	if (i &amp;gt; 0) {&lt;br /&gt;
		for (int j = 0; j &amp;lt;= i; j++) {&lt;br /&gt;
			while (w[j] &amp;gt; 0) {&lt;br /&gt;
				c[j].signal();&lt;br /&gt;
				w[j]--;&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
		&lt;br /&gt;
		s[0] = 0;&lt;br /&gt;
		for (int i = 1; i &amp;lt; MAX; i++) {&lt;br /&gt;
			s[i] = w[i] + s[i - 1];&lt;br /&gt;
		}&lt;br /&gt;
	} else {&lt;br /&gt;
		w[n]++;&lt;br /&gt;
		c[n].wait();&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Soluzione proposta da [https://so.v2.cs.unibo.it/wiki/index.php/User:Flecart Flecart friend],regalo a flecart la proprietà intellettuale di questa soluzione&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
class Monitor{&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
  min_heap&amp;lt;(int,cond)&amp;gt; h;&lt;br /&gt;
&lt;br /&gt;
  void at_least(int n){&lt;br /&gt;
    int sum=0;&lt;br /&gt;
    int max_to_sblock= -INF;&lt;br /&gt;
    cond c = new cond(n);&lt;br /&gt;
    h.push((n,c));&lt;br /&gt;
    // la heap viene visitata in maniera crescente&lt;br /&gt;
    for(auto f=h.begin_iter();null!=f.next();f++) {&lt;br /&gt;
        sum++;&lt;br /&gt;
        if(f.0&amp;lt;=sum){&lt;br /&gt;
          max_to_sblock =f.0;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    for(auto f=h.begin_iter();null!=f.next();f++) {&lt;br /&gt;
        if(f.0&amp;lt;=max_to_sblock){&lt;br /&gt;
          f.1.signal();&lt;br /&gt;
          h.remove(c);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    if(n&amp;gt;max_to_sblock){&lt;br /&gt;
      c.wait();&lt;br /&gt;
    }&lt;br /&gt;
    free(c)&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Prova 2021/06/23 =&lt;br /&gt;
&lt;br /&gt;
== Esercizio C1 == &lt;br /&gt;
&lt;br /&gt;
=== Consegna === &lt;br /&gt;
Esercizio c.1: Scrivere il monitor delayvalue con una sola procedure entry:&lt;br /&gt;
  int delay(int value);&lt;br /&gt;
Il monitor deve sospendere i primi NDELAY processi che chiamano la delay. Le successive chiamate di delay&lt;br /&gt;
devono mantenere costante il numero di processi sospesi, ogni successiva chiamata devo riattivare il primo&lt;br /&gt;
processo in attesa prima di sospendersi, la delay ritorna il valore passato come parametro dal processo che&lt;br /&gt;
ne ha riattivato l'esecuzione. e.g. se NDELAY è 2:&lt;br /&gt;
  P1: delay(44) -&amp;gt; P1 si sospende&lt;br /&gt;
  P2: delay(40) -&amp;gt; P2 si sospende&lt;br /&gt;
  P3: delay(42) -&amp;gt; P1 si riattiva e ritorna 42, P3 si sospende&lt;br /&gt;
  P4: delay(22) -&amp;gt; P2 si riattiva e ritorna 22, P4 si sospende&lt;br /&gt;
&lt;br /&gt;
=== Soluzione proposta 1 ===&lt;br /&gt;
Soluzione proposta da [https://so.v2.cs.unibo.it/wiki/index.php/User:Flecart Flecart], da controllare&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// variabile definita altrove.&lt;br /&gt;
extern int NDELAY;&lt;br /&gt;
&lt;br /&gt;
class Monitor {&lt;br /&gt;
    Queue&amp;lt;condition&amp;gt; stopped;&lt;br /&gt;
    int curr_value;&lt;br /&gt;
    Monitor {&lt;br /&gt;
        stopped = Queue&amp;lt;condition&amp;gt;();&lt;br /&gt;
        curr_value = 0;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    int delay(int value) {&lt;br /&gt;
        curr_value = value;&lt;br /&gt;
        if (stopped.size() == NDELAY) {&lt;br /&gt;
            condition first = stopped.dequeue();&lt;br /&gt;
            first.signal();&lt;br /&gt;
        }&lt;br /&gt;
        condition c = new condition();&lt;br /&gt;
        stopped.enqueue(c);&lt;br /&gt;
        c.wait();    &lt;br /&gt;
&lt;br /&gt;
        return curr_value;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Soluzione proposta 1 ===&lt;br /&gt;
Soluzione proposta da [https://so.v2.cs.unibo.it/wiki/index.php/User:Flecart Flecart friend], regalo la proprietà intellettuale a flecart. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
monitor dalayvalue{&lt;br /&gt;
&lt;br /&gt;
#define NDELAY 22&lt;br /&gt;
  int blocked=0;&lt;br /&gt;
  int lastvalue=0;&lt;br /&gt;
  cond c;&lt;br /&gt;
&lt;br /&gt;
  int dalay(int value){&lt;br /&gt;
    lastvalue=value;&lt;br /&gt;
    if(blocked&amp;lt;NDELAY){&lt;br /&gt;
      blocked++;&lt;br /&gt;
      c.wait();&lt;br /&gt;
    }else if(blocked==NDELAY){&lt;br /&gt;
      c.signal();&lt;br /&gt;
      c.wait();&lt;br /&gt;
    }&lt;br /&gt;
    return lastvalue;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Esercizio c2 ==&lt;br /&gt;
&lt;br /&gt;
=== Consegna ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Esercizio c.2: Implementare usando semafori ordinari (fair, fifo) un servizio di semafori a priorità lifo che&lt;br /&gt;
fornisca le seguenti primitive:&lt;br /&gt;
 void PLP(int prio);&lt;br /&gt;
 void PLV()&lt;br /&gt;
PLP e PLV si devono comportare rispettivamente come P e V. Quando la PLV deve riattivare un processo&lt;br /&gt;
sceglie fra quelli in attesa quello a priorità massima, nel caso siano presenti più processi a priorità massima&lt;br /&gt;
sceglie quello in attesa da meno tempo. &lt;br /&gt;
&lt;br /&gt;
=== Soluzione proposta 1 ===&lt;br /&gt;
&lt;br /&gt;
Esercizio c2 (da controllare) da Flecart.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Stack&amp;lt;semaphore&amp;gt; stack[MAX_PRIORITY];&lt;br /&gt;
int num_V = 0;&lt;br /&gt;
semaphore mutex(1);&lt;br /&gt;
&lt;br /&gt;
void  PLP(int prio) {&lt;br /&gt;
    mutex.P();&lt;br /&gt;
    if (num_V &amp;gt; 0) {&lt;br /&gt;
        num_V--;&lt;br /&gt;
        mutex.V();&lt;br /&gt;
        return;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    semaphore sem = semaphore(0);&lt;br /&gt;
    stack[prio].push(sem);&lt;br /&gt;
    mutex.V();&lt;br /&gt;
    sem.P();&lt;br /&gt;
&lt;br /&gt;
    mutex.V();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void PLV() {&lt;br /&gt;
    mutex.P();&lt;br /&gt;
    &lt;br /&gt;
    for (int i = MAX_PRIORITY - 1; i &amp;gt;= 0; i--) {&lt;br /&gt;
        if (stack[i].size() &amp;gt; 0) {&lt;br /&gt;
            sem = stack[i].pop();&lt;br /&gt;
            sem.V();&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    num_V++;&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;
&lt;br /&gt;
= Prova 2021/05/26 =&lt;br /&gt;
&lt;br /&gt;
== Consegna c1 == &lt;br /&gt;
&lt;br /&gt;
Esercizio c.1: Un buffer sincrono strampalato (bss) ha due procedure entry:&lt;br /&gt;
void put(T value)&lt;br /&gt;
list of T get(void)&lt;br /&gt;
La entry put viene utilizzata per aggiungere un elemento e la entry get per leggere tutti quelli disponibili.&lt;br /&gt;
Se più processi chiamano la put quando nessun processo è in attesa per una get, rimangono tutti bloccati.&lt;br /&gt;
Quando successivamente un processo chiama la get riceve la lista di tutti gli elementi inseriti con le put e&lt;br /&gt;
tutti i processi vengono sbloccati.&lt;br /&gt;
Se il buffer è vuoto tutti i processi che chiamano la get rimangono bloccati. quando un processo chiama&lt;br /&gt;
successivamente la put tutti i processi in attesa per la get si sbloccano e ricevono lo stesso valore di ritorno:&lt;br /&gt;
una lista contenente il solo valore passato come parametro alla put. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Soluzione proposta 1 ===&lt;br /&gt;
&lt;br /&gt;
Soluzione proposta da [https://so.v2.cs.unibo.it/wiki/index.php/User:Flecart Flecart]&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
int num = 0; // se è positiva rappresenta numero di gets che aspettano, se negativa, numero di puts&lt;br /&gt;
semaphore semput(0);&lt;br /&gt;
semaphore semget(0);&lt;br /&gt;
semaphore mutex(1);&lt;br /&gt;
list&amp;lt;T&amp;gt; global_list;&lt;br /&gt;
&lt;br /&gt;
void put(T value) {&lt;br /&gt;
    //&amp;lt; await(num &amp;gt; 0) --&amp;gt; global_list.add(value) &amp;gt;&lt;br /&gt;
    mutex.P();&lt;br /&gt;
    if (num &amp;lt;= 0) {&lt;br /&gt;
        num--;&lt;br /&gt;
        mutex.V();&lt;br /&gt;
        semput.P();&lt;br /&gt;
        num++;&lt;br /&gt;
    }&lt;br /&gt;
    global_list.add(value);&lt;br /&gt;
&lt;br /&gt;
    if (num &amp;lt; 0)&lt;br /&gt;
        semput.V();&lt;br /&gt;
    else &lt;br /&gt;
        semget.V();&lt;br /&gt;
&lt;br /&gt;
    return;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
list of T get() {&lt;br /&gt;
    list&amp;lt;T&amp;gt; local_list;&lt;br /&gt;
&lt;br /&gt;
    mutex.P();&lt;br /&gt;
    if (num &amp;gt;= 0) {&lt;br /&gt;
        num++;&lt;br /&gt;
        mutex.V();&lt;br /&gt;
        semget.P();&lt;br /&gt;
        num--;&lt;br /&gt;
    } else {&lt;br /&gt;
        semput.V();&lt;br /&gt;
        semget.P();&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    local_list = global_list; // fa deep copy&lt;br /&gt;
&lt;br /&gt;
    if (num &amp;gt; 0) {&lt;br /&gt;
        semget.V();&lt;br /&gt;
    } else {&lt;br /&gt;
        global_list = list&amp;lt;T&amp;gt;();&lt;br /&gt;
        mutex.V(); &lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    return local_list;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&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:Gio Gio]&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
class bss{&lt;br /&gt;
  int waiting_put=0;&lt;br /&gt;
  int waiting_get=0;&lt;br /&gt;
  cond cw,cg;&lt;br /&gt;
  queue&amp;lt;T&amp;gt; q;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
  void put(T value){&lt;br /&gt;
    q.push(T);&lt;br /&gt;
    if(waiting_get&amp;gt;0){&lt;br /&gt;
      cg.signal()&lt;br /&gt;
    }else{&lt;br /&gt;
      waiting_put++;&lt;br /&gt;
      cw.wait();&lt;br /&gt;
      waiting_put--;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  list&amp;lt;T&amp;gt; get(){&lt;br /&gt;
    if(waiting_put&amp;gt;0){&lt;br /&gt;
      while(waiting_put&amp;gt;0){&lt;br /&gt;
        cw.signal();&lt;br /&gt;
      }&lt;br /&gt;
    }else{&lt;br /&gt;
      waiting_get++;&lt;br /&gt;
      cg.wait();&lt;br /&gt;
      waiting_get--;&lt;br /&gt;
    }&lt;br /&gt;
    list&amp;lt;T&amp;gt; p= q.tolist();&lt;br /&gt;
    if(waiting_get&amp;gt;0){&lt;br /&gt;
      cg.signal();&lt;br /&gt;
    }&lt;br /&gt;
    q.removeAll();&lt;br /&gt;
    return p;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== esercizio c2 == &lt;br /&gt;
&lt;br /&gt;
Dato un servizio di message passing asincrono implementare un servizio di message passing&lt;br /&gt;
asincrono a selezione di mittenti (samp) senza fare uso di processi server.&lt;br /&gt;
Il servizio samp ha due primitive:&lt;br /&gt;
sasend(message , destination)&lt;br /&gt;
sarecv(senders)&lt;br /&gt;
dove senders è un insieme.&lt;br /&gt;
la sarecv restituisce il primo messaggio che uno dei processi in senders ha spedito al processo ricevente&lt;br /&gt;
usando la sasend (o spedito da qualsiasi processo se senders è vuoto).&lt;br /&gt;
&lt;br /&gt;
=== Soluzione proposta 1 === &lt;br /&gt;
&lt;br /&gt;
Soluzione proposta da [[User:Flecart|Flecart]] ([[User talk:Flecart|talk]]) 15:29, 15 January 2023 (CET)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
sasend(message, destination) {&lt;br /&gt;
	pid t = getpid();&lt;br /&gt;
	asend(&amp;lt;message, t&amp;gt;, destination);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// variabile privata di sarecv&lt;br /&gt;
queue all_messages[MAX_PROC];&lt;br /&gt;
&lt;br /&gt;
// stora tutti i messaggi ricevuti, lo utilizziamo come queue per tutti, con &lt;br /&gt;
// anche la possibilità di rimuovere in un punto a scelta.&lt;br /&gt;
vector&amp;lt;&amp;lt;messages, pid&amp;gt;&amp;gt; msg; &lt;br /&gt;
sarecv(senders) {&lt;br /&gt;
	if (senders.len() == 0) {&lt;br /&gt;
		if (msg.len() == 0) {&lt;br /&gt;
			&amp;lt;message, sender&amp;gt; = arecv(ANY);&lt;br /&gt;
			return message;&lt;br /&gt;
		} else {&lt;br /&gt;
			&amp;lt;message, sender&amp;gt; = msg.pop_back();&lt;br /&gt;
			return message;&lt;br /&gt;
		}&lt;br /&gt;
	} else {&lt;br /&gt;
		do {&lt;br /&gt;
			for (idx in senders) {&lt;br /&gt;
				if (all_messages[idx].size() &amp;gt; 0) {&lt;br /&gt;
					message = all_messages[idx].dequeue();&lt;br /&gt;
					// rimuove il singolo messaggio dal vector, non tutti quelli uguali.&lt;br /&gt;
					msg.remove(&amp;lt;message, idx&amp;gt;);&lt;br /&gt;
					return message;&lt;br /&gt;
				}&lt;br /&gt;
			}	&lt;br /&gt;
			&lt;br /&gt;
			&amp;lt;message, sender&amp;gt; = arecv(ANY);&lt;br /&gt;
			msg.push_back(&amp;lt;message, sender&amp;gt;);&lt;br /&gt;
			all_messages[sender].enqueue(&amp;lt;message&amp;gt;);&lt;br /&gt;
		} while(true);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Gio</name></author>
	</entry>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=Prove_scritte_2020&amp;diff=2900</id>
		<title>Prove scritte 2020</title>
		<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php?title=Prove_scritte_2020&amp;diff=2900"/>
		<updated>2023-01-16T13:43:03Z</updated>

		<summary type="html">&lt;p&gt;Gio: /* Prova 2020/01/15 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Prova 2020/01/15 =&lt;br /&gt;
&lt;br /&gt;
== esercizio c1 == &lt;br /&gt;
&lt;br /&gt;
=== Soluzione proposta 1 ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
class TS{&lt;br /&gt;
&lt;br /&gt;
  int v=0;&lt;br /&gt;
  queue&amp;lt;(unsigned int,cond)&amp;gt; pq;&lt;br /&gt;
  usinged int timer;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
  void V(){&lt;br /&gt;
    if(pq.empty()){&lt;br /&gt;
      v++;&lt;br /&gt;
    }else{&lt;br /&gt;
      pq.pop().signal();&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  bool P(unsigned int timeout){&lt;br /&gt;
    if(v == 0){&lt;br /&gt;
      cond c = new condition();&lt;br /&gt;
      pq.push((timeout+timer,));&lt;br /&gt;
      c.wait();&lt;br /&gt;
      free(c);&lt;br /&gt;
      if timer== timeout+timer{&lt;br /&gt;
        return true;&lt;br /&gt;
      }&lt;br /&gt;
    }else{&lt;br /&gt;
      v--;&lt;br /&gt;
    }&lt;br /&gt;
    return false;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  void tick(){&lt;br /&gt;
    timer++;&lt;br /&gt;
    for [i,c] in pq.iter(){&lt;br /&gt;
      if( i &amp;lt;= timer) {&lt;br /&gt;
        c.signal();&lt;br /&gt;
        // la nostra stuttura dati supporta la rimozione durante lo scorrimento&lt;br /&gt;
        // per esempio può essere una lista&lt;br /&gt;
        pq.remove(c);&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;
=== Soluzione proposta 2 ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int value;&lt;br /&gt;
boolean ret_val;&lt;br /&gt;
int time;&lt;br /&gt;
min_heap&amp;lt;int, condition&amp;gt; heap;  // ordinato sul tempo minore.&lt;br /&gt;
vector&amp;lt;condition&amp;gt; queue; // vector utilizzato come queue, con rimozione anche nel mezzo.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
monitor {&lt;br /&gt;
	value = 0;&lt;br /&gt;
	time = 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void V(void) {&lt;br /&gt;
	if (heap.size() &amp;gt; 0) {&lt;br /&gt;
		condition c = queue.pop_back(); // remove and return&lt;br /&gt;
		heap.remove(c);  // rimuovi l'unico elemento con c.&lt;br /&gt;
		ret_val = true;&lt;br /&gt;
		c.signal();&lt;br /&gt;
	} else {&lt;br /&gt;
		value++;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
boolean P(unsigned int timeout) {	&lt;br /&gt;
	if (value &amp;gt; 0) {&lt;br /&gt;
		value--;&lt;br /&gt;
		return true;&lt;br /&gt;
	} else {&lt;br /&gt;
		int next_time = timeout + time;&lt;br /&gt;
		condition c = new condition();&lt;br /&gt;
		heap.insert(&amp;lt;next_time, c&amp;gt;);&lt;br /&gt;
		queue.push_back(c);&lt;br /&gt;
		c.wait();&lt;br /&gt;
		free(c);&lt;br /&gt;
		&lt;br /&gt;
		return ret_val;	&lt;br /&gt;
	}	&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void tick(void) {&lt;br /&gt;
	ret_val = false;&lt;br /&gt;
	time++;&lt;br /&gt;
	while (heap.size() &amp;gt; 0 &amp;amp;&amp;amp; heap.top().0 &amp;lt;= time) {&lt;br /&gt;
		condition c = heap.top().1;&lt;br /&gt;
		heap.deleteTop();&lt;br /&gt;
		queue.remove(c);&lt;br /&gt;
		c.signal();&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== esercizio c2 ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Soluzione proposta 1 (da controllare)===&lt;br /&gt;
&lt;br /&gt;
[[User:Gio|Gio]] ([[User talk:Gio|talk]]) 14:43, 16 January 2023 (CET)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
void multisend(pid_t destination,T msg,int times){&lt;br /&gt;
  for(int i=0;i&amp;lt;n;i++){&lt;br /&gt;
    asend(&amp;lt;n-i,getpid(),msg&amp;gt;,destination);&lt;br /&gt;
    ack=arecv(destination)&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
T multirecv(pid_t sender){&lt;br /&gt;
  int i;&lt;br /&gt;
  if(sender==ANY){&lt;br /&gt;
    //assegna il pid preso da a recv a sender&lt;br /&gt;
    &amp;lt;i, sender, msg&amp;gt;=arecv(ANY);&lt;br /&gt;
  }else{&lt;br /&gt;
    &amp;lt;i, sender, msg&amp;gt;=arecv(sender);&lt;br /&gt;
  }&lt;br /&gt;
  asend(ack,sender);&lt;br /&gt;
  i--;&lt;br /&gt;
  while(i&amp;gt;0)&lt;br /&gt;
    &amp;lt;j, sender, msg&amp;gt;=arecv(sender);&lt;br /&gt;
    asend(ack,sender);&lt;br /&gt;
    i--;&lt;br /&gt;
    assert(i==j);&lt;br /&gt;
  }&lt;br /&gt;
  return msg;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Prova 2020/02/20 =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== esercizio c2 ==&lt;br /&gt;
&lt;br /&gt;
Sol : x alla seconda&lt;/div&gt;</summary>
		<author><name>Gio</name></author>
	</entry>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=Prove_scritte_2019&amp;diff=2899</id>
		<title>Prove scritte 2019</title>
		<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php?title=Prove_scritte_2019&amp;diff=2899"/>
		<updated>2023-01-16T13:10:55Z</updated>

		<summary type="html">&lt;p&gt;Gio: /* Esercizio c.2 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Esame 18/06/2019 ==&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2019.06.18.tot.pdf 2019.06.18.tot.pdf]&lt;br /&gt;
=== Esercizio c.1 (da controllare) ===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
monitor pg{&lt;br /&gt;
&lt;br /&gt;
  int waitingReader = 0;&lt;br /&gt;
  int waitingWriter = 0;&lt;br /&gt;
&lt;br /&gt;
  condition ok2write;&lt;br /&gt;
  condition ok2read;&lt;br /&gt;
&lt;br /&gt;
  T datobuf;&lt;br /&gt;
&lt;br /&gt;
  entry put (T dato) {&lt;br /&gt;
&lt;br /&gt;
    if (waitingReader &amp;gt; 0)&lt;br /&gt;
      datobuf = dato;&lt;br /&gt;
      while (waitingReader &amp;gt; 0)&lt;br /&gt;
        ok2read.signal();&lt;br /&gt;
    else if (waitingWriter &amp;gt;= 0)&lt;br /&gt;
      waitingWriter++;&lt;br /&gt;
      ok2write.wait();&lt;br /&gt;
      waitingWriter--;&lt;br /&gt;
      datobuf = dato;&lt;br /&gt;
&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  entry T get (void) {&lt;br /&gt;
&lt;br /&gt;
    if (waitingReader &amp;gt; 0 || waitingWriter == 0)&lt;br /&gt;
      waitingReader++;&lt;br /&gt;
      ok2read.wait();&lt;br /&gt;
      waitingReader--;&lt;br /&gt;
    else if (waitingWriter &amp;gt; 0) &lt;br /&gt;
      ok2write.signal();&lt;br /&gt;
      return datobuf;&lt;br /&gt;
    &lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&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;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
monitor taon {&lt;br /&gt;
condition ok2w, ok2r;&lt;br /&gt;
int nw, nr = 0;&lt;br /&gt;
T buf;&lt;br /&gt;
&lt;br /&gt;
entry  void put (T dato){&lt;br /&gt;
	nw++;&lt;br /&gt;
	if( nw != 1 || nr == 0)&lt;br /&gt;
             ok2w.wait();&lt;br /&gt;
	buf = dato;&lt;br /&gt;
	for (i=0, i++, i &amp;lt; nr)&lt;br /&gt;
	     ok2r.signal();&lt;br /&gt;
	nw--;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
entry T get(){&lt;br /&gt;
	nr++;&lt;br /&gt;
	if(nw==0)&lt;br /&gt;
	    ok2r.wait();&lt;br /&gt;
	ok2w.signal();&lt;br /&gt;
	T dato = buf;&lt;br /&gt;
	nr --;&lt;br /&gt;
	return dato;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.2 ===&lt;br /&gt;
**non è l'esercizio corretto**&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
/* MP sincrono dato quello asincrono */&lt;br /&gt;
&lt;br /&gt;
void ssend(obj msg, process q)&lt;br /&gt;
{&lt;br /&gt;
    asend(msg, q);&lt;br /&gt;
    ack = areceive(q);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
obj sreceive(process p)&lt;br /&gt;
{&lt;br /&gt;
    obj msg = areceive(p);&lt;br /&gt;
    asend(ack, p);&lt;br /&gt;
    return msg;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Soluzione:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
dati asend/arecv devo implementare lssend lsrecv&lt;br /&gt;
&lt;br /&gt;
lssend(dst, msg):&lt;br /&gt;
    asend(dst, (MSG, myid(), msg))&lt;br /&gt;
    arecv(dst)&lt;br /&gt;
&lt;br /&gt;
lsrecv(snd):&lt;br /&gt;
    asend(myid(), (TAG, myid(), NULL))    // mi mando un messaggio che riesco a riconoscere&lt;br /&gt;
    while True:&lt;br /&gt;
        (T, s, m) =  arecv(ANY)           // continua a ricevere finchè non ricevi il mio messaggio&lt;br /&gt;
        if (T != TAG) data.push(s, m)&lt;br /&gt;
        else break&lt;br /&gt;
    while (((s,m) = data.pop(snd) == NULL):   // c'è il messaggio di src definito?&lt;br /&gt;
        (T, s, m) =  arecv(ANY)&lt;br /&gt;
        data.push(s, m)&lt;br /&gt;
    asend(s, (ACK, myid(), NULL)&lt;br /&gt;
    return m&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Esercizio g.1 (sbagliato) ===&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
x = long_compute()/short_compute()&lt;br /&gt;
X = io()&lt;br /&gt;
&lt;br /&gt;
   0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3 3 3 3 3 3 3 3 3 4 4 4 4 4 4 4 4 4 4 5 5 5 5 5 5 5 5 5 5 6 6 6 6 6 6 6 6 6 6 7 7 7 7 7 7 7 7 7 7 8 8 8&lt;br /&gt;
   0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2&lt;br /&gt;
P1 |x|x|x|x|x|X|-|-|-|-|-|-|X|X|X|-|-|-|-|-|-|X|x|x|-|-|-|-|-|-|x|x|x|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|X|X|X|-|-|-|-|-|-|X|X|x|-|-|-|-|-|-|x|-|-|&lt;br /&gt;
P2         |-|-|x|x|x|-|-|-|-|-|-|x|x|-|-|-|-|-|-|-|X|X|X|-|-|-|-|-|-|X|X|x|-|-|-|-|-|-|x|x|x|-|-|-|-|-|-|x|-|-|-|-|-|-|-|-|X|X|X|-|-|-|-|-|-|X|X|x|-|-|-|x|-|-|&lt;br /&gt;
P3               |-|-|x|x|x|-|-|-|-|-|-|x|x|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|X|X|X|-|-|-|-|-|-|X|X|x|-|-|-|-|-|-|x|x|x|-|-|-|-|-|-|x|-|-|-|-|-|-|-|-|X|X|X|-|-|-|X|X|x|x|&lt;br /&gt;
 &amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Esercizio g.1 ===&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
P1(start=0): 5ms CPU, 5ms IO, 5ms CPU, 5ms IO, 2ms CPU&lt;br /&gt;
P2(start=4): 5ms CPU, 5ms IO, 5ms CPU, 5ms IO, 2ms CPU&lt;br /&gt;
P3(start=7): 5ms CPU, 5ms IO, 5ms CPU, 5ms IO, 2ms CPU&lt;br /&gt;
&lt;br /&gt;
 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3 3 3 3 3 3 3 3 3 4 4 4 4 4 4 4 4 4 4 5 &lt;br /&gt;
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 &lt;br /&gt;
P|1 1 1|1 1|2 2 2|3 3 3|2 2|1 1 1|3 3|1 1|2 2 2*3 3 3|2 2|3 3|1 1|-|2 2|- - -|3 3|&lt;br /&gt;
I          |1 1 1 1 1|     |2 2 2 2 2|3 3 3 3 3|1 1 1 1 1|2 2 2 2 2|3 3 3 3 3|&lt;br /&gt;
&lt;br /&gt;
r - - - - 2 - - 3 2 2 2 1 1 3 3 3 1 1 2 2 - - - 2 2 2 3 3 1 1&lt;br /&gt;
                      1 3 3&lt;br /&gt;
&lt;br /&gt;
* 3 ha finito input output e 2 è ancora in esecuzione quindi c'è da scegliere&lt;br /&gt;
 &amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Esercizio g.2 (da controllare) ===&lt;br /&gt;
# Può richiedere supporto hardware. Se implementato con contatori o stack questi devono essere aggiornati ad ogni riferimento alla memoria. L'intero sistema viene appesantito e rallentato.&lt;br /&gt;
# Il journaling si assicura che i dati sul filesystem siano consistenti, ma non aggiornati. Assicura la coerenza dei dati, ma non la perdita dei file se il filesystem si danneggia.&lt;br /&gt;
# Si dice che un programma A ha lo stesso potere espressivo di un programma B quando è possibile esprimere ogni programma scritto con B mediante A. Per implementare MP sincrono dato quello asincrono basta aggiungere una libreria. Per implementare MP asincrono dato quello sincrono bisogna aggiungere un processo server.&lt;br /&gt;
# In questi casi tutte le istruzioni vengono eseguite con la massima autorità, con problemi di sicurezza nel caso un utente estraneo prenda il controllo del sistema o rischio di commettere gravi errori semplicemente sbagliando a digitare un comando.&lt;br /&gt;
&lt;br /&gt;
== Esame 18/05/2019 ==&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2019.05.18.tot.pdf 2019.05.18.tot.pdf]&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.1 (da controllare) ===&lt;br /&gt;
&lt;br /&gt;
* Controllato dall'utente ? in data ?&lt;br /&gt;
* ...&lt;br /&gt;
&lt;br /&gt;
Il sorgente seguente può essere eseguito scaricando in una stessa directory il package [[Tool per semafori e monitor|pysm]] del prof. Davoli.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
#!/usr/bin/env python3&lt;br /&gt;
&lt;br /&gt;
import threading&lt;br /&gt;
&lt;br /&gt;
from array import array&lt;br /&gt;
from pysm.monitor import condition, entry, monitor&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class storage(monitor):&lt;br /&gt;
    ELEMS = 16&lt;br /&gt;
&lt;br /&gt;
    def __init__(self):&lt;br /&gt;
        &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
        Implementazione che permette l'avanzamento degli operai in presenza di&lt;br /&gt;
        altri operai in attesa.&lt;br /&gt;
        &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
        monitor.__init__(self)&lt;br /&gt;
        self._v = array('L', self.ELEMS * [0])&lt;br /&gt;
        self._c = tuple(condition(self) for i in self._v)&lt;br /&gt;
        # self._requests[i] = [l1, l2, ..., ln] se per l'attrezzo i ci sono in&lt;br /&gt;
        # attesa n processi che richiedono ciascuno l1, l2, ..., ln unita'&lt;br /&gt;
        self._requests = {i: list() for i in range(self.ELEMS)}&lt;br /&gt;
&lt;br /&gt;
    @entry&lt;br /&gt;
    def add(self, components):&lt;br /&gt;
        if len(components) != self.ELEMS:&lt;br /&gt;
            raise ValueError(&amp;quot;components must contain exactly ELEMS elements&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
        for i, c in enumerate(components):&lt;br /&gt;
            self._v[i] += c&lt;br /&gt;
&lt;br /&gt;
            # Finche' per il componente i ci sono richieste in sospeso che&lt;br /&gt;
            # possono essere soddisfatte, svegliamo il processo in attesa, che&lt;br /&gt;
            # proseguira' col richiedere i componenti successivi&lt;br /&gt;
            while self._requests[i] and self._requests[i][0] &amp;lt;= self._v[i]:&lt;br /&gt;
                self._c[i].signal()&lt;br /&gt;
&lt;br /&gt;
    @entry&lt;br /&gt;
    def get(self, components):&lt;br /&gt;
        if len(components) != self.ELEMS:&lt;br /&gt;
            raise ValueError(&amp;quot;components must contain exactly ELEMS elements&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
        for i in range(len(components)):&lt;br /&gt;
            if components[i] &amp;lt;= self._v[i]:&lt;br /&gt;
                self._v[i] -= components[i]&lt;br /&gt;
            else:&lt;br /&gt;
                components[i] -= self._v[i]&lt;br /&gt;
                self._v[i] = 0&lt;br /&gt;
&lt;br /&gt;
                self._requests[i].append(components[i])&lt;br /&gt;
                self._c[i].wait()&lt;br /&gt;
&lt;br /&gt;
                self._v[i] -= components[i]&lt;br /&gt;
                self._requests[i].pop(0)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def request(m, q):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    Funzione processo che simula la richiesta di un operaio.&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    name = threading.current_thread().name&lt;br /&gt;
&lt;br /&gt;
    print(&amp;quot;[%s] Requesting %s&amp;quot; % (name, q))&lt;br /&gt;
    m.get(q)&lt;br /&gt;
    print(&amp;quot;[%s] Done requesting&amp;quot; % (name))&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def supply(m, s):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    Funzione processo che simula il rifornimento di un magazziniere.&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    name = threading.current_thread().name&lt;br /&gt;
&lt;br /&gt;
    print(&amp;quot;[%s] Supplying %s&amp;quot; % (name, s))&lt;br /&gt;
    m.add(s)&lt;br /&gt;
    print(&amp;quot;[%s] Done supplying&amp;quot; % (name))&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    m = storage()&lt;br /&gt;
    requests = [&lt;br /&gt;
        threading.Thread(name='req1', target=request, args=(m, [4, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])),&lt;br /&gt;
        threading.Thread(name='req2', target=request, args=(m, [0, 0, 2, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])),&lt;br /&gt;
        threading.Thread(name='req3', target=request, args=(m, [4, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])),&lt;br /&gt;
        threading.Thread(name='req4', target=request, args=(m, [4, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])),&lt;br /&gt;
        threading.Thread(name='req5', target=request, args=(m, [4, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])),&lt;br /&gt;
    ]&lt;br /&gt;
    supplies = [&lt;br /&gt;
        threading.Thread(name='supply1', target=supply, args=(m, [4, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])),&lt;br /&gt;
        threading.Thread(name='supply2', target=supply, args=(m, [4, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])),&lt;br /&gt;
        threading.Thread(name='supply3', target=supply, args=(m, [4, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])),&lt;br /&gt;
        threading.Thread(name='supply4', target=supply, args=(m, [4, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])),&lt;br /&gt;
        threading.Thread(name='supply5', target=supply, args=(m, [0, 0, 2, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])),&lt;br /&gt;
    ]&lt;br /&gt;
&lt;br /&gt;
    for t in requests + supplies:&lt;br /&gt;
        t.daemon = True&lt;br /&gt;
        t.start()&lt;br /&gt;
    &lt;br /&gt;
    for t in requests + supplies:&lt;br /&gt;
        t.join()&lt;br /&gt;
&lt;br /&gt;
    return 0&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    exit(main())&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.2 (da controllare) ===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
unsigned procs_in = 0;&lt;br /&gt;
semaphore mutex = new binary_semaphore(1);&lt;br /&gt;
queue&amp;lt;semaphore&amp;gt; semaphores = new queue&amp;lt;&amp;gt;();&lt;br /&gt;
&lt;br /&gt;
sau_enter () {&lt;br /&gt;
	mutex.P();&lt;br /&gt;
	procs_in++;&lt;br /&gt;
	mutex.V();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
sau_exit () {&lt;br /&gt;
	mutex.P();&lt;br /&gt;
	procs_in--;&lt;br /&gt;
&lt;br /&gt;
	if (procs_in &amp;gt; 0) {&lt;br /&gt;
		semaphore s = new semaphore(0);&lt;br /&gt;
&lt;br /&gt;
		semaphores.enqueue(s);&lt;br /&gt;
		mutex.V();&lt;br /&gt;
		s.P();&lt;br /&gt;
	} else {&lt;br /&gt;
		while (!sempahores.empty())&lt;br /&gt;
			semaphores.dequeue().V();&lt;br /&gt;
&lt;br /&gt;
		mutex.V();&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Esercizio g.1 (da controllare) ===&lt;br /&gt;
==== Domanda a) ====&lt;br /&gt;
Poiché lo scheduler è non-preemptive, una volta assegnata la CPU ad un dato processo, questi non viene cambiato finché non ha terminato. Visto il vincolo nel testo della consegna, una volta concluso il processo corrente si hanno solo due scelte: selezionare il più recente processo A o il più recente processo B.&lt;br /&gt;
&lt;br /&gt;
Nuovi processi A partono ogni 6ms, nuovi processi B ogni 8ms; gli intervalli di tempo in cui partono sia processi A sia processi B sono multipli di mcm(6, 8) ms = 24ms: cioè ai tempi 0ms, 24ms, 48ms, 72ms, ..., parte sia un processo A sia un processo B.&lt;br /&gt;
&lt;br /&gt;
In ognuno di questi intervalli di 24ms, si susseguono sia processi A sia processi B. I processi A sono 24ms / 6ms = 4, i processi B 24ms / 8ms = 3; i primi richiedono 4 * 3ms = 12ms, i secondi 3 * 4ms = 12ms. È possibile dimostrare induttivamente che ad ogni nuovo intervallo di 24ms, i processi di quello precedente sono stati tutti svolti e che quelli correnti saranno terminati entro 24ms (infatti ad ogni 24ms, è un po' come se le condizioni iniziali venissero ristabilite). Pertanto è possibile eseguire entrambi i processi senza portare a starvation.&lt;br /&gt;
&lt;br /&gt;
==== Domanda b) ====&lt;br /&gt;
Ragionamento analogo al punto precedente, con alcune differenze date dalle permutazioni in cui certi processi vengono schedulati.&lt;br /&gt;
&lt;br /&gt;
==== Domanda c) ====&lt;br /&gt;
Per definizione, uno scheudler round-robin garantisce possibilità di esecuzione a tutti i processi, pertanto è possibile. La figura mostra un intervallamento di scheduling secondo criterio RR che evidenzia come sia possibile completare tutti i processi entro i 24ms.&lt;br /&gt;
&lt;br /&gt;
[[File:Epson 25082020151034.jpg]]&lt;br /&gt;
&lt;br /&gt;
=== Esercizio g.2 (da controllare) ===&lt;br /&gt;
&lt;br /&gt;
# Basso, perché vengono generate molte page trap. Così facendo i processi direttamente interessati devono attendere il caricamento delle pagine di memoria ed essere posti in attesa, riducendo l'utilizzazione della CPU.&lt;br /&gt;
# Sì, ad esempio il MBR (Master Boot Record) e l'area di swap. Il MBR contiene meta-informazioni sul disco stesso e non è adatto a contenere informazioni concrete, mentre l'area di swap può essere considerata un'estensione della memoria centrale del calcolatore.&lt;br /&gt;
# Flessibile, perché se intendo riconfigurare alcuni parametri del sistema non occorre ricompilare il kernel, ma solamente riscrivere/riconfigurare e rilanciare il programma che si fa carico del servizio in questione; affidabile, in quanto i servizi di sistema sono realizzati tramite processi a livello utente, e un loro crash non si ripercuote sull'intero sistema; meno efficiente (di un kernel monolitico) in quanto i vari servizi comunicano con il kernel non tramite chiamate di sistema, ma un vero e proprio servizio di message passing tra processi, che aggiunge overhead.&lt;br /&gt;
# Come voci di una directory che puntano allo stesso inode (laddove il file system sia basato su inode) o più in generale allo stesso FCB (File Control Block). Per determinare se un dato FCB non è più linkato da nessuna voce (entry) si utilizza un contatore che rappresenta il numero corrente di riferimenti; quando questo diventa 0, il FCB può essere eliminato dal file system.&lt;br /&gt;
&lt;br /&gt;
== Esame 14/02/2019 ==&lt;br /&gt;
[https://www.cs.unibo.it/~renzo/so/compiti/2019.02.14.tot.pdf Testo d'esame].&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.1 (da controllare) ===&lt;br /&gt;
&lt;br /&gt;
* Controllato dall'utente [[User:Acsor|Acsor]] ([[User talk:Acsor|talk]]) in data 16:03, 2 September 2020 (CEST). Ritengo sia: corretto&lt;br /&gt;
* Controllato dall'utente ? in data ?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
# Original authors: Mattia Guazzaloca, Paolo Marzolo&lt;br /&gt;
#&lt;br /&gt;
# Contributors: utente Acsor&lt;br /&gt;
&lt;br /&gt;
class monobinarysem(monitor):&lt;br /&gt;
    def __init__(self, val):&lt;br /&gt;
        monitor.__init__(self)&lt;br /&gt;
        self.iszero = condition(self)&lt;br /&gt;
        self.val = val&lt;br /&gt;
        &lt;br /&gt;
    @entry&lt;br /&gt;
    def monoP(self):&lt;br /&gt;
        if self.val == 0:&lt;br /&gt;
            self.iszero.wait()&lt;br /&gt;
        &lt;br /&gt;
        self.val -= 1&lt;br /&gt;
        &lt;br /&gt;
    @entry&lt;br /&gt;
    def monoV(self):&lt;br /&gt;
        if self.val == 0:&lt;br /&gt;
            self.val += 1&lt;br /&gt;
            self.iszero.signal()&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.2 (controllato) ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
# Original author: Renzo Davoli (durante la lezione)&lt;br /&gt;
#&lt;br /&gt;
# Contributors:&lt;br /&gt;
&lt;br /&gt;
def pssend(message, destination):&lt;br /&gt;
    asend((self(),message),destination)&lt;br /&gt;
&lt;br /&gt;
    while(1):&lt;br /&gt;
        snd, message = arecv(ANY)&lt;br /&gt;
&lt;br /&gt;
        if (message == ACK):&lt;br /&gt;
            break&lt;br /&gt;
&lt;br /&gt;
        datastruct.add(snd, message)&lt;br /&gt;
   &lt;br /&gt;
&lt;br /&gt;
def psreceive(sender):&lt;br /&gt;
    dummy = Message(null)&lt;br /&gt;
    asend(self(), dummy) # self is my id&lt;br /&gt;
    &lt;br /&gt;
    while(1):&lt;br /&gt;
        snd, message = arecv(ANY)&lt;br /&gt;
&lt;br /&gt;
        if (message == dummy):&lt;br /&gt;
            break&lt;br /&gt;
&lt;br /&gt;
        datastruct.add(snd, message)&lt;br /&gt;
        &lt;br /&gt;
    if (datastruct.match(sender)):&lt;br /&gt;
        src, msg = datastruct.get(sender)&lt;br /&gt;
        asend((self(),ACK), src)&lt;br /&gt;
&lt;br /&gt;
        return msg&lt;br /&gt;
    else:&lt;br /&gt;
        return None&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Esame 28/05/2019 ==&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2019.05.18.tot.pdf 2019.05.18.tot.pdf]&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.1 (da controllare) ===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
monitor storage:&lt;br /&gt;
   &lt;br /&gt;
    [16] int vector&lt;br /&gt;
    [16] condition ok2get&lt;br /&gt;
    [16] bool available = { 1, ..., 1 }&lt;br /&gt;
   &lt;br /&gt;
    entry get([16] int components):&lt;br /&gt;
        for (i from 0 to 15):&lt;br /&gt;
            while ((components[i] &amp;gt; vector[i]) || !available[i]):&lt;br /&gt;
                if (available[i]):&lt;br /&gt;
                    available[i] = false&lt;br /&gt;
                ok2get[i].wait()&lt;br /&gt;
            vector[i] -= components[i]&lt;br /&gt;
            available[i] = true&lt;br /&gt;
            ok2get[i].signal()&lt;br /&gt;
  &lt;br /&gt;
    entry add([16] int components):&lt;br /&gt;
        for (i from 0 to 15):&lt;br /&gt;
            vector[i] += components[i]&lt;br /&gt;
            available[i] = true&lt;br /&gt;
            ok2get[i].signal()&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&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;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
monitor storage{&lt;br /&gt;
	int stored[16]&lt;br /&gt;
	int components[16]&lt;br /&gt;
	condition ok2make[16]&lt;br /&gt;
	boolean required[16] //false&lt;br /&gt;
	&lt;br /&gt;
	void add(components){&lt;br /&gt;
		stored += components;&lt;br /&gt;
		for(i=0; i&amp;lt; 16; i ++){&lt;br /&gt;
			if(required[i] == true)&lt;br /&gt;
				ok2make(i).signal();&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	void get(components){&lt;br /&gt;
		for(i = 0; i&amp;lt; 16; i++){&lt;br /&gt;
			if (stored[i] &amp;gt;= components[i])&lt;br /&gt;
				stored[i] -= components[i]&lt;br /&gt;
			else&lt;br /&gt;
				required[i] = true&lt;br /&gt;
				ok2make(i).wait();&lt;br /&gt;
				required[i] = false&lt;br /&gt;
				i—;&lt;br /&gt;
&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Esame 15/07/2019 ==&lt;br /&gt;
[http://www.cs.unibo.it/~renzo/so/compiti/2019.07.15.tot.pdf 2019.07.15.tot.pdf]&lt;br /&gt;
=== Esercizio c.1 ===&lt;br /&gt;
&lt;br /&gt;
# Verifica del 18/05/2020 dell'utente [[User:Acsor|Acsor]]. Ritengo sia: corretto&lt;br /&gt;
# Verifica del ... dell'utente ... . Ritengo sia: ...&lt;br /&gt;
# ...&lt;br /&gt;
&lt;br /&gt;
Una semplice realizzazione in Python dello pseudocodice seguente è disponibile [https://github.com/pollomarzo/rdso1920/tree/master/2019exams/samepc qui].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
# Original authors: Mattia Guazzaloca, Paolo Marzolo&lt;br /&gt;
#&lt;br /&gt;
# Contributors: utente Acsor&lt;br /&gt;
&lt;br /&gt;
monitor pair_buffer:&lt;br /&gt;
    int nw, nr;&lt;br /&gt;
    queue buffer;&lt;br /&gt;
    condition same_number;&lt;br /&gt;
&lt;br /&gt;
    pair_buffer():&lt;br /&gt;
        nw = nr = 0&lt;br /&gt;
        buffer = queue()&lt;br /&gt;
        same_number = condition()&lt;br /&gt;
    &lt;br /&gt;
    @entry&lt;br /&gt;
    put(T x):&lt;br /&gt;
        nw++;&lt;br /&gt;
        buffer.enqueue(x);&lt;br /&gt;
        &lt;br /&gt;
        if nw != nr:&lt;br /&gt;
            same_number.wait();&lt;br /&gt;
            &lt;br /&gt;
        same_number.signal();&lt;br /&gt;
        nw--;&lt;br /&gt;
        &lt;br /&gt;
    @entry&lt;br /&gt;
    T get(void):&lt;br /&gt;
        nr++;&lt;br /&gt;
&lt;br /&gt;
        if nw != nr: &lt;br /&gt;
            same_number.wait();&lt;br /&gt;
        else:&lt;br /&gt;
            same_number.signal();&lt;br /&gt;
        &lt;br /&gt;
        T val = buffer.dequeue();&lt;br /&gt;
        same_number.signal();&lt;br /&gt;
        nr--;&lt;br /&gt;
&lt;br /&gt;
        return val;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.2 (da controllare) ===&lt;br /&gt;
Viene ritornata x stessa, in un numero di iterazioni pari a length(x). Il calcolo viene svolto tramite message passing tra processi client e processo server; [http://www.treccani.it/magazine/lingua_italiana/domande_e_risposte/grammatica/grammatica_030.html quest'ultimo] opera una sorta di iterazione inoltrando a se stesso il messaggio spedito da un client finché x != &amp;quot;&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Se più processi chiamano la funzione dilemma() allo stesso tempo, ciò non causa disagi nel calcolo del risultato finale. Infatti l'identificatore del processo cliente destinatario è memorizzato in pid, e protratto fino alla chiamata in cui x == &amp;quot;&amp;quot;. Inoltre la presenza di molteplici richieste non causa sovrapposizione, posto che asend() memorizzi il contenuto di messaggi in sospeso in una coda FIFO.&lt;br /&gt;
&lt;br /&gt;
== Esame 13/09/2019 ==&lt;br /&gt;
Testo: [https://www.cs.unibo.it/~renzo/so/compiti/2019.09.13.tot.pdf 2019.09.13.tot.pdf].&lt;br /&gt;
&lt;br /&gt;
=== Esercizio c.1 (controllato) ===&lt;br /&gt;
* Controllato dal professor Davoli durante la lezione del 19/05/2020.&lt;br /&gt;
* Controllato dall'utente [[User:Acsor|Acsor]] ([[User talk:Acsor|talk]]) in data 19:13, 1 September 2020 (CEST). &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
# Original author: Andrea R.&lt;br /&gt;
&lt;br /&gt;
monitor mbuf:&lt;br /&gt;
    waiting = 0&lt;br /&gt;
    queue&amp;lt;pair&amp;lt;T, int&amp;gt;&amp;gt; q    # (dato, molteplicità)&lt;br /&gt;
    condition ok2add         # q.length() &amp;lt; MAXELEM&lt;br /&gt;
    condition ok2get         # q.length() &amp;gt; 0&lt;br /&gt;
    &lt;br /&gt;
&lt;br /&gt;
    entry void add(T data, int n):&lt;br /&gt;
        if q.length() &amp;gt;= MAXELEM:&lt;br /&gt;
            ok2add.wait()&lt;br /&gt;
&lt;br /&gt;
        q.enqueue({data, n})&lt;br /&gt;
&lt;br /&gt;
        if waiting &amp;gt;= q.front().second:&lt;br /&gt;
            ok2get.signal()&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    entry T get():&lt;br /&gt;
        waiting++                                        # vuole ricevere&lt;br /&gt;
        if q.empty() or waiting &amp;lt; q.front().second:      # cortocircuitato&lt;br /&gt;
            ok2get.wait()&lt;br /&gt;
&lt;br /&gt;
        x = q.front().first&lt;br /&gt;
        q.front().second--&lt;br /&gt;
        waiting--                    # riceve&lt;br /&gt;
&lt;br /&gt;
        if q.front().second &amp;gt; 0:     # cascata&lt;br /&gt;
            ok2get.signal()&lt;br /&gt;
        else:                        # ultimo che riceve&lt;br /&gt;
            q.dequeue()&lt;br /&gt;
            ok2add.signal()&lt;br /&gt;
        return x&lt;br /&gt;
&amp;lt;/source&amp;gt;&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;
Il programma è composto da due processi, ognuno dei quali stampa all'infinito il proprio identificatore. Perché sia possibile stampare è però necessario attendere il proprio turno, condizione gestita dal monitor bohm: esso possiede due stati (0 o 1) ed è possibile entrarvi quando l'id del processo invocante e il valore dello stato corrispondono; la procedura post() di bohm setta lo stato al valore complementare e sveglia il processo in attesa sulla coda di condizione corrispondente (al nuovo stato). &lt;br /&gt;
&lt;br /&gt;
È possibile implementare il meccanismo di sincronizzazione con semafori tramite il codice seguente&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
binary_sempahore[2] sem = {new binary_semaphore(1), new binary_semaphore(0)};&lt;br /&gt;
&lt;br /&gt;
void pre (int n) {&lt;br /&gt;
    sem[n].P();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void post (int n) {&lt;br /&gt;
    sem[1 - n].V();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Esercizio g.1 (da controllare) ===&lt;br /&gt;
* Controllato dall'utente ? in data ?&lt;br /&gt;
* ...&lt;br /&gt;
&lt;br /&gt;
Date le variabili del problema x, y ed m, bisogna avere x &amp;lt; m, x &amp;lt; y e che il tempo di arrivo dei processi P1, P2 e P3 durante lo scheduling RR sia P1, P2 e P3. Per ulteriori informazioni vedere lo svolgimento in figura. (Nota: non è specificata la relazione tra y ed m né sono considerati i casi x = m e x = y.)&lt;br /&gt;
&lt;br /&gt;
[[File:2019-09-13-g1.jpg | 768px]]&lt;br /&gt;
&lt;br /&gt;
=== Esercizio g.2 (da controllare) ===&lt;br /&gt;
&lt;br /&gt;
# Le opzioni per comunicare con le periferiche di IO sono solitamente due: polling (sondaggio) e interrupt. Mediante il polling il sistema verifica costantemente lo stato dei dispositivi di IO prendendo azione quando esso cambia, con gli interrupt sono i dispositivi stessi a notificare il cambiamento del loro stato. Poiché fare polling significa eseguire ciclicamente delle istruzioni che svolgano il controllo, ricevere degli interrupt è più efficiente perché nello stesso tempo è possibile svolgere altro lavoro utile.&lt;br /&gt;
# ''Da svolgere.''&lt;br /&gt;
# Quando bisogna svolgere un'operazione di swap-in (caricamento di una pagina dalla memoria secondaria a quella primaria) e di swap-out (inversa alla precedente). L'algoritmo di rimpiazzamento è invocato durante un'operazione di swap-in che vede la memoria centrale completamente occupata: in tal caso sarà necessario individuare una pagina da spostare in memoria secondaria.&lt;br /&gt;
# Vantaggi: dimensioni del file eseguibile finale ridotte, in quanto non è richiesto mantenere all'interno dello stesso una copia delle procedure di cui ci si serve; risparmio in memoria centrale: per un dato simbolo appartenente ad una data libreria, è possibile riservare un solo spazio in memoria condiviso da più processi che ne hanno bisogno. Svantaggi: versionamento, ovvero l'installazione di versioni più aggiornate della stessa libreria in conflitto con quelle meno recenti: tale problema è risolto mediante la definizione precisa di numeri di versione delle librerie e la specificazione delle dipendenze (rispetto ad un dato numero di versione).&lt;/div&gt;</summary>
		<author><name>Gio</name></author>
	</entry>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=Prove_scritte_2022&amp;diff=2886</id>
		<title>Prove scritte 2022</title>
		<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php?title=Prove_scritte_2022&amp;diff=2886"/>
		<updated>2023-01-15T10:49:36Z</updated>

		<summary type="html">&lt;p&gt;Gio: /* Soluzione proposta (da controllare) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Prova 2022/09/06 =&lt;br /&gt;
&lt;br /&gt;
== Esercizio c1 == &lt;br /&gt;
&lt;br /&gt;
Esercizio c.1: I bit di un numero intero rappresentano condizioni di un sistema. Se lo stato attuale è 6 (0110) vuole dire&lt;br /&gt;
che attualmente sono vere le condizioni 2 (0010) e 4 (0100).&lt;br /&gt;
Scrivere un monitor bitcond che fornisca le seguenti procedure entry:&lt;br /&gt;
void set(int bit2set); accende nello stato attuale i bit di bit2set&lt;br /&gt;
void unset(int bit2unset) spegne nello stato attuale i bit di bit2unset&lt;br /&gt;
void statuswait(int bit2wait) attende che lo stato attuale soddisfi tutti le condizioni indicate in bit2wait (cioè&lt;br /&gt;
che tutti i bit in bit2wait siano accesi nello stato attuale).&lt;br /&gt;
Le richieste statuswait devono essere servite in ordine FIFO (cioè un processo anche se sono presenti tutte le&lt;br /&gt;
condizioni necessarie deve attendere se un processo che ha chiamato statuswait prima è in attesa).&lt;br /&gt;
Lo stato iniziale è zero (nessuna risorsa disponibile)&lt;br /&gt;
&lt;br /&gt;
=== Soluzione proposta 1 ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class bitcond{&lt;br /&gt;
  int bitmap;&lt;br /&gt;
  int lastBitmask;&lt;br /&gt;
  int has=0;&lt;br /&gt;
  &lt;br /&gt;
  condition waiting;&lt;br /&gt;
  condition c;&lt;br /&gt;
&lt;br /&gt;
  void set(int i){&lt;br /&gt;
    bitmap|=i; &lt;br /&gt;
      if(bitmap&amp;amp;lastBitmask == bitmap) c.signal();&lt;br /&gt;
  }&lt;br /&gt;
  void unset(int i){&lt;br /&gt;
    bitmap&amp;amp;=~i; &lt;br /&gt;
  }&lt;br /&gt;
  void statuswait(int i){&lt;br /&gt;
    has++; &lt;br /&gt;
    if(has&amp;gt;1){&lt;br /&gt;
      waiting.wait();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if(!(bitmap&amp;amp;i==i)){&lt;br /&gt;
      lastBitmask=i;&lt;br /&gt;
      c.wait();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    waiting.signal();&lt;br /&gt;
    has--;&lt;br /&gt;
  }&lt;br /&gt;
  bitcond(){&lt;br /&gt;
    bitmap = 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;
=== Soluzione proposta 2 ===&lt;br /&gt;
Proposta da [[User:Flecart|Flecart]] ([[User talk:Flecart|talk]]) 12:06, 14 January 2023 (CET)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
const int int_size = 32;&lt;br /&gt;
&lt;br /&gt;
class monitor {&lt;br /&gt;
    int value;&lt;br /&gt;
    condition bitset[int_size];&lt;br /&gt;
&lt;br /&gt;
    int numstatuswaiting;&lt;br /&gt;
    condition waiting;&lt;br /&gt;
    &lt;br /&gt;
    monitor() {&lt;br /&gt;
        value = 0;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    /// guarda se il bit n-significativo è settato in from&lt;br /&gt;
    bool nbit(int from, int n) {&lt;br /&gt;
        return (from &amp;amp; (1 &amp;lt;&amp;lt; n)) != 0&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void entry set(int bit2set) {&lt;br /&gt;
        value |= bit2set;&lt;br /&gt;
&lt;br /&gt;
        for (int i = 0; i &amp;lt; 32; i++) {&lt;br /&gt;
            if (nbit(value, i))&lt;br /&gt;
                bitset[i].signal();&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void entry statuswait(int bit2wait) {&lt;br /&gt;
        // in questo modo solamente un singolo processo è dentro ad aspettare&lt;br /&gt;
        // che tutte le condizioni siano rispettate&lt;br /&gt;
        if (numstatuswaiting &amp;gt; 0)&lt;br /&gt;
            waiting.wait();&lt;br /&gt;
        &lt;br /&gt;
        numstatuswaiting++;&lt;br /&gt;
        int i = 0;&lt;br /&gt;
        while(i &amp;lt; 32) {&lt;br /&gt;
            if (nbit(bit2wait, i) &amp;amp;&amp;amp; !nbit(value, i)) {&lt;br /&gt;
                bitset[i].wait();&lt;br /&gt;
&lt;br /&gt;
                // ricomincia a guardare tutti i bit da zero, perché&lt;br /&gt;
                // nel frattempo potrebbero essere cambiati.&lt;br /&gt;
                // -1 così con l'istruzione successiva diventa 0&lt;br /&gt;
                i = -1; &lt;br /&gt;
            }&lt;br /&gt;
            i++;&lt;br /&gt;
        }&lt;br /&gt;
        &lt;br /&gt;
        numstatuswaiting--;&lt;br /&gt;
        waiting.signal();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Soluzione proposta 3 ===&lt;br /&gt;
Proposta da [[User:Flecart|Flecart]] ([[User talk:Flecart|talk]]) 12:07, 14 January 2023 (CET)&lt;br /&gt;
questa è la soluzione più brutta, ma dovrebbe andare.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
const int int_size = 32;&lt;br /&gt;
&lt;br /&gt;
class monitor {&lt;br /&gt;
    int value;&lt;br /&gt;
    condition status;&lt;br /&gt;
&lt;br /&gt;
    int numstatuswaiting;&lt;br /&gt;
    condition waiting;&lt;br /&gt;
    &lt;br /&gt;
    monitor() {&lt;br /&gt;
        value = 0;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    /// guarda se il bit n-significativo è settato in from&lt;br /&gt;
    bool nbit(int from, int n) {&lt;br /&gt;
        return (from &amp;amp; (1 &amp;lt;&amp;lt; n)) != 0&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void entry set(int bit2set) {&lt;br /&gt;
        value |= bit2set;&lt;br /&gt;
        status.signal();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    void entry unset(int bit2unset) {&lt;br /&gt;
        value = (value &amp;amp; ~bit2unset);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void entry statuswait(int bit2wait) {&lt;br /&gt;
        // in questo modo solamente un singolo processo è dentro ad aspettare&lt;br /&gt;
        // che tutte le condizioni siano rispettate&lt;br /&gt;
        if (numstatuswaiting &amp;gt; 0)&lt;br /&gt;
            waiting.wait();&lt;br /&gt;
        &lt;br /&gt;
        numstatuswaiting++;&lt;br /&gt;
        while(true) {&lt;br /&gt;
            if ((value &amp;amp; bit2wait) == bit2wait) &lt;br /&gt;
                break;&lt;br /&gt;
            else &lt;br /&gt;
                status.wait();&lt;br /&gt;
        }&lt;br /&gt;
        numstatuswaiting--;&lt;br /&gt;
        waiting.signal();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Prova 2022/06/21 =&lt;br /&gt;
&lt;br /&gt;
== Esercizio c1 ==&lt;br /&gt;
Scrivere il monitor collocamento:&lt;br /&gt;
  void cercolavoro(char *nome, char *skill)&lt;br /&gt;
  void char *assumo(char * skill)&lt;br /&gt;
Quando un processo chiama la cercolavoro si mette in attesa di una richiesta di lavoro e rimane bloccato nel monitor&lt;br /&gt;
fino a che non è stato assunto. Nella cercolavoro viene indicato il nome dell'aspirante lavoratore la sua capacità (skill).&lt;br /&gt;
Un datore di lavoro con necessità di personale chiama la assumo specificando la capacità richiesta. Se c'è in attesa&lt;br /&gt;
almeno un aspirante lavoratore con quella specifica capacità (uguale valore di skill), il datore di lavoro riceve il nome del&lt;br /&gt;
nuovo dipendente ed entrambi i processi escono dal monitor. Nel caso non ci siano richieste compatibili il datore di&lt;br /&gt;
lavoro si blocca nel monitor attendendo un lavoratore con la capacità cercata. Quando arriva il lavoratore che soddisfa&lt;br /&gt;
le richieste si sbloccano entrambi i processi lavoratore e datore di lavoro. La assumo restituisce in ogni caso il nome del&lt;br /&gt;
dipendente da assumere.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Soluzione proposta === &lt;br /&gt;
&lt;br /&gt;
Soluzione proposta da [[User:Flecart|Flecart]] ([[User talk:Flecart|talk]]) 12:08, 14 January 2023 (CET)&lt;br /&gt;
&lt;br /&gt;
ci potrebbe essere un errore in quanto non è specificato il comportamento della struttura dati in alcune situazioni&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
class collocamento{&lt;br /&gt;
&lt;br /&gt;
set&amp;lt;char *, condition&amp;gt; richieste;  // chi assume cerca questa skill&lt;br /&gt;
set&amp;lt;char *, char *, condition&amp;gt; ricerche; // nome e skill di chi cerca&lt;br /&gt;
&lt;br /&gt;
char *last_nome;&lt;br /&gt;
&lt;br /&gt;
collocamento {&lt;br /&gt;
	last_nome = NULL;&lt;br /&gt;
	richieste = set();&lt;br /&gt;
	ricerche = set();	&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void cercolavoro(char *nome, char *skill) {&lt;br /&gt;
	datore = richieste.find(skill);  // cerca valutando la prima come chiave&lt;br /&gt;
	if (datore != NULL) {&lt;br /&gt;
		&amp;lt;skill, cond&amp;gt; = datore;&lt;br /&gt;
		richieste.remove(datore);&lt;br /&gt;
		last_nome = nome;&lt;br /&gt;
		cond.signal();		&lt;br /&gt;
	} else {&lt;br /&gt;
		condition c = new condition();&lt;br /&gt;
		ricerche.insert(nome, skill, c);&lt;br /&gt;
		c.wait();&lt;br /&gt;
		free(c);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void char *assumo(char * skill){&lt;br /&gt;
	lavoratore = ricerche.find2(skill); // cerca valutando la seconda come chiave.&lt;br /&gt;
	if (lavoratore != NULL) {&lt;br /&gt;
		&amp;lt;nome, skill, cond&amp;gt; = lavoratore;&lt;br /&gt;
		ricerche.remove(lavoratore);&lt;br /&gt;
		cond.signal();&lt;br /&gt;
		last_nome = nome;&lt;br /&gt;
	} else {&lt;br /&gt;
		condition c = new condition();&lt;br /&gt;
		richieste.insert(skill, c);&lt;br /&gt;
		c.wait();&lt;br /&gt;
		free(c);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	return last_nome;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
}// class collocamento&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Soluzione proposta === &lt;br /&gt;
&lt;br /&gt;
Soluzione proposta da [[User:Flecart|Flecart Frend]], regalo la proprietà intellettuale di questa soluzione a flecart.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
class workdisptcher{&lt;br /&gt;
&lt;br /&gt;
  // la multi map può storare più di un valore per una chiave&lt;br /&gt;
  // quando viene richiesta una particolare chiave da in maniera LIFO&lt;br /&gt;
  // il risultato&lt;br /&gt;
  // es:&lt;br /&gt;
  // multi_map&amp;lt;char *,int&amp;gt; lavoratori;&lt;br /&gt;
  // lavoratori.insert(&amp;quot;prova&amp;quot;,2);&lt;br /&gt;
  // lavoratori.insert(&amp;quot;prova&amp;quot;,1);&lt;br /&gt;
  // lavoratori.get(&amp;quot;prova&amp;quot;) == 2&lt;br /&gt;
  // lavoratori.remove(&amp;quot;prova&amp;quot;)&lt;br /&gt;
  // lavoratori.get(&amp;quot;prova&amp;quot;) == 1&lt;br /&gt;
  multi_map&amp;lt;char *,(char*,cond)&amp;gt; lavoratori;&lt;br /&gt;
  multi_map&amp;lt;char *,cond&amp;gt; posti_aperti;&lt;br /&gt;
  char* buffer_name;&lt;br /&gt;
  void cercolavoro(char *nome, char *skill){&lt;br /&gt;
    if(posti_aperti.find(skill)){&lt;br /&gt;
      auto entry =posti_aperti.get(skill);&lt;br /&gt;
      posti_aperti.remove(entry);&lt;br /&gt;
      buffer_name=name;&lt;br /&gt;
      entry.1.signal();&lt;br /&gt;
    }else{&lt;br /&gt;
      cond c= new cond();&lt;br /&gt;
      lavoratori.insert(skill,(nome,c)) ;&lt;br /&gt;
      c.wait();&lt;br /&gt;
      free(c);&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  void char *assumo(char * skill){&lt;br /&gt;
    if(lavoratori.find(skill)){&lt;br /&gt;
      auto entry =lavoratori.get(skill);&lt;br /&gt;
      posti_aperti.remove(entry);&lt;br /&gt;
      auto [nome,cnd] = entry.1;&lt;br /&gt;
      cond.signal();&lt;br /&gt;
      return nome;&lt;br /&gt;
    }else{&lt;br /&gt;
      cond c= new cond();&lt;br /&gt;
      posti_aperti.insert(skill,c) ;&lt;br /&gt;
      c.wait();&lt;br /&gt;
      free(c);&lt;br /&gt;
      return buffer_name;&lt;br /&gt;
    }&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 c2 ==&lt;br /&gt;
Un servizio viene fornito in modalità client-server usando message passing asincrono.&lt;br /&gt;
Al fine di aumentare l'efficienza si decide di usare molti server e un processo dispatcher in grado di distribuire le&lt;br /&gt;
richieste agli N server. Quando un processo server è libero riceve dal dispatcher la prossima richiesta da elaborare:&lt;br /&gt;
codice di ogni client (tanti!): .....&lt;br /&gt;
  asend(&amp;lt;getpid(), request&amp;gt;, dispatcher)&lt;br /&gt;
  result = arecv(dispatcher)&lt;br /&gt;
&lt;br /&gt;
server process[i], i = 0, ..., N-1:&lt;br /&gt;
 request = arecv(dispatcher)&lt;br /&gt;
 result = compute(request)&lt;br /&gt;
 asend(&amp;lt;getpid(), result&amp;gt;, dispatcher)&lt;br /&gt;
Scrivere il processo dispatcher. (il dispatcher conosce i pid di tutti i server).&lt;br /&gt;
&lt;br /&gt;
=== Soluzione proposta (sbagliata) === &lt;br /&gt;
&lt;br /&gt;
Soluzione proposta da [https://so.v2.cs.unibo.it/wiki/index.php/User:Flecart Flecart] &lt;br /&gt;
&lt;br /&gt;
Questo esercizio è stato corretto tempo fa in classe dal professore, **non è completamente corretto** se si vuole provare a correggerlo alla fine dell'esercizio c'è scritto cos'è sbagliato.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
extern int N;&lt;br /&gt;
process dispatcher() {&lt;br /&gt;
    // indice che tiene conto a quale server dover mandare&lt;br /&gt;
    // per semplicità supponiamo che i server abbiano PID&lt;br /&gt;
    // da 0 a N - 1&lt;br /&gt;
    int i = 0; &lt;br /&gt;
&lt;br /&gt;
    // mappa server a pid del processo che lo ha richiesto.&lt;br /&gt;
    // chiave: pid del server&lt;br /&gt;
    // value: queue richiesta dispatchata al server in chiave&lt;br /&gt;
    map&amp;lt;int, queue&amp;lt;int&amp;gt;&amp;gt; mapper; &lt;br /&gt;
    while (true) {&lt;br /&gt;
        res = arecv(ANY);&lt;br /&gt;
        &lt;br /&gt;
        // in questa parte l'importante è sapere&lt;br /&gt;
        // se la richiesta proviene dal  server o da un altro&lt;br /&gt;
        // processo, ho assunto che la disambiguazione &lt;br /&gt;
        // fosse immediata, un altro modo per checkare questo&lt;br /&gt;
        // è vedere se il PID del messaggio rientri fra quelli&lt;br /&gt;
        // noti al dispatcher.&lt;br /&gt;
        if (&amp;lt;pid, request&amp;gt; = res) {&lt;br /&gt;
            mapper[i].enqueue(pid);&lt;br /&gt;
            asend(request, i /*il i-esimo server*/);&lt;br /&gt;
            i++;&lt;br /&gt;
            i %= N;&lt;br /&gt;
        } else if (&amp;lt;pid, response&amp;gt; = res) {&lt;br /&gt;
            requester_pid = mapper[pid].dequeue();&lt;br /&gt;
            asend(response, requester_pid);&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;
l'es è sbagliato perchè dovrei mandare ai server liberi, non a round-robin [[User:Flecart|Flecart]] ([[User talk:Flecart|talk]]) 15:52, 14 January 2023 (CET)&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 frend] che cede a flecart la proprietà intellettuale di questa soluzione&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
dispatcher{&lt;br /&gt;
  queue&amp;lt;&amp;lt;pid,request&amp;gt;&amp;gt; work;&lt;br /&gt;
  queue&amp;lt;pid&amp;gt; freeserver;&lt;br /&gt;
  map&amp;lt;pid,pid&amp;gt; map_server_to_client;&lt;br /&gt;
  while(true){&lt;br /&gt;
    &amp;lt;pid,message&amp;gt;=arecv(ANY);&lt;br /&gt;
    if pid in servers{&lt;br /&gt;
      client=map_server_to_client.get(pid);&lt;br /&gt;
      map_client_to_server.remove(pid);&lt;br /&gt;
      freeserver.push(pid);&lt;br /&gt;
      asend(&amp;lt;message&amp;gt;,client);&lt;br /&gt;
    }else{&lt;br /&gt;
      work.push(&amp;lt;pid,message&amp;gt;);&lt;br /&gt;
    }&lt;br /&gt;
    while !freeserver.empty() and !work.emtpy(){&lt;br /&gt;
      server_pid = freeserver.pop();&lt;br /&gt;
      &amp;lt;client,msg&amp;gt; = work.pop();&lt;br /&gt;
      map_server_to_client.insert(server,client);&lt;br /&gt;
      asend(msg,server_pid);&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Prova 2022/06/01 =&lt;br /&gt;
&lt;br /&gt;
== Esercizio c1 ==&lt;br /&gt;
&lt;br /&gt;
Scrivere il monitor delay che fornisce due procedure entry:&lt;br /&gt;
  int wait_tick(int nticks)&lt;br /&gt;
  void tick(void)&lt;br /&gt;
La procedure entry tick è pensata per essere richiamata periodicamente (es. ogni secondo o ora o giorno) da un&lt;br /&gt;
processo.&lt;br /&gt;
Quando un processo chiama la wait_tick deve attendere un numero di chiamate della tick pari al parametro nticks.&lt;br /&gt;
Per esempio se un processo chiama wait_tick(2) deve fermarsi e verrà riattivato alla seconda successiva chiamata di&lt;br /&gt;
tick.&lt;br /&gt;
La funzione wait_tick ha come valore di ritorno il numero di processi che erano bloccati al momento della tick che ha&lt;br /&gt;
sbloccato il chiamante.&lt;br /&gt;
Esempio: P chiama wait_tick(2) e si blocca. Q chiama wait_tick(3) e si blocca. T chiama tick() non succede nulla. R&lt;br /&gt;
chiama wait_tick(2) e si blocca. T chiama tick(), viene sbloccata la wait_tick di P e il valore ritornato è 3. T chiama&lt;br /&gt;
tick(), vengono sbloccate le wait_tick di Q e R e il valore ritornato per entrambi i processi è 2&lt;br /&gt;
&lt;br /&gt;
=== Soluzione proprosta 1 (da controllare) ===&lt;br /&gt;
Soluzione proposta 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;
class MonitorDelay {&lt;br /&gt;
    int curr_time;&lt;br /&gt;
    int waiting_num;&lt;br /&gt;
&lt;br /&gt;
    // min heap con il tempo di sblocco dei processi e la condizione su cui è fermato&lt;br /&gt;
    // il tempo di sblocco minore è messo in cima alla heap&lt;br /&gt;
    // la sintassi con pair è ispirata alla std::pair di c++&lt;br /&gt;
    heap&amp;lt;pair&amp;lt;int, condition&amp;gt;&amp;gt; waiting; &lt;br /&gt;
&lt;br /&gt;
    void init() {&lt;br /&gt;
        curr_time = 0;&lt;br /&gt;
        waiting = heap&amp;lt;pair&amp;lt;int, condition&amp;gt;&amp;gt;();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    int entry wait_tick(int nticks) {&lt;br /&gt;
        if (nticks &amp;lt;= 0) {&lt;br /&gt;
            return waiting.size();&lt;br /&gt;
        } else {&lt;br /&gt;
            condition c = new condition();&lt;br /&gt;
            waiting.insert(make_pair(nticks + curr_time, c));&lt;br /&gt;
            c.wait();&lt;br /&gt;
            free(c);&lt;br /&gt;
        }&lt;br /&gt;
        return waiting_num;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    void entry tick(void) {&lt;br /&gt;
        waiting_num = waiting.size();&lt;br /&gt;
        curr_time++;&lt;br /&gt;
&lt;br /&gt;
        while (waiting.head().first &amp;lt;= curr_time) {&lt;br /&gt;
            condition c = waiting.head().second;&lt;br /&gt;
            waiting.deleteHead();&lt;br /&gt;
            c.signal();&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Esercizio c2 ==&lt;br /&gt;
&lt;br /&gt;
=== Consegna ===&lt;br /&gt;
&lt;br /&gt;
Esercizio c.2: Un servizio di message passing asincrono non fifo (nfasend/nfarecv) consegna in tempo finito tutti i&lt;br /&gt;
messaggi spediti ma non è garantito che i messaggi vengano ricevuti nell'ordine nel quale sono stati spediti.&lt;br /&gt;
  void nfasend(msg_t msg, pid_t dest)&lt;br /&gt;
  msg_t nfarecv(pid_t sender)&lt;br /&gt;
Dato un servizio di message passing asincrono non fifo scrivere una libreria che implementi il servizio di message&lt;br /&gt;
passing asincrono fifo:&lt;br /&gt;
  void asend(msg_t msg, pid_t dest)&lt;br /&gt;
  msg_t arecv(pid_t sender)&lt;br /&gt;
Nota: sia il servizio dato (non fifo) sia quello da implementare (fifo) consentono la ricezione solo da mittente specificato&lt;br /&gt;
(non supportano ANY/*).&lt;br /&gt;
&lt;br /&gt;
=== Soluzione proposta 1 ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void nfasend(msg_t msg, pid_t dest);&lt;br /&gt;
msg_t nfarecv(pid_t sender);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// array di grandezza di massimi numero di processi, inizializzato a 0&lt;br /&gt;
// utilizzato per contare il numero di messaggi inviati a un certo processo.&lt;br /&gt;
int num_sender[MAX_PROC];&lt;br /&gt;
&lt;br /&gt;
//RICORDA che ogni sender ha il suo num_sender[...]&lt;br /&gt;
&lt;br /&gt;
void asend(msg_t msg, pid_t dest) {&lt;br /&gt;
	src = getpid();&lt;br /&gt;
	nfasend(&amp;lt;msg, num_send[dest]&amp;gt;, dest);&lt;br /&gt;
	num_sender[dest]++;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// molto simile a num_sender, ma è utilizzato per contare il numero di messaggi ricevuti, in ordine.&lt;br /&gt;
int num_receiver[MAX_PROC];&lt;br /&gt;
// array heap ordinato sul int (per ogni heap in cima c'è il messaggio col minimo int).&lt;br /&gt;
min_heap&amp;lt;msg, int&amp;gt; messages[MAX_PROC];&lt;br /&gt;
&lt;br /&gt;
//RICORDA che ogni receiver ha il suo proprio num_receiver[...] e messages[...]&lt;br /&gt;
&lt;br /&gt;
msg_t arecv(pid_t sender) {&lt;br /&gt;
	p = getpid();&lt;br /&gt;
	&lt;br /&gt;
	if (messages[sender].size() &amp;gt; 0 &amp;amp;&amp;amp; messages[sender].top() == num_receiver[sender]) {&lt;br /&gt;
		(msg, num_mess) = messages[sender].removeTop();&lt;br /&gt;
		num_receiver[sender]++;&lt;br /&gt;
		return msg;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	(msg, num_mess) = nfarecv(sender);&lt;br /&gt;
&lt;br /&gt;
	while (num_mess != num_receiver[sender]) {&lt;br /&gt;
		messages[sender].insert(msg, num_mess);&lt;br /&gt;
		(msg, num_mess) = nfarecv(sender);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	num_receiver[sender]++;&lt;br /&gt;
	return msg;	&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Gio</name></author>
	</entry>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=User_talk:Gio&amp;diff=2879</id>
		<title>User talk:Gio</title>
		<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php?title=User_talk:Gio&amp;diff=2879"/>
		<updated>2023-01-14T20:07:45Z</updated>

		<summary type="html">&lt;p&gt;Gio: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Pls don't talk to me.&lt;/div&gt;</summary>
		<author><name>Gio</name></author>
	</entry>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=User_talk:Gio&amp;diff=2878</id>
		<title>User talk:Gio</title>
		<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php?title=User_talk:Gio&amp;diff=2878"/>
		<updated>2023-01-14T20:07:27Z</updated>

		<summary type="html">&lt;p&gt;Gio: Pls, don't talk to me&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Gio</name></author>
	</entry>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=Prove_scritte_2021&amp;diff=2877</id>
		<title>Prove scritte 2021</title>
		<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php?title=Prove_scritte_2021&amp;diff=2877"/>
		<updated>2023-01-14T16:20:16Z</updated>

		<summary type="html">&lt;p&gt;Gio: /* Es C1 (da correggere) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
= Prova 21/07/2021=&lt;br /&gt;
&lt;br /&gt;
== Es C1 (da correggere) == &lt;br /&gt;
&lt;br /&gt;
Soluzione proposta da [https://so.v2.cs.unibo.it/wiki/index.php/User:Flecart Flecart friend],regalo a flecart la proprietà intellettuale di questa soluzione&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
class node{&lt;br /&gt;
  node parent;&lt;br /&gt;
  sq sq1;&lt;br /&gt;
  cond c;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
class BinTree{&lt;br /&gt;
  vector&amp;lt;node&amp;gt; base;&lt;br /&gt;
  void create(int N){&lt;br /&gt;
    base=new vector&amp;lt;node&amp;gt;(2^N);&lt;br /&gt;
    for(int i=0;i&amp;lt;2^N;i++)&lt;br /&gt;
      base[i]=new node(null,0,new cond);&lt;br /&gt;
    for(int i=1;i&amp;lt;=N;i++){&lt;br /&gt;
      for(int j=0;j&amp;lt;2^(N-i);j++){&lt;br /&gt;
        get(j,i-1).parent=get(j+i,i-1).parent=new node(null,0,new cond);&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  node get(int i,int level){&lt;br /&gt;
    return get(base[i],level);&lt;br /&gt;
  }&lt;br /&gt;
  node get(node n,int level){&lt;br /&gt;
    if(level==0){&lt;br /&gt;
      return node;&lt;br /&gt;
    }&lt;br /&gt;
    return get(node.parent,level-1);&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class Torneo{&lt;br /&gt;
  BinTree bin(N);&lt;br /&gt;
  int forma[2^N];&lt;br /&gt;
  bool win;&lt;br /&gt;
&lt;br /&gt;
  bool gioca(int i,int turno,int forma){&lt;br /&gt;
    forma[i]=forma;&lt;br /&gt;
    if null==bin.get(i,turno).sq1{&lt;br /&gt;
      bin.get(i,turno).sq1=i;&lt;br /&gt;
      bin.get(i,turno).c.wait();&lt;br /&gt;
      return !win;&lt;br /&gt;
    }else{&lt;br /&gt;
      sq1= bin.get(i,turno).sq1;&lt;br /&gt;
      if(forma[sq1]==forma[i]){&lt;br /&gt;
        win=random();&lt;br /&gt;
      }else{&lt;br /&gt;
        win=forma[sq1]&amp;lt;forma[i];&lt;br /&gt;
      }&lt;br /&gt;
      bin.get(i,turno).signal();&lt;br /&gt;
    }&lt;br /&gt;
    return win;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Prova 2021/09/15 =&lt;br /&gt;
&lt;br /&gt;
== Esercizio C1 == &lt;br /&gt;
&lt;br /&gt;
=== Consegna === &lt;br /&gt;
Esercizio c.1: Scrivere il monitor alrv (at least rendez-vous) che fornisce una sola procedure entry:&lt;br /&gt;
procedure entry void at_least(int n)&lt;br /&gt;
Quando un processo chiama la funzione at_least vuol dire che vuole sincronizzarsi con un insieme di almeno n&lt;br /&gt;
processi (incluso il chiamante).&lt;br /&gt;
Esempi:&lt;br /&gt;
Se un processo chiama at_least(1) non si blocca.&lt;br /&gt;
Se il processo p chiama at_least(2) si blocca, se poi il processo q chiama at_least(2) oppure at_least(1) si&lt;br /&gt;
sbloccano sia p sia q (la richiesta di p è soddisfatta, ne aspettava almeno 2, p e q)&lt;br /&gt;
Se il processo p chiama at_least(2) si blocca, se poi il processo q chiama at_least(3) si blocca anch'esso perché&lt;br /&gt;
sebbene la richiesta di p possa essere soddisfatta, q non può ancora sbloccarsi: ci sono solo 2 processi in attesa mentre&lt;br /&gt;
q ne vuole 3. Un terzo processo che chiami at_least(x) con x=1,2,3 li sblocca tutti.&lt;br /&gt;
Hint: sia w[k ] il numero dei processi in attesa di essere in almeno k (quelli che hanno chiamato at_least(k) e non&lt;br /&gt;
hanno completato l'esecuzione della funzione). Sia s[n]=∑&lt;br /&gt;
k=1&lt;br /&gt;
n&lt;br /&gt;
w[k ] (rappresenta il numero di processi soddisfacibili:&lt;br /&gt;
e.g. se ci sono 4 processi in attesa, potrebbero essere soddisfatte le richieste dei processi che ne aspettano almeno 2,&lt;br /&gt;
almeno 3 o almeno 4). Preso, se esiste, il massimo indice m tale che s[m]≥m tutti i processi in attesa di essere in n,&lt;br /&gt;
per n≤m possono essere sbloccati.&lt;br /&gt;
&lt;br /&gt;
=== 1. Soluzione proposta ===&lt;br /&gt;
Soluzione proposta da [https://so.v2.cs.unibo.it/wiki/index.php/User:Flecart Flecart]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
extern int MAX;  // il massimo numero di attesa&lt;br /&gt;
monitor alrv {&lt;br /&gt;
	int w[MAX];&lt;br /&gt;
	int s[MAX];&lt;br /&gt;
	condition c[MAX];&lt;br /&gt;
&lt;br /&gt;
	init() {&lt;br /&gt;
		for (int i = 0; i &amp;lt; MAX; i++) {&lt;br /&gt;
			w[i] = s[i] = 0;&lt;br /&gt;
		}&lt;br /&gt;
	}	&lt;br /&gt;
&lt;br /&gt;
procedure entry void at_least(int n) {&lt;br /&gt;
	if (n &amp;gt;= MAX || n &amp;lt;= 0) raise error;&lt;br /&gt;
	&lt;br /&gt;
	int i;&lt;br /&gt;
	for (i = n; i &amp;lt; MAX; i++) s[i]++;&lt;br /&gt;
	&lt;br /&gt;
	for (i = MAX - 1; i &amp;gt; 0; i--) {&lt;br /&gt;
		if (s[i] &amp;gt;= i) break;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	if (i &amp;gt; 0) {&lt;br /&gt;
		for (int j = 0; j &amp;lt;= i; j++) {&lt;br /&gt;
			while (w[j] &amp;gt; 0) {&lt;br /&gt;
				c[j].signal();&lt;br /&gt;
				w[j]--;&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
		&lt;br /&gt;
		s[0] = 0;&lt;br /&gt;
		for (int i = 1; i &amp;lt; MAX; i++) {&lt;br /&gt;
			s[i] = w[i] + s[i - 1];&lt;br /&gt;
		}&lt;br /&gt;
	} else {&lt;br /&gt;
		w[n]++;&lt;br /&gt;
		c[n].wait();&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Soluzione proposta da [https://so.v2.cs.unibo.it/wiki/index.php/User:Flecart Flecart friend],regalo a flecart la proprietà intellettuale di questa soluzione&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
class Monitor{&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
  min_heap&amp;lt;(int,cond)&amp;gt; h;&lt;br /&gt;
&lt;br /&gt;
  void at_least(int n){&lt;br /&gt;
    int sum=0;&lt;br /&gt;
    int max_to_sblock= -INF;&lt;br /&gt;
    cond c = new cond(n);&lt;br /&gt;
    h.push((n,c));&lt;br /&gt;
    // la heap viene visitata in maniera crescente&lt;br /&gt;
    for(auto f=h.begin_iter();null!=f.next();f++) {&lt;br /&gt;
        sum++;&lt;br /&gt;
        if(f.0&amp;lt;=sum){&lt;br /&gt;
          max_to_sblock =f.0;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    for(auto f=h.begin_iter();null!=f.next();f++) {&lt;br /&gt;
        if(f.0&amp;lt;=max_to_sblock){&lt;br /&gt;
          f.1.signal();&lt;br /&gt;
          h.remove(c);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    if(n&amp;gt;max_to_sblock){&lt;br /&gt;
      c.wait();&lt;br /&gt;
    }&lt;br /&gt;
    free(c)&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Prova 2021/06/23 =&lt;br /&gt;
&lt;br /&gt;
== Esercizio C1 == &lt;br /&gt;
&lt;br /&gt;
=== Consegna === &lt;br /&gt;
Esercizio c.1: Scrivere il monitor delayvalue con una sola procedure entry:&lt;br /&gt;
  int delay(int value);&lt;br /&gt;
Il monitor deve sospendere i primi NDELAY processi che chiamano la delay. Le successive chiamate di delay&lt;br /&gt;
devono mantenere costante il numero di processi sospesi, ogni successiva chiamata devo riattivare il primo&lt;br /&gt;
processo in attesa prima di sospendersi, la delay ritorna il valore passato come parametro dal processo che&lt;br /&gt;
ne ha riattivato l'esecuzione. e.g. se NDELAY è 2:&lt;br /&gt;
  P1: delay(44) -&amp;gt; P1 si sospende&lt;br /&gt;
  P2: delay(40) -&amp;gt; P2 si sospende&lt;br /&gt;
  P3: delay(42) -&amp;gt; P1 si riattiva e ritorna 42, P3 si sospende&lt;br /&gt;
  P4: delay(22) -&amp;gt; P2 si riattiva e ritorna 22, P4 si sospende&lt;br /&gt;
&lt;br /&gt;
=== Soluzione proposta 1 ===&lt;br /&gt;
Soluzione proposta da [https://so.v2.cs.unibo.it/wiki/index.php/User:Flecart Flecart], da controllare&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// variabile definita altrove.&lt;br /&gt;
extern int NDELAY;&lt;br /&gt;
&lt;br /&gt;
class Monitor {&lt;br /&gt;
    Queue&amp;lt;condition&amp;gt; stopped;&lt;br /&gt;
    int curr_value;&lt;br /&gt;
    Monitor {&lt;br /&gt;
        stopped = Queue&amp;lt;condition&amp;gt;();&lt;br /&gt;
        curr_value = 0;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    int delay(int value) {&lt;br /&gt;
        curr_value = value;&lt;br /&gt;
        if (stopped.size() == NDELAY) {&lt;br /&gt;
            condition first = stopped.dequeue();&lt;br /&gt;
            first.signal();&lt;br /&gt;
        }&lt;br /&gt;
        condition c = new condition();&lt;br /&gt;
        stopped.enqueue(c);&lt;br /&gt;
        c.wait();    &lt;br /&gt;
&lt;br /&gt;
        return curr_value;&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 c2 ==&lt;br /&gt;
&lt;br /&gt;
=== Consegna ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Esercizio c.2: Implementare usando semafori ordinari (fair, fifo) un servizio di semafori a priorità lifo che&lt;br /&gt;
fornisca le seguenti primitive:&lt;br /&gt;
 void PLP(int prio);&lt;br /&gt;
 void PLV()&lt;br /&gt;
PLP e PLV si devono comportare rispettivamente come P e V. Quando la PLV deve riattivare un processo&lt;br /&gt;
sceglie fra quelli in attesa quello a priorità massima, nel caso siano presenti più processi a priorità massima&lt;br /&gt;
sceglie quello in attesa da meno tempo. &lt;br /&gt;
&lt;br /&gt;
=== Soluzione proposta 1 ===&lt;br /&gt;
&lt;br /&gt;
Esercizio c2 (da controllare) da Flecart.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Stack&amp;lt;semaphore&amp;gt; stack[MAX_PRIORITY];&lt;br /&gt;
int num_V = 0;&lt;br /&gt;
semaphore mutex(1);&lt;br /&gt;
&lt;br /&gt;
void  PLP(int prio) {&lt;br /&gt;
    mutex.P();&lt;br /&gt;
    if (num_V &amp;gt; 0) {&lt;br /&gt;
        num_V--;&lt;br /&gt;
        mutex.V();&lt;br /&gt;
        return;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    semaphore sem = semaphore(0);&lt;br /&gt;
    stack[prio].push(sem);&lt;br /&gt;
    mutex.V();&lt;br /&gt;
    sem.P();&lt;br /&gt;
&lt;br /&gt;
    mutex.V();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void PLV() {&lt;br /&gt;
    mutex.P();&lt;br /&gt;
    &lt;br /&gt;
    for (int i = MAX_PRIORITY - 1; i &amp;gt;= 0; i--) {&lt;br /&gt;
        if (stack[i].size() &amp;gt; 0) {&lt;br /&gt;
            sem = stack[i].pop();&lt;br /&gt;
            sem.V();&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    num_V++;&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;
&lt;br /&gt;
= Prova 2021/05/26 =&lt;br /&gt;
&lt;br /&gt;
== Consegna c1 == &lt;br /&gt;
&lt;br /&gt;
Esercizio c.1: Un buffer sincrono strampalato (bss) ha due procedure entry:&lt;br /&gt;
void put(T value)&lt;br /&gt;
list of T get(void)&lt;br /&gt;
La entry put viene utilizzata per aggiungere un elemento e la entry get per leggere tutti quelli disponibili.&lt;br /&gt;
Se più processi chiamano la put quando nessun processo è in attesa per una get, rimangono tutti bloccati.&lt;br /&gt;
Quando successivamente un processo chiama la get riceve la lista di tutti gli elementi inseriti con le put e&lt;br /&gt;
tutti i processi vengono sbloccati.&lt;br /&gt;
Se il buffer è vuoto tutti i processi che chiamano la get rimangono bloccati. quando un processo chiama&lt;br /&gt;
successivamente la put tutti i processi in attesa per la get si sbloccano e ricevono lo stesso valore di ritorno:&lt;br /&gt;
una lista contenente il solo valore passato come parametro alla put. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Soluzione proposta 1 ===&lt;br /&gt;
&lt;br /&gt;
Soluzione proposta da [https://so.v2.cs.unibo.it/wiki/index.php/User:Flecart Flecart]&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
int num = 0; // se è positiva rappresenta numero di gets che aspettano, se negativa, numero di puts&lt;br /&gt;
semaphore semput(0);&lt;br /&gt;
semaphore semget(0);&lt;br /&gt;
semaphore mutex(1);&lt;br /&gt;
list&amp;lt;T&amp;gt; global_list;&lt;br /&gt;
&lt;br /&gt;
void put(T value) {&lt;br /&gt;
    //&amp;lt; await(num &amp;gt; 0) --&amp;gt; global_list.add(value) &amp;gt;&lt;br /&gt;
    mutex.P();&lt;br /&gt;
    if (num &amp;lt;= 0) {&lt;br /&gt;
        num--;&lt;br /&gt;
        mutex.V();&lt;br /&gt;
        semput.P();&lt;br /&gt;
        num++;&lt;br /&gt;
    }&lt;br /&gt;
    global_list.add(value);&lt;br /&gt;
&lt;br /&gt;
    if (num &amp;lt; 0)&lt;br /&gt;
        semput.V();&lt;br /&gt;
    else &lt;br /&gt;
        semget.V();&lt;br /&gt;
&lt;br /&gt;
    return;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
list of T get() {&lt;br /&gt;
    list&amp;lt;T&amp;gt; local_list;&lt;br /&gt;
&lt;br /&gt;
    mutex.P();&lt;br /&gt;
    if (num &amp;gt;= 0) {&lt;br /&gt;
        num++;&lt;br /&gt;
        mutex.V();&lt;br /&gt;
        semget.P();&lt;br /&gt;
        num--;&lt;br /&gt;
    } else {&lt;br /&gt;
        semput.V();&lt;br /&gt;
        semget.P();&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    local_list = global_list; // fa deep copy&lt;br /&gt;
&lt;br /&gt;
    if (num &amp;gt; 0) {&lt;br /&gt;
        semget.V();&lt;br /&gt;
    } else {&lt;br /&gt;
        global_list = list&amp;lt;T&amp;gt;();&lt;br /&gt;
        mutex.V(); &lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    return local_list;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&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:Gio Gio]&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
class bss{&lt;br /&gt;
  int waiting_put=0;&lt;br /&gt;
  int waiting_get=0;&lt;br /&gt;
  cond cw,cg;&lt;br /&gt;
  queue&amp;lt;T&amp;gt; q;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
  void put(T value){&lt;br /&gt;
    q.push(T);&lt;br /&gt;
    if(waiting_get&amp;gt;0){&lt;br /&gt;
      cg.signal()&lt;br /&gt;
    }else{&lt;br /&gt;
      waiting_put++;&lt;br /&gt;
      cw.wait();&lt;br /&gt;
      waiting_put--;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  list&amp;lt;T&amp;gt; get(){&lt;br /&gt;
    if(waiting_put&amp;gt;0){&lt;br /&gt;
      while(waiting_put&amp;gt;0){&lt;br /&gt;
        cw.signal();&lt;br /&gt;
      }&lt;br /&gt;
    }else{&lt;br /&gt;
      waiting_get++;&lt;br /&gt;
      cg.wait();&lt;br /&gt;
      waiting_get--;&lt;br /&gt;
    }&lt;br /&gt;
    list&amp;lt;T&amp;gt; p= q.tolist();&lt;br /&gt;
    if(waiting_get&amp;gt;0){&lt;br /&gt;
      cg.signal();&lt;br /&gt;
    }&lt;br /&gt;
    q.removeAll();&lt;br /&gt;
    return p;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== esercizio c2 == &lt;br /&gt;
&lt;br /&gt;
Dato un servizio di message passing asincrono implementare un servizio di message passing&lt;br /&gt;
asincrono a selezione di mittenti (samp) senza fare uso di processi server.&lt;br /&gt;
Il servizio samp ha due primitive:&lt;br /&gt;
sasend(message , destination)&lt;br /&gt;
sarecv(senders)&lt;br /&gt;
dove senders è un insieme.&lt;br /&gt;
la sarecv restituisce il primo messaggio che uno dei processi in senders ha spedito al processo ricevente&lt;br /&gt;
usando la sasend (o spedito da qualsiasi processo se senders è vuoto).&lt;br /&gt;
&lt;br /&gt;
=== Soluzione proposta 1 === &lt;br /&gt;
&lt;br /&gt;
Soluzione proposta da [https://so.v2.cs.unibo.it/wiki/index.php/User:Flecart Flecart]&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
sasend(message, destination) {&lt;br /&gt;
	pid t = getpid();&lt;br /&gt;
	asend(&amp;lt;message, t&amp;gt;, destination);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// variabile privata di sarecv&lt;br /&gt;
queue all_messages[MAX_PROC];&lt;br /&gt;
&lt;br /&gt;
// stora tutti i messaggi ricevuti, lo utilizziamo come queue per tutti, con &lt;br /&gt;
// anche la possibilità di rimuovere in un punto a scelta.&lt;br /&gt;
vector&amp;lt;&amp;lt;messages, pid&amp;gt;&amp;gt; msg; &lt;br /&gt;
sarecv(senders) {&lt;br /&gt;
	if (senders.len() == 0) {&lt;br /&gt;
		if (msg.len() == 0) {&lt;br /&gt;
			&amp;lt;message, sender&amp;gt; = arecv(ANY);&lt;br /&gt;
			return message;&lt;br /&gt;
		} else {&lt;br /&gt;
			&amp;lt;message, sender&amp;gt; = msg.pop_back();&lt;br /&gt;
			return message;&lt;br /&gt;
		}&lt;br /&gt;
	} else {&lt;br /&gt;
		do {&lt;br /&gt;
			for (idx in senders) {&lt;br /&gt;
				if (all_messages[idx].size() &amp;gt; 0) {&lt;br /&gt;
					message = all_messages[idx].dequeue();&lt;br /&gt;
					// rimuove il singolo messaggio dal vector, non tutti quelli uguali.&lt;br /&gt;
					msg.remove(&amp;lt;message, idx&amp;gt;);&lt;br /&gt;
					return message;&lt;br /&gt;
				}&lt;br /&gt;
			}	&lt;br /&gt;
			&lt;br /&gt;
			&amp;lt;message, sender&amp;gt; = arecv(ANY);&lt;br /&gt;
			msg.push_back(&amp;lt;message, sender&amp;gt;);&lt;br /&gt;
			all_messages[sender].enqueue(&amp;lt;message&amp;gt;);&lt;br /&gt;
		} while(true);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Gio</name></author>
	</entry>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=Prove_scritte_2021&amp;diff=2876</id>
		<title>Prove scritte 2021</title>
		<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php?title=Prove_scritte_2021&amp;diff=2876"/>
		<updated>2023-01-14T16:19:01Z</updated>

		<summary type="html">&lt;p&gt;Gio: /* Prova 2021/09/15 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
= Prova 21/07/2021=&lt;br /&gt;
&lt;br /&gt;
== Es C1 (da correggere) == &lt;br /&gt;
&lt;br /&gt;
Soluzione proposta da [https://so.v2.cs.unibo.it/wiki/index.php/User:Flecart Flecart friend],regalo a flecart la proprietà intellettuale di questa soluzione&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;class node{&lt;br /&gt;
  node parent;&lt;br /&gt;
  sq sq1;&lt;br /&gt;
  cond c;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
class BinTree{&lt;br /&gt;
  vector&amp;lt;node&amp;gt; base;&lt;br /&gt;
  void create(int N){&lt;br /&gt;
    base=new vector&amp;lt;node&amp;gt;(2^N);&lt;br /&gt;
    for(int i=0;i&amp;lt;2^N;i++)&lt;br /&gt;
      base[i]=new node(null,0,new cond);&lt;br /&gt;
    for(int i=1;i&amp;lt;=N;i++){&lt;br /&gt;
      for(int j=0;j&amp;lt;2^(N-i);j++){&lt;br /&gt;
        get(j,i-1).parent=get(j+i,i-1).parent=new node(null,0,new cond);&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  node get(int i,int level){&lt;br /&gt;
    return get(base[i],level);&lt;br /&gt;
  }&lt;br /&gt;
  node get(node n,int level){&lt;br /&gt;
    if(level==0){&lt;br /&gt;
      return node;&lt;br /&gt;
    }&lt;br /&gt;
    return get(node.parent,level-1);&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class Torneo{&lt;br /&gt;
  BinTree bin(N);&lt;br /&gt;
  int forma[2^N];&lt;br /&gt;
  bool win;&lt;br /&gt;
&lt;br /&gt;
  bool gioca(int i,int turno,int forma){&lt;br /&gt;
    forma[i]=forma;&lt;br /&gt;
    if null==bin.get(i,turno).sq1{&lt;br /&gt;
      bin.get(i,turno).sq1=i;&lt;br /&gt;
      bin.get(i,turno).c.wait();&lt;br /&gt;
      return !win;&lt;br /&gt;
    }else{&lt;br /&gt;
      sq1= bin.get(i,turno).sq1;&lt;br /&gt;
      if(forma[sq1]==forma[i]){&lt;br /&gt;
        win=random();&lt;br /&gt;
      }else{&lt;br /&gt;
        win=forma[sq1]&amp;lt;forma[i];&lt;br /&gt;
      }&lt;br /&gt;
      bin.get(i,turno).signal();&lt;br /&gt;
    }&lt;br /&gt;
    return win;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Prova 2021/09/15 =&lt;br /&gt;
&lt;br /&gt;
== Esercizio C1 == &lt;br /&gt;
&lt;br /&gt;
=== Consegna === &lt;br /&gt;
Esercizio c.1: Scrivere il monitor alrv (at least rendez-vous) che fornisce una sola procedure entry:&lt;br /&gt;
procedure entry void at_least(int n)&lt;br /&gt;
Quando un processo chiama la funzione at_least vuol dire che vuole sincronizzarsi con un insieme di almeno n&lt;br /&gt;
processi (incluso il chiamante).&lt;br /&gt;
Esempi:&lt;br /&gt;
Se un processo chiama at_least(1) non si blocca.&lt;br /&gt;
Se il processo p chiama at_least(2) si blocca, se poi il processo q chiama at_least(2) oppure at_least(1) si&lt;br /&gt;
sbloccano sia p sia q (la richiesta di p è soddisfatta, ne aspettava almeno 2, p e q)&lt;br /&gt;
Se il processo p chiama at_least(2) si blocca, se poi il processo q chiama at_least(3) si blocca anch'esso perché&lt;br /&gt;
sebbene la richiesta di p possa essere soddisfatta, q non può ancora sbloccarsi: ci sono solo 2 processi in attesa mentre&lt;br /&gt;
q ne vuole 3. Un terzo processo che chiami at_least(x) con x=1,2,3 li sblocca tutti.&lt;br /&gt;
Hint: sia w[k ] il numero dei processi in attesa di essere in almeno k (quelli che hanno chiamato at_least(k) e non&lt;br /&gt;
hanno completato l'esecuzione della funzione). Sia s[n]=∑&lt;br /&gt;
k=1&lt;br /&gt;
n&lt;br /&gt;
w[k ] (rappresenta il numero di processi soddisfacibili:&lt;br /&gt;
e.g. se ci sono 4 processi in attesa, potrebbero essere soddisfatte le richieste dei processi che ne aspettano almeno 2,&lt;br /&gt;
almeno 3 o almeno 4). Preso, se esiste, il massimo indice m tale che s[m]≥m tutti i processi in attesa di essere in n,&lt;br /&gt;
per n≤m possono essere sbloccati.&lt;br /&gt;
&lt;br /&gt;
=== 1. Soluzione proposta ===&lt;br /&gt;
Soluzione proposta da [https://so.v2.cs.unibo.it/wiki/index.php/User:Flecart Flecart]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
extern int MAX;  // il massimo numero di attesa&lt;br /&gt;
monitor alrv {&lt;br /&gt;
	int w[MAX];&lt;br /&gt;
	int s[MAX];&lt;br /&gt;
	condition c[MAX];&lt;br /&gt;
&lt;br /&gt;
	init() {&lt;br /&gt;
		for (int i = 0; i &amp;lt; MAX; i++) {&lt;br /&gt;
			w[i] = s[i] = 0;&lt;br /&gt;
		}&lt;br /&gt;
	}	&lt;br /&gt;
&lt;br /&gt;
procedure entry void at_least(int n) {&lt;br /&gt;
	if (n &amp;gt;= MAX || n &amp;lt;= 0) raise error;&lt;br /&gt;
	&lt;br /&gt;
	int i;&lt;br /&gt;
	for (i = n; i &amp;lt; MAX; i++) s[i]++;&lt;br /&gt;
	&lt;br /&gt;
	for (i = MAX - 1; i &amp;gt; 0; i--) {&lt;br /&gt;
		if (s[i] &amp;gt;= i) break;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	if (i &amp;gt; 0) {&lt;br /&gt;
		for (int j = 0; j &amp;lt;= i; j++) {&lt;br /&gt;
			while (w[j] &amp;gt; 0) {&lt;br /&gt;
				c[j].signal();&lt;br /&gt;
				w[j]--;&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
		&lt;br /&gt;
		s[0] = 0;&lt;br /&gt;
		for (int i = 1; i &amp;lt; MAX; i++) {&lt;br /&gt;
			s[i] = w[i] + s[i - 1];&lt;br /&gt;
		}&lt;br /&gt;
	} else {&lt;br /&gt;
		w[n]++;&lt;br /&gt;
		c[n].wait();&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Soluzione proposta da [https://so.v2.cs.unibo.it/wiki/index.php/User:Flecart Flecart friend],regalo a flecart la proprietà intellettuale di questa soluzione&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
class Monitor{&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
  min_heap&amp;lt;(int,cond)&amp;gt; h;&lt;br /&gt;
&lt;br /&gt;
  void at_least(int n){&lt;br /&gt;
    int sum=0;&lt;br /&gt;
    int max_to_sblock= -INF;&lt;br /&gt;
    cond c = new cond(n);&lt;br /&gt;
    h.push((n,c));&lt;br /&gt;
    // la heap viene visitata in maniera crescente&lt;br /&gt;
    for(auto f=h.begin_iter();null!=f.next();f++) {&lt;br /&gt;
        sum++;&lt;br /&gt;
        if(f.0&amp;lt;=sum){&lt;br /&gt;
          max_to_sblock =f.0;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    for(auto f=h.begin_iter();null!=f.next();f++) {&lt;br /&gt;
        if(f.0&amp;lt;=max_to_sblock){&lt;br /&gt;
          f.1.signal();&lt;br /&gt;
          h.remove(c);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    if(n&amp;gt;max_to_sblock){&lt;br /&gt;
      c.wait();&lt;br /&gt;
    }&lt;br /&gt;
    free(c)&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Prova 2021/06/23 =&lt;br /&gt;
&lt;br /&gt;
== Esercizio C1 == &lt;br /&gt;
&lt;br /&gt;
=== Consegna === &lt;br /&gt;
Esercizio c.1: Scrivere il monitor delayvalue con una sola procedure entry:&lt;br /&gt;
  int delay(int value);&lt;br /&gt;
Il monitor deve sospendere i primi NDELAY processi che chiamano la delay. Le successive chiamate di delay&lt;br /&gt;
devono mantenere costante il numero di processi sospesi, ogni successiva chiamata devo riattivare il primo&lt;br /&gt;
processo in attesa prima di sospendersi, la delay ritorna il valore passato come parametro dal processo che&lt;br /&gt;
ne ha riattivato l'esecuzione. e.g. se NDELAY è 2:&lt;br /&gt;
  P1: delay(44) -&amp;gt; P1 si sospende&lt;br /&gt;
  P2: delay(40) -&amp;gt; P2 si sospende&lt;br /&gt;
  P3: delay(42) -&amp;gt; P1 si riattiva e ritorna 42, P3 si sospende&lt;br /&gt;
  P4: delay(22) -&amp;gt; P2 si riattiva e ritorna 22, P4 si sospende&lt;br /&gt;
&lt;br /&gt;
=== Soluzione proposta 1 ===&lt;br /&gt;
Soluzione proposta da [https://so.v2.cs.unibo.it/wiki/index.php/User:Flecart Flecart], da controllare&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// variabile definita altrove.&lt;br /&gt;
extern int NDELAY;&lt;br /&gt;
&lt;br /&gt;
class Monitor {&lt;br /&gt;
    Queue&amp;lt;condition&amp;gt; stopped;&lt;br /&gt;
    int curr_value;&lt;br /&gt;
    Monitor {&lt;br /&gt;
        stopped = Queue&amp;lt;condition&amp;gt;();&lt;br /&gt;
        curr_value = 0;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    int delay(int value) {&lt;br /&gt;
        curr_value = value;&lt;br /&gt;
        if (stopped.size() == NDELAY) {&lt;br /&gt;
            condition first = stopped.dequeue();&lt;br /&gt;
            first.signal();&lt;br /&gt;
        }&lt;br /&gt;
        condition c = new condition();&lt;br /&gt;
        stopped.enqueue(c);&lt;br /&gt;
        c.wait();    &lt;br /&gt;
&lt;br /&gt;
        return curr_value;&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 c2 ==&lt;br /&gt;
&lt;br /&gt;
=== Consegna ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Esercizio c.2: Implementare usando semafori ordinari (fair, fifo) un servizio di semafori a priorità lifo che&lt;br /&gt;
fornisca le seguenti primitive:&lt;br /&gt;
 void PLP(int prio);&lt;br /&gt;
 void PLV()&lt;br /&gt;
PLP e PLV si devono comportare rispettivamente come P e V. Quando la PLV deve riattivare un processo&lt;br /&gt;
sceglie fra quelli in attesa quello a priorità massima, nel caso siano presenti più processi a priorità massima&lt;br /&gt;
sceglie quello in attesa da meno tempo. &lt;br /&gt;
&lt;br /&gt;
=== Soluzione proposta 1 ===&lt;br /&gt;
&lt;br /&gt;
Esercizio c2 (da controllare) da Flecart.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Stack&amp;lt;semaphore&amp;gt; stack[MAX_PRIORITY];&lt;br /&gt;
int num_V = 0;&lt;br /&gt;
semaphore mutex(1);&lt;br /&gt;
&lt;br /&gt;
void  PLP(int prio) {&lt;br /&gt;
    mutex.P();&lt;br /&gt;
    if (num_V &amp;gt; 0) {&lt;br /&gt;
        num_V--;&lt;br /&gt;
        mutex.V();&lt;br /&gt;
        return;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    semaphore sem = semaphore(0);&lt;br /&gt;
    stack[prio].push(sem);&lt;br /&gt;
    mutex.V();&lt;br /&gt;
    sem.P();&lt;br /&gt;
&lt;br /&gt;
    mutex.V();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void PLV() {&lt;br /&gt;
    mutex.P();&lt;br /&gt;
    &lt;br /&gt;
    for (int i = MAX_PRIORITY - 1; i &amp;gt;= 0; i--) {&lt;br /&gt;
        if (stack[i].size() &amp;gt; 0) {&lt;br /&gt;
            sem = stack[i].pop();&lt;br /&gt;
            sem.V();&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    num_V++;&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;
&lt;br /&gt;
= Prova 2021/05/26 =&lt;br /&gt;
&lt;br /&gt;
== Consegna c1 == &lt;br /&gt;
&lt;br /&gt;
Esercizio c.1: Un buffer sincrono strampalato (bss) ha due procedure entry:&lt;br /&gt;
void put(T value)&lt;br /&gt;
list of T get(void)&lt;br /&gt;
La entry put viene utilizzata per aggiungere un elemento e la entry get per leggere tutti quelli disponibili.&lt;br /&gt;
Se più processi chiamano la put quando nessun processo è in attesa per una get, rimangono tutti bloccati.&lt;br /&gt;
Quando successivamente un processo chiama la get riceve la lista di tutti gli elementi inseriti con le put e&lt;br /&gt;
tutti i processi vengono sbloccati.&lt;br /&gt;
Se il buffer è vuoto tutti i processi che chiamano la get rimangono bloccati. quando un processo chiama&lt;br /&gt;
successivamente la put tutti i processi in attesa per la get si sbloccano e ricevono lo stesso valore di ritorno:&lt;br /&gt;
una lista contenente il solo valore passato come parametro alla put. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Soluzione proposta 1 ===&lt;br /&gt;
&lt;br /&gt;
Soluzione proposta da [https://so.v2.cs.unibo.it/wiki/index.php/User:Flecart Flecart]&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
int num = 0; // se è positiva rappresenta numero di gets che aspettano, se negativa, numero di puts&lt;br /&gt;
semaphore semput(0);&lt;br /&gt;
semaphore semget(0);&lt;br /&gt;
semaphore mutex(1);&lt;br /&gt;
list&amp;lt;T&amp;gt; global_list;&lt;br /&gt;
&lt;br /&gt;
void put(T value) {&lt;br /&gt;
    //&amp;lt; await(num &amp;gt; 0) --&amp;gt; global_list.add(value) &amp;gt;&lt;br /&gt;
    mutex.P();&lt;br /&gt;
    if (num &amp;lt;= 0) {&lt;br /&gt;
        num--;&lt;br /&gt;
        mutex.V();&lt;br /&gt;
        semput.P();&lt;br /&gt;
        num++;&lt;br /&gt;
    }&lt;br /&gt;
    global_list.add(value);&lt;br /&gt;
&lt;br /&gt;
    if (num &amp;lt; 0)&lt;br /&gt;
        semput.V();&lt;br /&gt;
    else &lt;br /&gt;
        semget.V();&lt;br /&gt;
&lt;br /&gt;
    return;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
list of T get() {&lt;br /&gt;
    list&amp;lt;T&amp;gt; local_list;&lt;br /&gt;
&lt;br /&gt;
    mutex.P();&lt;br /&gt;
    if (num &amp;gt;= 0) {&lt;br /&gt;
        num++;&lt;br /&gt;
        mutex.V();&lt;br /&gt;
        semget.P();&lt;br /&gt;
        num--;&lt;br /&gt;
    } else {&lt;br /&gt;
        semput.V();&lt;br /&gt;
        semget.P();&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    local_list = global_list; // fa deep copy&lt;br /&gt;
&lt;br /&gt;
    if (num &amp;gt; 0) {&lt;br /&gt;
        semget.V();&lt;br /&gt;
    } else {&lt;br /&gt;
        global_list = list&amp;lt;T&amp;gt;();&lt;br /&gt;
        mutex.V(); &lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    return local_list;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&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:Gio Gio]&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
class bss{&lt;br /&gt;
  int waiting_put=0;&lt;br /&gt;
  int waiting_get=0;&lt;br /&gt;
  cond cw,cg;&lt;br /&gt;
  queue&amp;lt;T&amp;gt; q;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
  void put(T value){&lt;br /&gt;
    q.push(T);&lt;br /&gt;
    if(waiting_get&amp;gt;0){&lt;br /&gt;
      cg.signal()&lt;br /&gt;
    }else{&lt;br /&gt;
      waiting_put++;&lt;br /&gt;
      cw.wait();&lt;br /&gt;
      waiting_put--;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  list&amp;lt;T&amp;gt; get(){&lt;br /&gt;
    if(waiting_put&amp;gt;0){&lt;br /&gt;
      while(waiting_put&amp;gt;0){&lt;br /&gt;
        cw.signal();&lt;br /&gt;
      }&lt;br /&gt;
    }else{&lt;br /&gt;
      waiting_get++;&lt;br /&gt;
      cg.wait();&lt;br /&gt;
      waiting_get--;&lt;br /&gt;
    }&lt;br /&gt;
    list&amp;lt;T&amp;gt; p= q.tolist();&lt;br /&gt;
    if(waiting_get&amp;gt;0){&lt;br /&gt;
      cg.signal();&lt;br /&gt;
    }&lt;br /&gt;
    q.removeAll();&lt;br /&gt;
    return p;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== esercizio c2 == &lt;br /&gt;
&lt;br /&gt;
Dato un servizio di message passing asincrono implementare un servizio di message passing&lt;br /&gt;
asincrono a selezione di mittenti (samp) senza fare uso di processi server.&lt;br /&gt;
Il servizio samp ha due primitive:&lt;br /&gt;
sasend(message , destination)&lt;br /&gt;
sarecv(senders)&lt;br /&gt;
dove senders è un insieme.&lt;br /&gt;
la sarecv restituisce il primo messaggio che uno dei processi in senders ha spedito al processo ricevente&lt;br /&gt;
usando la sasend (o spedito da qualsiasi processo se senders è vuoto).&lt;br /&gt;
&lt;br /&gt;
=== Soluzione proposta 1 === &lt;br /&gt;
&lt;br /&gt;
Soluzione proposta da [https://so.v2.cs.unibo.it/wiki/index.php/User:Flecart Flecart]&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
sasend(message, destination) {&lt;br /&gt;
	pid t = getpid();&lt;br /&gt;
	asend(&amp;lt;message, t&amp;gt;, destination);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// variabile privata di sarecv&lt;br /&gt;
queue all_messages[MAX_PROC];&lt;br /&gt;
&lt;br /&gt;
// stora tutti i messaggi ricevuti, lo utilizziamo come queue per tutti, con &lt;br /&gt;
// anche la possibilità di rimuovere in un punto a scelta.&lt;br /&gt;
vector&amp;lt;&amp;lt;messages, pid&amp;gt;&amp;gt; msg; &lt;br /&gt;
sarecv(senders) {&lt;br /&gt;
	if (senders.len() == 0) {&lt;br /&gt;
		if (msg.len() == 0) {&lt;br /&gt;
			&amp;lt;message, sender&amp;gt; = arecv(ANY);&lt;br /&gt;
			return message;&lt;br /&gt;
		} else {&lt;br /&gt;
			&amp;lt;message, sender&amp;gt; = msg.pop_back();&lt;br /&gt;
			return message;&lt;br /&gt;
		}&lt;br /&gt;
	} else {&lt;br /&gt;
		do {&lt;br /&gt;
			for (idx in senders) {&lt;br /&gt;
				if (all_messages[idx].size() &amp;gt; 0) {&lt;br /&gt;
					message = all_messages[idx].dequeue();&lt;br /&gt;
					// rimuove il singolo messaggio dal vector, non tutti quelli uguali.&lt;br /&gt;
					msg.remove(&amp;lt;message, idx&amp;gt;);&lt;br /&gt;
					return message;&lt;br /&gt;
				}&lt;br /&gt;
			}	&lt;br /&gt;
			&lt;br /&gt;
			&amp;lt;message, sender&amp;gt; = arecv(ANY);&lt;br /&gt;
			msg.push_back(&amp;lt;message, sender&amp;gt;);&lt;br /&gt;
			all_messages[sender].enqueue(&amp;lt;message&amp;gt;);&lt;br /&gt;
		} while(true);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Gio</name></author>
	</entry>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=Prove_scritte_2022&amp;diff=2875</id>
		<title>Prove scritte 2022</title>
		<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php?title=Prove_scritte_2022&amp;diff=2875"/>
		<updated>2023-01-14T15:17:01Z</updated>

		<summary type="html">&lt;p&gt;Gio: /* Soluzione proposta (da controllare) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Prova 2022/09/06 =&lt;br /&gt;
&lt;br /&gt;
== Esercizio c1 == &lt;br /&gt;
&lt;br /&gt;
Esercizio c.1: I bit di un numero intero rappresentano condizioni di un sistema. Se lo stato attuale è 6 (0110) vuole dire&lt;br /&gt;
che attualmente sono vere le condizioni 2 (0010) e 4 (0100).&lt;br /&gt;
Scrivere un monitor bitcond che fornisca le seguenti procedure entry:&lt;br /&gt;
void set(int bit2set); accende nello stato attuale i bit di bit2set&lt;br /&gt;
void unset(int bit2unset) spegne nello stato attuale i bit di bit2unset&lt;br /&gt;
void statuswait(int bit2wait) attende che lo stato attuale soddisfi tutti le condizioni indicate in bit2wait (cioè&lt;br /&gt;
che tutti i bit in bit2wait siano accesi nello stato attuale).&lt;br /&gt;
Le richieste statuswait devono essere servite in ordine FIFO (cioè un processo anche se sono presenti tutte le&lt;br /&gt;
condizioni necessarie deve attendere se un processo che ha chiamato statuswait prima è in attesa).&lt;br /&gt;
Lo stato iniziale è zero (nessuna risorsa disponibile)&lt;br /&gt;
&lt;br /&gt;
=== Soluzione proposta 1 ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class bitcond{&lt;br /&gt;
  int bitmap;&lt;br /&gt;
  int lastBitmask;&lt;br /&gt;
  int has=0;&lt;br /&gt;
  &lt;br /&gt;
  condition waiting;&lt;br /&gt;
  condition c;&lt;br /&gt;
&lt;br /&gt;
  void set(int i){&lt;br /&gt;
    bitmap|=i; &lt;br /&gt;
      if(bitmap&amp;amp;lastBitmask == bitmap) c.signal();&lt;br /&gt;
  }&lt;br /&gt;
  void unset(int i){&lt;br /&gt;
    bitmap&amp;amp;=~i; &lt;br /&gt;
  }&lt;br /&gt;
  void statuswait(int i){&lt;br /&gt;
    has++; &lt;br /&gt;
    if(has&amp;gt;1){&lt;br /&gt;
      waiting.wait();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if(!(bitmap&amp;amp;i==i)){&lt;br /&gt;
      lastBitmask=i;&lt;br /&gt;
      c.wait();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    waiting.signal();&lt;br /&gt;
    has--;&lt;br /&gt;
  }&lt;br /&gt;
  bitcond(){&lt;br /&gt;
    bitmap = 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;
=== Soluzione proposta 2 ===&lt;br /&gt;
Proposta da [[User:Flecart|Flecart]] ([[User talk:Flecart|talk]]) 12:06, 14 January 2023 (CET)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
const int int_size = 32;&lt;br /&gt;
&lt;br /&gt;
class monitor {&lt;br /&gt;
    int value;&lt;br /&gt;
    condition bitset[int_size];&lt;br /&gt;
&lt;br /&gt;
    int numstatuswaiting;&lt;br /&gt;
    condition waiting;&lt;br /&gt;
    &lt;br /&gt;
    monitor() {&lt;br /&gt;
        value = 0;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    /// guarda se il bit n-significativo è settato in from&lt;br /&gt;
    bool nbit(int from, int n) {&lt;br /&gt;
        return (from &amp;amp; (1 &amp;lt;&amp;lt; n)) != 0&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void entry set(int bit2set) {&lt;br /&gt;
        value |= bit2set;&lt;br /&gt;
&lt;br /&gt;
        for (int i = 0; i &amp;lt; 32; i++) {&lt;br /&gt;
            if (nbit(value, i))&lt;br /&gt;
                bitset[i].signal();&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void entry statuswait(int bit2wait) {&lt;br /&gt;
        // in questo modo solamente un singolo processo è dentro ad aspettare&lt;br /&gt;
        // che tutte le condizioni siano rispettate&lt;br /&gt;
        if (numstatuswaiting &amp;gt; 0)&lt;br /&gt;
            waiting.wait();&lt;br /&gt;
        &lt;br /&gt;
        numstatuswaiting++;&lt;br /&gt;
        int i = 0;&lt;br /&gt;
        while(i &amp;lt; 32) {&lt;br /&gt;
            if (nbit(bit2wait, i) &amp;amp;&amp;amp; !nbit(value, i)) {&lt;br /&gt;
                bitset[i].wait();&lt;br /&gt;
&lt;br /&gt;
                // ricomincia a guardare tutti i bit da zero, perché&lt;br /&gt;
                // nel frattempo potrebbero essere cambiati.&lt;br /&gt;
                // -1 così con l'istruzione successiva diventa 0&lt;br /&gt;
                i = -1; &lt;br /&gt;
            }&lt;br /&gt;
            i++;&lt;br /&gt;
        }&lt;br /&gt;
        &lt;br /&gt;
        numstatuswaiting--;&lt;br /&gt;
        waiting.signal();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Soluzione proposta 3 ===&lt;br /&gt;
Proposta da [[User:Flecart|Flecart]] ([[User talk:Flecart|talk]]) 12:07, 14 January 2023 (CET)&lt;br /&gt;
questa è la soluzione più brutta, ma dovrebbe andare.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
const int int_size = 32;&lt;br /&gt;
&lt;br /&gt;
class monitor {&lt;br /&gt;
    int value;&lt;br /&gt;
    condition status;&lt;br /&gt;
&lt;br /&gt;
    int numstatuswaiting;&lt;br /&gt;
    condition waiting;&lt;br /&gt;
    &lt;br /&gt;
    monitor() {&lt;br /&gt;
        value = 0;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    /// guarda se il bit n-significativo è settato in from&lt;br /&gt;
    bool nbit(int from, int n) {&lt;br /&gt;
        return (from &amp;amp; (1 &amp;lt;&amp;lt; n)) != 0&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void entry set(int bit2set) {&lt;br /&gt;
        value |= bit2set;&lt;br /&gt;
        status.signal();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    void entry unset(int bit2unset) {&lt;br /&gt;
        value = (value &amp;amp; ~bit2unset);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void entry statuswait(int bit2wait) {&lt;br /&gt;
        // in questo modo solamente un singolo processo è dentro ad aspettare&lt;br /&gt;
        // che tutte le condizioni siano rispettate&lt;br /&gt;
        if (numstatuswaiting &amp;gt; 0)&lt;br /&gt;
            waiting.wait();&lt;br /&gt;
        &lt;br /&gt;
        numstatuswaiting++;&lt;br /&gt;
        while(true) {&lt;br /&gt;
            if ((value &amp;amp; bit2wait) == bit2wait) &lt;br /&gt;
                break;&lt;br /&gt;
            else &lt;br /&gt;
                status.wait();&lt;br /&gt;
        }&lt;br /&gt;
        numstatuswaiting--;&lt;br /&gt;
        waiting.signal();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Prova 2022/06/21 =&lt;br /&gt;
&lt;br /&gt;
== Esercizio c1 ==&lt;br /&gt;
Scrivere il monitor collocamento:&lt;br /&gt;
  void cercolavoro(char *nome, char *skill)&lt;br /&gt;
  void char *assumo(char * skill)&lt;br /&gt;
Quando un processo chiama la cercolavoro si mette in attesa di una richiesta di lavoro e rimane bloccato nel monitor&lt;br /&gt;
fino a che non è stato assunto. Nella cercolavoro viene indicato il nome dell'aspirante lavoratore la sua capacità (skill).&lt;br /&gt;
Un datore di lavoro con necessità di personale chiama la assumo specificando la capacità richiesta. Se c'è in attesa&lt;br /&gt;
almeno un aspirante lavoratore con quella specifica capacità (uguale valore di skill), il datore di lavoro riceve il nome del&lt;br /&gt;
nuovo dipendente ed entrambi i processi escono dal monitor. Nel caso non ci siano richieste compatibili il datore di&lt;br /&gt;
lavoro si blocca nel monitor attendendo un lavoratore con la capacità cercata. Quando arriva il lavoratore che soddisfa&lt;br /&gt;
le richieste si sbloccano entrambi i processi lavoratore e datore di lavoro. La assumo restituisce in ogni caso il nome del&lt;br /&gt;
dipendente da assumere.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Soluzione proposta === &lt;br /&gt;
&lt;br /&gt;
Soluzione proposta da [[User:Flecart|Flecart]] ([[User talk:Flecart|talk]]) 12:08, 14 January 2023 (CET)&lt;br /&gt;
&lt;br /&gt;
ci potrebbe essere un errore in quanto non è specificato il comportamento della struttura dati in alcune situazioni&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
class collocamento{&lt;br /&gt;
&lt;br /&gt;
set&amp;lt;char *, condition&amp;gt; richieste;  // chi assume cerca questa skill&lt;br /&gt;
set&amp;lt;char *, char *, condition&amp;gt; ricerche; // nome e skill di chi cerca&lt;br /&gt;
&lt;br /&gt;
char *last_nome;&lt;br /&gt;
&lt;br /&gt;
collocamento {&lt;br /&gt;
	last_nome = NULL;&lt;br /&gt;
	richieste = set();&lt;br /&gt;
	ricerche = set();	&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void cercolavoro(char *nome, char *skill) {&lt;br /&gt;
	datore = richieste.find(skill);  // cerca valutando la prima come chiave&lt;br /&gt;
	if (datore != NULL) {&lt;br /&gt;
		&amp;lt;skill, cond&amp;gt; = datore;&lt;br /&gt;
		richieste.remove(datore);&lt;br /&gt;
		last_nome = nome;&lt;br /&gt;
		cond.signal();		&lt;br /&gt;
	} else {&lt;br /&gt;
		condition c = new condition();&lt;br /&gt;
		ricerche.insert(nome, skill, c);&lt;br /&gt;
		c.wait();&lt;br /&gt;
		free(c);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void char *assumo(char * skill){&lt;br /&gt;
	lavoratore = ricerche.find2(skill); // cerca valutando la seconda come chiave.&lt;br /&gt;
	if (lavoratore != NULL) {&lt;br /&gt;
		&amp;lt;nome, skill, cond&amp;gt; = lavoratore;&lt;br /&gt;
		ricerche.remove(lavoratore);&lt;br /&gt;
		cond.signal();&lt;br /&gt;
		last_nome = nome;&lt;br /&gt;
	} else {&lt;br /&gt;
		condition c = new condition();&lt;br /&gt;
		richieste.insert(skill, c);&lt;br /&gt;
		c.wait();&lt;br /&gt;
		free(c);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	return last_nome;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
}// class collocamento&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Soluzione proposta === &lt;br /&gt;
&lt;br /&gt;
Soluzione proposta da [[User:Flecart|Flecart Frend]], regalo la proprietà intellettuale di questa soluzione a flecart.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
class workdisptcher{&lt;br /&gt;
&lt;br /&gt;
  // la multi map può storare più di un valore per una chiave&lt;br /&gt;
  // quando viene richiesta una particolare chiave da in maniera LIFO&lt;br /&gt;
  // il risultato&lt;br /&gt;
  // es:&lt;br /&gt;
  // multi_map&amp;lt;char *,int&amp;gt; lavoratori;&lt;br /&gt;
  // lavoratori.insert(&amp;quot;prova&amp;quot;,2);&lt;br /&gt;
  // lavoratori.insert(&amp;quot;prova&amp;quot;,1);&lt;br /&gt;
  // lavoratori.get(&amp;quot;prova&amp;quot;) == 2&lt;br /&gt;
  // lavoratori.remove(&amp;quot;prova&amp;quot;)&lt;br /&gt;
  // lavoratori.get(&amp;quot;prova&amp;quot;) == 1&lt;br /&gt;
  multi_map&amp;lt;char *,(char*,cond)&amp;gt; lavoratori;&lt;br /&gt;
  multi_map&amp;lt;char *,cond&amp;gt; posti_aperti;&lt;br /&gt;
  char* buffer_name;&lt;br /&gt;
  void cercolavoro(char *nome, char *skill){&lt;br /&gt;
    if(posti_aperti.find(skill)){&lt;br /&gt;
      auto entry =posti_aperti.get(skill);&lt;br /&gt;
      posti_aperti.remove(entry);&lt;br /&gt;
      buffer_name=name;&lt;br /&gt;
      entry.1.signal();&lt;br /&gt;
    }else{&lt;br /&gt;
      cond c= new cond();&lt;br /&gt;
      lavoratori.insert(skill,(nome,c)) ;&lt;br /&gt;
      c.wait();&lt;br /&gt;
      free(c);&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  void char *assumo(char * skill){&lt;br /&gt;
    if(lavoratori.find(skill)){&lt;br /&gt;
      auto entry =lavoratori.get(skill);&lt;br /&gt;
      posti_aperti.remove(entry);&lt;br /&gt;
      auto [nome,cnd] = entry.1;&lt;br /&gt;
      cond.signal();&lt;br /&gt;
      return nome;&lt;br /&gt;
    }else{&lt;br /&gt;
      cond c= new cond();&lt;br /&gt;
      posti_aperti.insert(skill,c) ;&lt;br /&gt;
      c.wait();&lt;br /&gt;
      free(c);&lt;br /&gt;
      return buffer_name;&lt;br /&gt;
    }&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 c2 ==&lt;br /&gt;
Un servizio viene fornito in modalità client-server usando message passing asincrono.&lt;br /&gt;
Al fine di aumentare l'efficienza si decide di usare molti server e un processo dispatcher in grado di distribuire le&lt;br /&gt;
richieste agli N server. Quando un processo server è libero riceve dal dispatcher la prossima richiesta da elaborare:&lt;br /&gt;
codice di ogni client (tanti!): .....&lt;br /&gt;
  asend(&amp;lt;getpid(), request&amp;gt;, dispatcher)&lt;br /&gt;
  result = arecv(dispatcher)&lt;br /&gt;
&lt;br /&gt;
server process[i], i = 0, ..., N-1:&lt;br /&gt;
 request = arecv(dispatcher)&lt;br /&gt;
 result = compute(request)&lt;br /&gt;
 asend(&amp;lt;getpid(), result&amp;gt;, dispatcher)&lt;br /&gt;
Scrivere il processo dispatcher. (il dispatcher conosce i pid di tutti i server).&lt;br /&gt;
&lt;br /&gt;
=== Soluzione proposta (da controllare) === &lt;br /&gt;
&lt;br /&gt;
Soluzione proposta da [https://so.v2.cs.unibo.it/wiki/index.php/User:Flecart Flecart] &lt;br /&gt;
&lt;br /&gt;
Questo esercizio è stato corretto tempo fa in classe dal professore, &amp;lt;bold&amp;gt;non è completamente corretto&amp;lt;/bold&amp;gt; perché &lt;br /&gt;
dovrei mandare ai server liberi, non a round-robin [[User:Flecart|Flecart]] ([[User talk:Flecart|talk]]) 15:52, 14 January 2023 (CET)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
extern int N;&lt;br /&gt;
process dispatcher() {&lt;br /&gt;
    // indice che tiene conto a quale server dover mandare&lt;br /&gt;
    // per semplicità supponiamo che i server abbiano PID&lt;br /&gt;
    // da 0 a N - 1&lt;br /&gt;
    int i = 0; &lt;br /&gt;
&lt;br /&gt;
    // mappa server a pid del processo che lo ha richiesto.&lt;br /&gt;
    // chiave: pid del server&lt;br /&gt;
    // value: queue richiesta dispatchata al server in chiave&lt;br /&gt;
    map&amp;lt;int, queue&amp;lt;int&amp;gt;&amp;gt; mapper; &lt;br /&gt;
    while (true) {&lt;br /&gt;
        res = arecv(ANY);&lt;br /&gt;
        &lt;br /&gt;
        // in questa parte l'importante è sapere&lt;br /&gt;
        // se la richiesta proviene dal  server o da un altro&lt;br /&gt;
        // processo, ho assunto che la disambiguazione &lt;br /&gt;
        // fosse immediata, un altro modo per checkare questo&lt;br /&gt;
        // è vedere se il PID del messaggio rientri fra quelli&lt;br /&gt;
        // noti al dispatcher.&lt;br /&gt;
        if (&amp;lt;pid, request&amp;gt; = res) {&lt;br /&gt;
            mapper[i].enqueue(pid);&lt;br /&gt;
            asend(request, i /*il i-esimo server*/);&lt;br /&gt;
            i++;&lt;br /&gt;
            i %= N;&lt;br /&gt;
        } else if (&amp;lt;pid, response&amp;gt; = res) {&lt;br /&gt;
            requester_pid = mapper[pid].dequeue();&lt;br /&gt;
            asend(response, requester_pid);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&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 frend] che cede a flecart la proprietà intellettuale di questa soluzione&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
dispatcher{&lt;br /&gt;
  queue&amp;lt;&amp;lt;pid,request&amp;gt;&amp;gt; work;&lt;br /&gt;
  queue&amp;lt;pid&amp;gt; freeserver;&lt;br /&gt;
  map&amp;lt;pid,pid&amp;gt; map_server_to_client;&lt;br /&gt;
  while(true){&lt;br /&gt;
    &amp;lt;pid,message&amp;gt;=arecv(ANY);&lt;br /&gt;
    if pid in servers{&lt;br /&gt;
      client=map_server_to_client.get(pid);&lt;br /&gt;
      map_client_to_server.remove(pid);&lt;br /&gt;
      freeserver.push(pid);&lt;br /&gt;
      asend(&amp;lt;message&amp;gt;,client);&lt;br /&gt;
    }else{&lt;br /&gt;
      work.push(&amp;lt;pid,message&amp;gt;);&lt;br /&gt;
    }&lt;br /&gt;
    while !freeserver.empty() and !work.emtpy(){&lt;br /&gt;
      server_pid = freeserver.pop();&lt;br /&gt;
      &amp;lt;client,msg&amp;gt; = work.pop();&lt;br /&gt;
      map_server_to_client.insert(server,client);&lt;br /&gt;
      asend(msg,server_pid);&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Prova 2022/06/01 =&lt;br /&gt;
&lt;br /&gt;
== Esercizio c1 ==&lt;br /&gt;
&lt;br /&gt;
Scrivere il monitor delay che fornisce due procedure entry:&lt;br /&gt;
  int wait_tick(int nticks)&lt;br /&gt;
  void tick(void)&lt;br /&gt;
La procedure entry tick è pensata per essere richiamata periodicamente (es. ogni secondo o ora o giorno) da un&lt;br /&gt;
processo.&lt;br /&gt;
Quando un processo chiama la wait_tick deve attendere un numero di chiamate della tick pari al parametro nticks.&lt;br /&gt;
Per esempio se un processo chiama wait_tick(2) deve fermarsi e verrà riattivato alla seconda successiva chiamata di&lt;br /&gt;
tick.&lt;br /&gt;
La funzione wait_tick ha come valore di ritorno il numero di processi che erano bloccati al momento della tick che ha&lt;br /&gt;
sbloccato il chiamante.&lt;br /&gt;
Esempio: P chiama wait_tick(2) e si blocca. Q chiama wait_tick(3) e si blocca. T chiama tick() non succede nulla. R&lt;br /&gt;
chiama wait_tick(2) e si blocca. T chiama tick(), viene sbloccata la wait_tick di P e il valore ritornato è 3. T chiama&lt;br /&gt;
tick(), vengono sbloccate le wait_tick di Q e R e il valore ritornato per entrambi i processi è 2&lt;br /&gt;
&lt;br /&gt;
=== Soluzione proprosta 1 (da controllare) ===&lt;br /&gt;
Soluzione proposta 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;
class MonitorDelay {&lt;br /&gt;
    int curr_time;&lt;br /&gt;
    int waiting_num;&lt;br /&gt;
&lt;br /&gt;
    // min heap con il tempo di sblocco dei processi e la condizione su cui è fermato&lt;br /&gt;
    // il tempo di sblocco minore è messo in cima alla heap&lt;br /&gt;
    // la sintassi con pair è ispirata alla std::pair di c++&lt;br /&gt;
    heap&amp;lt;pair&amp;lt;int, condition&amp;gt;&amp;gt; waiting; &lt;br /&gt;
&lt;br /&gt;
    void init() {&lt;br /&gt;
        curr_time = 0;&lt;br /&gt;
        waiting = heap&amp;lt;pair&amp;lt;int, condition&amp;gt;&amp;gt;();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    int entry wait_tick(int nticks) {&lt;br /&gt;
        if (nticks &amp;lt;= 0) {&lt;br /&gt;
            return waiting.size();&lt;br /&gt;
        } else {&lt;br /&gt;
            condition c = new condition();&lt;br /&gt;
            waiting.insert(make_pair(nticks + curr_time, c));&lt;br /&gt;
            c.wait();&lt;br /&gt;
            free(c);&lt;br /&gt;
        }&lt;br /&gt;
        return waiting_num;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    void entry tick(void) {&lt;br /&gt;
        waiting_num = waiting.size();&lt;br /&gt;
        curr_time++;&lt;br /&gt;
&lt;br /&gt;
        while (waiting.head().first &amp;lt;= curr_time) {&lt;br /&gt;
            condition c = waiting.head().second;&lt;br /&gt;
            waiting.deleteHead();&lt;br /&gt;
            c.signal();&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Esercizio c2 ==&lt;br /&gt;
&lt;br /&gt;
=== Consegna ===&lt;br /&gt;
&lt;br /&gt;
Esercizio c.2: Un servizio di message passing asincrono non fifo (nfasend/nfarecv) consegna in tempo finito tutti i&lt;br /&gt;
messaggi spediti ma non è garantito che i messaggi vengano ricevuti nell'ordine nel quale sono stati spediti.&lt;br /&gt;
  void nfasend(msg_t msg, pid_t dest)&lt;br /&gt;
  msg_t nfarecv(pid_t sender)&lt;br /&gt;
Dato un servizio di message passing asincrono non fifo scrivere una libreria che implementi il servizio di message&lt;br /&gt;
passing asincrono fifo:&lt;br /&gt;
  void asend(msg_t msg, pid_t dest)&lt;br /&gt;
  msg_t arecv(pid_t sender)&lt;br /&gt;
Nota: sia il servizio dato (non fifo) sia quello da implementare (fifo) consentono la ricezione solo da mittente specificato&lt;br /&gt;
(non supportano ANY/*).&lt;br /&gt;
&lt;br /&gt;
=== Soluzione proposta 1 ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void nfasend(msg_t msg, pid_t dest);&lt;br /&gt;
msg_t nfarecv(pid_t sender);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// array di grandezza di massimi numero di processi, inizializzato a 0&lt;br /&gt;
// utilizzato per contare il numero di messaggi inviati a un certo processo.&lt;br /&gt;
int num_sender[MAX_PROC];&lt;br /&gt;
&lt;br /&gt;
//RICORDA che ogni sender ha il suo num_sender[...]&lt;br /&gt;
&lt;br /&gt;
void asend(msg_t msg, pid_t dest) {&lt;br /&gt;
	src = getpid();&lt;br /&gt;
	nfasend(&amp;lt;msg, num_send[dest]&amp;gt;, dest);&lt;br /&gt;
	num_sender[dest]++;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// molto simile a num_sender, ma è utilizzato per contare il numero di messaggi ricevuti, in ordine.&lt;br /&gt;
int num_receiver[MAX_PROC];&lt;br /&gt;
// array heap ordinato sul int (per ogni heap in cima c'è il messaggio col minimo int).&lt;br /&gt;
min_heap&amp;lt;msg, int&amp;gt; messages[MAX_PROC];&lt;br /&gt;
&lt;br /&gt;
//RICORDA che ogni receiver ha il suo proprio num_receiver[...] e messages[...]&lt;br /&gt;
&lt;br /&gt;
msg_t arecv(pid_t sender) {&lt;br /&gt;
	p = getpid();&lt;br /&gt;
	&lt;br /&gt;
	if (messages[sender].size() &amp;gt; 0 &amp;amp;&amp;amp; messages[sender].top() == num_receiver[sender]) {&lt;br /&gt;
		(msg, num_mess) = messages[sender].removeTop();&lt;br /&gt;
		num_receiver[sender]++;&lt;br /&gt;
		return msg;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	(msg, num_mess) = nfarecv(sender);&lt;br /&gt;
&lt;br /&gt;
	while (num_mess != num_receiver[sender]) {&lt;br /&gt;
		messages[sender].insert(msg, num_mess);&lt;br /&gt;
		(msg, num_mess) = nfarecv(sender);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	num_receiver[sender]++;&lt;br /&gt;
	return msg;	&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Gio</name></author>
	</entry>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=Prove_scritte_2022&amp;diff=2874</id>
		<title>Prove scritte 2022</title>
		<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php?title=Prove_scritte_2022&amp;diff=2874"/>
		<updated>2023-01-14T15:11:32Z</updated>

		<summary type="html">&lt;p&gt;Gio: /* Soluzione proposta (da controllare) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Prova 2022/09/06 =&lt;br /&gt;
&lt;br /&gt;
== Esercizio c1 == &lt;br /&gt;
&lt;br /&gt;
Esercizio c.1: I bit di un numero intero rappresentano condizioni di un sistema. Se lo stato attuale è 6 (0110) vuole dire&lt;br /&gt;
che attualmente sono vere le condizioni 2 (0010) e 4 (0100).&lt;br /&gt;
Scrivere un monitor bitcond che fornisca le seguenti procedure entry:&lt;br /&gt;
void set(int bit2set); accende nello stato attuale i bit di bit2set&lt;br /&gt;
void unset(int bit2unset) spegne nello stato attuale i bit di bit2unset&lt;br /&gt;
void statuswait(int bit2wait) attende che lo stato attuale soddisfi tutti le condizioni indicate in bit2wait (cioè&lt;br /&gt;
che tutti i bit in bit2wait siano accesi nello stato attuale).&lt;br /&gt;
Le richieste statuswait devono essere servite in ordine FIFO (cioè un processo anche se sono presenti tutte le&lt;br /&gt;
condizioni necessarie deve attendere se un processo che ha chiamato statuswait prima è in attesa).&lt;br /&gt;
Lo stato iniziale è zero (nessuna risorsa disponibile)&lt;br /&gt;
&lt;br /&gt;
=== Soluzione proposta 1 ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class bitcond{&lt;br /&gt;
  int bitmap;&lt;br /&gt;
  int lastBitmask;&lt;br /&gt;
  int has=0;&lt;br /&gt;
  &lt;br /&gt;
  condition waiting;&lt;br /&gt;
  condition c;&lt;br /&gt;
&lt;br /&gt;
  void set(int i){&lt;br /&gt;
    bitmap|=i; &lt;br /&gt;
      if(bitmap&amp;amp;lastBitmask == bitmap) c.signal();&lt;br /&gt;
  }&lt;br /&gt;
  void unset(int i){&lt;br /&gt;
    bitmap&amp;amp;=~i; &lt;br /&gt;
  }&lt;br /&gt;
  void statuswait(int i){&lt;br /&gt;
    has++; &lt;br /&gt;
    if(has&amp;gt;1){&lt;br /&gt;
      waiting.wait();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if(!(bitmap&amp;amp;i==i)){&lt;br /&gt;
      lastBitmask=i;&lt;br /&gt;
      c.wait();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    waiting.signal();&lt;br /&gt;
    has--;&lt;br /&gt;
  }&lt;br /&gt;
  bitcond(){&lt;br /&gt;
    bitmap = 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;
=== Soluzione proposta 2 ===&lt;br /&gt;
Proposta da [[User:Flecart|Flecart]] ([[User talk:Flecart|talk]]) 12:06, 14 January 2023 (CET)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
const int int_size = 32;&lt;br /&gt;
&lt;br /&gt;
class monitor {&lt;br /&gt;
    int value;&lt;br /&gt;
    condition bitset[int_size];&lt;br /&gt;
&lt;br /&gt;
    int numstatuswaiting;&lt;br /&gt;
    condition waiting;&lt;br /&gt;
    &lt;br /&gt;
    monitor() {&lt;br /&gt;
        value = 0;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    /// guarda se il bit n-significativo è settato in from&lt;br /&gt;
    bool nbit(int from, int n) {&lt;br /&gt;
        return (from &amp;amp; (1 &amp;lt;&amp;lt; n)) != 0&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void entry set(int bit2set) {&lt;br /&gt;
        value |= bit2set;&lt;br /&gt;
&lt;br /&gt;
        for (int i = 0; i &amp;lt; 32; i++) {&lt;br /&gt;
            if (nbit(value, i))&lt;br /&gt;
                bitset[i].signal();&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void entry statuswait(int bit2wait) {&lt;br /&gt;
        // in questo modo solamente un singolo processo è dentro ad aspettare&lt;br /&gt;
        // che tutte le condizioni siano rispettate&lt;br /&gt;
        if (numstatuswaiting &amp;gt; 0)&lt;br /&gt;
            waiting.wait();&lt;br /&gt;
        &lt;br /&gt;
        numstatuswaiting++;&lt;br /&gt;
        int i = 0;&lt;br /&gt;
        while(i &amp;lt; 32) {&lt;br /&gt;
            if (nbit(bit2wait, i) &amp;amp;&amp;amp; !nbit(value, i)) {&lt;br /&gt;
                bitset[i].wait();&lt;br /&gt;
&lt;br /&gt;
                // ricomincia a guardare tutti i bit da zero, perché&lt;br /&gt;
                // nel frattempo potrebbero essere cambiati.&lt;br /&gt;
                // -1 così con l'istruzione successiva diventa 0&lt;br /&gt;
                i = -1; &lt;br /&gt;
            }&lt;br /&gt;
            i++;&lt;br /&gt;
        }&lt;br /&gt;
        &lt;br /&gt;
        numstatuswaiting--;&lt;br /&gt;
        waiting.signal();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Soluzione proposta 3 ===&lt;br /&gt;
Proposta da [[User:Flecart|Flecart]] ([[User talk:Flecart|talk]]) 12:07, 14 January 2023 (CET)&lt;br /&gt;
questa è la soluzione più brutta, ma dovrebbe andare.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
const int int_size = 32;&lt;br /&gt;
&lt;br /&gt;
class monitor {&lt;br /&gt;
    int value;&lt;br /&gt;
    condition status;&lt;br /&gt;
&lt;br /&gt;
    int numstatuswaiting;&lt;br /&gt;
    condition waiting;&lt;br /&gt;
    &lt;br /&gt;
    monitor() {&lt;br /&gt;
        value = 0;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    /// guarda se il bit n-significativo è settato in from&lt;br /&gt;
    bool nbit(int from, int n) {&lt;br /&gt;
        return (from &amp;amp; (1 &amp;lt;&amp;lt; n)) != 0&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void entry set(int bit2set) {&lt;br /&gt;
        value |= bit2set;&lt;br /&gt;
        status.signal();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    void entry unset(int bit2unset) {&lt;br /&gt;
        value = (value &amp;amp; ~bit2unset);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    void entry statuswait(int bit2wait) {&lt;br /&gt;
        // in questo modo solamente un singolo processo è dentro ad aspettare&lt;br /&gt;
        // che tutte le condizioni siano rispettate&lt;br /&gt;
        if (numstatuswaiting &amp;gt; 0)&lt;br /&gt;
            waiting.wait();&lt;br /&gt;
        &lt;br /&gt;
        numstatuswaiting++;&lt;br /&gt;
        while(true) {&lt;br /&gt;
            if ((value &amp;amp; bit2wait) == bit2wait) &lt;br /&gt;
                break;&lt;br /&gt;
            else &lt;br /&gt;
                status.wait();&lt;br /&gt;
        }&lt;br /&gt;
        numstatuswaiting--;&lt;br /&gt;
        waiting.signal();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Prova 2022/06/21 =&lt;br /&gt;
&lt;br /&gt;
== Esercizio c1 ==&lt;br /&gt;
Scrivere il monitor collocamento:&lt;br /&gt;
  void cercolavoro(char *nome, char *skill)&lt;br /&gt;
  void char *assumo(char * skill)&lt;br /&gt;
Quando un processo chiama la cercolavoro si mette in attesa di una richiesta di lavoro e rimane bloccato nel monitor&lt;br /&gt;
fino a che non è stato assunto. Nella cercolavoro viene indicato il nome dell'aspirante lavoratore la sua capacità (skill).&lt;br /&gt;
Un datore di lavoro con necessità di personale chiama la assumo specificando la capacità richiesta. Se c'è in attesa&lt;br /&gt;
almeno un aspirante lavoratore con quella specifica capacità (uguale valore di skill), il datore di lavoro riceve il nome del&lt;br /&gt;
nuovo dipendente ed entrambi i processi escono dal monitor. Nel caso non ci siano richieste compatibili il datore di&lt;br /&gt;
lavoro si blocca nel monitor attendendo un lavoratore con la capacità cercata. Quando arriva il lavoratore che soddisfa&lt;br /&gt;
le richieste si sbloccano entrambi i processi lavoratore e datore di lavoro. La assumo restituisce in ogni caso il nome del&lt;br /&gt;
dipendente da assumere.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Soluzione proposta (da controllare) === &lt;br /&gt;
&lt;br /&gt;
Soluzione proposta da [[User:Flecart|Flecart]] ([[User talk:Flecart|talk]]) 12:08, 14 January 2023 (CET)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
class collocamento{&lt;br /&gt;
&lt;br /&gt;
set&amp;lt;char *, condition&amp;gt; richieste;  // chi assume cerca questa skill&lt;br /&gt;
set&amp;lt;char *, char *, condition&amp;gt; ricerche; // nome e skill di chi cerca&lt;br /&gt;
&lt;br /&gt;
char *last_nome;&lt;br /&gt;
&lt;br /&gt;
collocamento {&lt;br /&gt;
	last_nome = NULL;&lt;br /&gt;
	richieste = set();&lt;br /&gt;
	ricerche = set();	&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void cercolavoro(char *nome, char *skill) {&lt;br /&gt;
	datore = richieste.find(skill);  // cerca valutando la prima come chiave&lt;br /&gt;
	if (datore != NULL) {&lt;br /&gt;
		&amp;lt;skill, cond&amp;gt; = datore;&lt;br /&gt;
		richieste.remove(datore);&lt;br /&gt;
		last_nome = nome;&lt;br /&gt;
		cond.signal();		&lt;br /&gt;
	} else {&lt;br /&gt;
		condition c = new condition();&lt;br /&gt;
		ricerche.insert(nome, skill, c);&lt;br /&gt;
		c.wait();&lt;br /&gt;
		free(c);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void char *assumo(char * skill){&lt;br /&gt;
	lavoratore = ricerche.find2(skill); // cerca valutando la seconda come chiave.&lt;br /&gt;
	if (lavoratore != NULL) {&lt;br /&gt;
		&amp;lt;nome, skill, cond&amp;gt; = lavoratore;&lt;br /&gt;
		ricerche.remove(lavoratore);&lt;br /&gt;
		cond.signal();&lt;br /&gt;
		last_nome = nome;&lt;br /&gt;
	} else {&lt;br /&gt;
		condition c = new condition();&lt;br /&gt;
		richieste.insert(skill, c);&lt;br /&gt;
		c.wait();&lt;br /&gt;
		free(c);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	return last_nome;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
}// class collocamento&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Esercizio c2 ==&lt;br /&gt;
Un servizio viene fornito in modalità client-server usando message passing asincrono.&lt;br /&gt;
Al fine di aumentare l'efficienza si decide di usare molti server e un processo dispatcher in grado di distribuire le&lt;br /&gt;
richieste agli N server. Quando un processo server è libero riceve dal dispatcher la prossima richiesta da elaborare:&lt;br /&gt;
codice di ogni client (tanti!): .....&lt;br /&gt;
  asend(&amp;lt;getpid(), request&amp;gt;, dispatcher)&lt;br /&gt;
  result = arecv(dispatcher)&lt;br /&gt;
&lt;br /&gt;
server process[i], i = 0, ..., N-1:&lt;br /&gt;
 request = arecv(dispatcher)&lt;br /&gt;
 result = compute(request)&lt;br /&gt;
 asend(&amp;lt;getpid(), result&amp;gt;, dispatcher)&lt;br /&gt;
Scrivere il processo dispatcher. (il dispatcher conosce i pid di tutti i server).&lt;br /&gt;
&lt;br /&gt;
=== Soluzione proposta (da controllare) === &lt;br /&gt;
&lt;br /&gt;
Soluzione proposta da [https://so.v2.cs.unibo.it/wiki/index.php/User:Flecart Flecart] &lt;br /&gt;
&lt;br /&gt;
Questo esercizio è stato corretto tempo fa in classe dal professore, &amp;lt;bold&amp;gt;non è completamente corretto&amp;lt;/bold&amp;gt; perché &lt;br /&gt;
dovrei mandare ai server liberi, non a round-robin [[User:Flecart|Flecart]] ([[User talk:Flecart|talk]]) 15:52, 14 January 2023 (CET)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
extern int N;&lt;br /&gt;
process dispatcher() {&lt;br /&gt;
    // indice che tiene conto a quale server dover mandare&lt;br /&gt;
    // per semplicità supponiamo che i server abbiano PID&lt;br /&gt;
    // da 0 a N - 1&lt;br /&gt;
    int i = 0; &lt;br /&gt;
&lt;br /&gt;
    // mappa server a pid del processo che lo ha richiesto.&lt;br /&gt;
    // chiave: pid del server&lt;br /&gt;
    // value: queue richiesta dispatchata al server in chiave&lt;br /&gt;
    map&amp;lt;int, queue&amp;lt;int&amp;gt;&amp;gt; mapper; &lt;br /&gt;
    while (true) {&lt;br /&gt;
        res = arecv(ANY);&lt;br /&gt;
        &lt;br /&gt;
        // in questa parte l'importante è sapere&lt;br /&gt;
        // se la richiesta proviene dal  server o da un altro&lt;br /&gt;
        // processo, ho assunto che la disambiguazione &lt;br /&gt;
        // fosse immediata, un altro modo per checkare questo&lt;br /&gt;
        // è vedere se il PID del messaggio rientri fra quelli&lt;br /&gt;
        // noti al dispatcher.&lt;br /&gt;
        if (&amp;lt;pid, request&amp;gt; = res) {&lt;br /&gt;
            mapper[i].enqueue(pid);&lt;br /&gt;
            asend(request, i /*il i-esimo server*/);&lt;br /&gt;
            i++;&lt;br /&gt;
            i %= N;&lt;br /&gt;
        } else if (&amp;lt;pid, response&amp;gt; = res) {&lt;br /&gt;
            requester_pid = mapper[pid].dequeue();&lt;br /&gt;
            asend(response, requester_pid);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&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 frend] che cede a flecart la proprietà intellettuale di questa soluzione&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
dispatcher{&lt;br /&gt;
  queue&amp;lt;&amp;lt;pid,request&amp;gt;&amp;gt; work;&lt;br /&gt;
  queue&amp;lt;pid&amp;gt; freeserver;&lt;br /&gt;
  map&amp;lt;pid,pid&amp;gt; map_server_to_client;&lt;br /&gt;
  while(true){&lt;br /&gt;
    &amp;lt;pid,message&amp;gt;=arecv(ANY);&lt;br /&gt;
    if pid in servers{&lt;br /&gt;
      client=map_server_to_client.get(pid);&lt;br /&gt;
      map_client_to_server.remove(pid);&lt;br /&gt;
      freeserver.push(pid);&lt;br /&gt;
      asend(&amp;lt;message&amp;gt;,client);&lt;br /&gt;
    }else{&lt;br /&gt;
      work.push(&amp;lt;pid,message&amp;gt;);&lt;br /&gt;
    }&lt;br /&gt;
    while !freeserver.empty() and !work.emtpy(){&lt;br /&gt;
      server_pid = freeserver.pop();&lt;br /&gt;
      &amp;lt;client,msg&amp;gt; = work.pop();&lt;br /&gt;
      map_server_to_client.insert(server,client);&lt;br /&gt;
      asend(msg,server_pid);&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Prova 2022/06/01 =&lt;br /&gt;
&lt;br /&gt;
== Esercizio c1 ==&lt;br /&gt;
&lt;br /&gt;
Scrivere il monitor delay che fornisce due procedure entry:&lt;br /&gt;
  int wait_tick(int nticks)&lt;br /&gt;
  void tick(void)&lt;br /&gt;
La procedure entry tick è pensata per essere richiamata periodicamente (es. ogni secondo o ora o giorno) da un&lt;br /&gt;
processo.&lt;br /&gt;
Quando un processo chiama la wait_tick deve attendere un numero di chiamate della tick pari al parametro nticks.&lt;br /&gt;
Per esempio se un processo chiama wait_tick(2) deve fermarsi e verrà riattivato alla seconda successiva chiamata di&lt;br /&gt;
tick.&lt;br /&gt;
La funzione wait_tick ha come valore di ritorno il numero di processi che erano bloccati al momento della tick che ha&lt;br /&gt;
sbloccato il chiamante.&lt;br /&gt;
Esempio: P chiama wait_tick(2) e si blocca. Q chiama wait_tick(3) e si blocca. T chiama tick() non succede nulla. R&lt;br /&gt;
chiama wait_tick(2) e si blocca. T chiama tick(), viene sbloccata la wait_tick di P e il valore ritornato è 3. T chiama&lt;br /&gt;
tick(), vengono sbloccate le wait_tick di Q e R e il valore ritornato per entrambi i processi è 2&lt;br /&gt;
&lt;br /&gt;
=== Soluzione proprosta 1 (da controllare) ===&lt;br /&gt;
Soluzione proposta 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;
class MonitorDelay {&lt;br /&gt;
    int curr_time;&lt;br /&gt;
    int waiting_num;&lt;br /&gt;
&lt;br /&gt;
    // min heap con il tempo di sblocco dei processi e la condizione su cui è fermato&lt;br /&gt;
    // il tempo di sblocco minore è messo in cima alla heap&lt;br /&gt;
    // la sintassi con pair è ispirata alla std::pair di c++&lt;br /&gt;
    heap&amp;lt;pair&amp;lt;int, condition&amp;gt;&amp;gt; waiting; &lt;br /&gt;
&lt;br /&gt;
    void init() {&lt;br /&gt;
        curr_time = 0;&lt;br /&gt;
        waiting = heap&amp;lt;pair&amp;lt;int, condition&amp;gt;&amp;gt;();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    int entry wait_tick(int nticks) {&lt;br /&gt;
        if (nticks &amp;lt;= 0) {&lt;br /&gt;
            return waiting.size();&lt;br /&gt;
        } else {&lt;br /&gt;
            condition c = new condition();&lt;br /&gt;
            waiting.insert(make_pair(nticks + curr_time, c));&lt;br /&gt;
            c.wait();&lt;br /&gt;
            free(c);&lt;br /&gt;
        }&lt;br /&gt;
        return waiting_num;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    void entry tick(void) {&lt;br /&gt;
        waiting_num = waiting.size();&lt;br /&gt;
        curr_time++;&lt;br /&gt;
&lt;br /&gt;
        while (waiting.head().first &amp;lt;= curr_time) {&lt;br /&gt;
            condition c = waiting.head().second;&lt;br /&gt;
            waiting.deleteHead();&lt;br /&gt;
            c.signal();&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Esercizio c2 ==&lt;br /&gt;
&lt;br /&gt;
=== Consegna ===&lt;br /&gt;
&lt;br /&gt;
Esercizio c.2: Un servizio di message passing asincrono non fifo (nfasend/nfarecv) consegna in tempo finito tutti i&lt;br /&gt;
messaggi spediti ma non è garantito che i messaggi vengano ricevuti nell'ordine nel quale sono stati spediti.&lt;br /&gt;
  void nfasend(msg_t msg, pid_t dest)&lt;br /&gt;
  msg_t nfarecv(pid_t sender)&lt;br /&gt;
Dato un servizio di message passing asincrono non fifo scrivere una libreria che implementi il servizio di message&lt;br /&gt;
passing asincrono fifo:&lt;br /&gt;
  void asend(msg_t msg, pid_t dest)&lt;br /&gt;
  msg_t arecv(pid_t sender)&lt;br /&gt;
Nota: sia il servizio dato (non fifo) sia quello da implementare (fifo) consentono la ricezione solo da mittente specificato&lt;br /&gt;
(non supportano ANY/*).&lt;br /&gt;
&lt;br /&gt;
=== Soluzione proposta 1 ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void nfasend(msg_t msg, pid_t dest);&lt;br /&gt;
msg_t nfarecv(pid_t sender);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// array di grandezza di massimi numero di processi, inizializzato a 0&lt;br /&gt;
// utilizzato per contare il numero di messaggi inviati a un certo processo.&lt;br /&gt;
int num_sender[MAX_PROC];&lt;br /&gt;
&lt;br /&gt;
//RICORDA che ogni sender ha il suo num_sender[...]&lt;br /&gt;
&lt;br /&gt;
void asend(msg_t msg, pid_t dest) {&lt;br /&gt;
	src = getpid();&lt;br /&gt;
	nfasend(&amp;lt;msg, num_send[dest]&amp;gt;, dest);&lt;br /&gt;
	num_sender[dest]++;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// molto simile a num_sender, ma è utilizzato per contare il numero di messaggi ricevuti, in ordine.&lt;br /&gt;
int num_receiver[MAX_PROC];&lt;br /&gt;
// array heap ordinato sul int (per ogni heap in cima c'è il messaggio col minimo int).&lt;br /&gt;
min_heap&amp;lt;msg, int&amp;gt; messages[MAX_PROC];&lt;br /&gt;
&lt;br /&gt;
//RICORDA che ogni receiver ha il suo proprio num_receiver[...] e messages[...]&lt;br /&gt;
&lt;br /&gt;
msg_t arecv(pid_t sender) {&lt;br /&gt;
	p = getpid();&lt;br /&gt;
	&lt;br /&gt;
	if (messages[sender].size() &amp;gt; 0 &amp;amp;&amp;amp; messages[sender].top() == num_receiver[sender]) {&lt;br /&gt;
		(msg, num_mess) = messages[sender].removeTop();&lt;br /&gt;
		num_receiver[sender]++;&lt;br /&gt;
		return msg;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	(msg, num_mess) = nfarecv(sender);&lt;br /&gt;
&lt;br /&gt;
	while (num_mess != num_receiver[sender]) {&lt;br /&gt;
		messages[sender].insert(msg, num_mess);&lt;br /&gt;
		(msg, num_mess) = nfarecv(sender);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	num_receiver[sender]++;&lt;br /&gt;
	return msg;	&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Gio</name></author>
	</entry>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=Prove_scritte_2020&amp;diff=2858</id>
		<title>Prove scritte 2020</title>
		<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php?title=Prove_scritte_2020&amp;diff=2858"/>
		<updated>2023-01-13T14:26:03Z</updated>

		<summary type="html">&lt;p&gt;Gio: /* esercizio c2 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Prova 2020/01/15 =&lt;br /&gt;
&lt;br /&gt;
== esercizio c1 == &lt;br /&gt;
&lt;br /&gt;
=== Soluzione proposta 1 ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
class TS{&lt;br /&gt;
&lt;br /&gt;
  int v=0;&lt;br /&gt;
  queue&amp;lt;(unsigned int,cond)&amp;gt; pq;&lt;br /&gt;
  usinged int timer;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
  void V(){&lt;br /&gt;
    if(pq.empty()){&lt;br /&gt;
      v++;&lt;br /&gt;
    }else{&lt;br /&gt;
      pq.pop().signal();&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  bool P(unsigned int timeout){&lt;br /&gt;
    if(v == 0){&lt;br /&gt;
      cond c = new condition();&lt;br /&gt;
      pq.push((timeout+timer,));&lt;br /&gt;
      c.wait();&lt;br /&gt;
      free(c);&lt;br /&gt;
      if timer== timeout+timer{&lt;br /&gt;
        return true;&lt;br /&gt;
      }&lt;br /&gt;
    }else{&lt;br /&gt;
      v--;&lt;br /&gt;
    }&lt;br /&gt;
    return false;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  void tick(){&lt;br /&gt;
    timer++;&lt;br /&gt;
    for [i,c] in pq.iter(){&lt;br /&gt;
      if( i &amp;lt;= timer) {&lt;br /&gt;
        c.signal();&lt;br /&gt;
        // la nostra stuttura dati supporta la rimozione durante lo scorrimento&lt;br /&gt;
        // per esempio può essere una lista&lt;br /&gt;
        pq.remove(c);&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;
=== Soluzione proposta 2 ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int value;&lt;br /&gt;
boolean ret_val;&lt;br /&gt;
int time;&lt;br /&gt;
min_heap&amp;lt;int, condition&amp;gt; heap;  // ordinato sul tempo minore.&lt;br /&gt;
vector&amp;lt;condition&amp;gt; queue; // vector utilizzato come queue, con rimozione anche nel mezzo.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
monitor {&lt;br /&gt;
	value = 0;&lt;br /&gt;
	time = 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void V(void) {&lt;br /&gt;
	if (heap.size() &amp;gt; 0) {&lt;br /&gt;
		condition c = queue.pop_back(); // remove and return&lt;br /&gt;
		heap.remove(c);  // rimuovi l'unico elemento con c.&lt;br /&gt;
		ret_val = true;&lt;br /&gt;
		c.signal();&lt;br /&gt;
	} else {&lt;br /&gt;
		value++;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
boolean P(unsigned int timeout) {	&lt;br /&gt;
	if (value &amp;gt; 0) {&lt;br /&gt;
		value--;&lt;br /&gt;
		return true;&lt;br /&gt;
	} else {&lt;br /&gt;
		int next_time = timeout + time;&lt;br /&gt;
		condition c = new condition();&lt;br /&gt;
		heap.insert(&amp;lt;next_time, c&amp;gt;);&lt;br /&gt;
		queue.push_back(c);&lt;br /&gt;
		c.wait();&lt;br /&gt;
		free(c);&lt;br /&gt;
		&lt;br /&gt;
		return ret_val;	&lt;br /&gt;
	}	&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void tick(void) {&lt;br /&gt;
	ret_val = false;&lt;br /&gt;
	time++;&lt;br /&gt;
	while (heap.size() &amp;gt; 0 &amp;amp;&amp;amp; heap.top().0 &amp;lt;= time) {&lt;br /&gt;
		condition c = heap.top().1;&lt;br /&gt;
		heap.deleteTop();&lt;br /&gt;
		queue.remove(c);&lt;br /&gt;
		c.signal();&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== esercizio c2 ==&lt;br /&gt;
&lt;br /&gt;
= Prova 2020/02/20 =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== esercizio c2 ==&lt;br /&gt;
&lt;br /&gt;
Sol : x alla seconda&lt;/div&gt;</summary>
		<author><name>Gio</name></author>
	</entry>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=Prove_scritte_2020&amp;diff=2857</id>
		<title>Prove scritte 2020</title>
		<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php?title=Prove_scritte_2020&amp;diff=2857"/>
		<updated>2023-01-13T14:24:20Z</updated>

		<summary type="html">&lt;p&gt;Gio: /* esercizio c2 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Prova 2020/01/15 =&lt;br /&gt;
&lt;br /&gt;
== esercizio c1 == &lt;br /&gt;
&lt;br /&gt;
=== Soluzione proposta 1 ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
class TS{&lt;br /&gt;
&lt;br /&gt;
  int v=0;&lt;br /&gt;
  queue&amp;lt;(unsigned int,cond)&amp;gt; pq;&lt;br /&gt;
  usinged int timer;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
  void V(){&lt;br /&gt;
    if(pq.empty()){&lt;br /&gt;
      v++;&lt;br /&gt;
    }else{&lt;br /&gt;
      pq.pop().signal();&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  bool P(unsigned int timeout){&lt;br /&gt;
    if(v == 0){&lt;br /&gt;
      cond c = new condition();&lt;br /&gt;
      pq.push((timeout+timer,));&lt;br /&gt;
      c.wait();&lt;br /&gt;
      free(c);&lt;br /&gt;
      if timer== timeout+timer{&lt;br /&gt;
        return true;&lt;br /&gt;
      }&lt;br /&gt;
    }else{&lt;br /&gt;
      v--;&lt;br /&gt;
    }&lt;br /&gt;
    return false;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  void tick(){&lt;br /&gt;
    timer++;&lt;br /&gt;
    for [i,c] in pq.iter(){&lt;br /&gt;
      if( i &amp;lt;= timer) {&lt;br /&gt;
        c.signal();&lt;br /&gt;
        // la nostra stuttura dati supporta la rimozione durante lo scorrimento&lt;br /&gt;
        // per esempio può essere una lista&lt;br /&gt;
        pq.remove(c);&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;
=== Soluzione proposta 2 ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int value;&lt;br /&gt;
boolean ret_val;&lt;br /&gt;
int time;&lt;br /&gt;
min_heap&amp;lt;int, condition&amp;gt; heap;  // ordinato sul tempo minore.&lt;br /&gt;
vector&amp;lt;condition&amp;gt; queue; // vector utilizzato come queue, con rimozione anche nel mezzo.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
monitor {&lt;br /&gt;
	value = 0;&lt;br /&gt;
	time = 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void V(void) {&lt;br /&gt;
	if (heap.size() &amp;gt; 0) {&lt;br /&gt;
		condition c = queue.pop_back(); // remove and return&lt;br /&gt;
		heap.remove(c);  // rimuovi l'unico elemento con c.&lt;br /&gt;
		ret_val = true;&lt;br /&gt;
		c.signal();&lt;br /&gt;
	} else {&lt;br /&gt;
		value++;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
boolean P(unsigned int timeout) {	&lt;br /&gt;
	if (value &amp;gt; 0) {&lt;br /&gt;
		value--;&lt;br /&gt;
		return true;&lt;br /&gt;
	} else {&lt;br /&gt;
		int next_time = timeout + time;&lt;br /&gt;
		condition c = new condition();&lt;br /&gt;
		heap.insert(&amp;lt;next_time, c&amp;gt;);&lt;br /&gt;
		queue.push_back(c);&lt;br /&gt;
		c.wait();&lt;br /&gt;
		free(c);&lt;br /&gt;
		&lt;br /&gt;
		return ret_val;	&lt;br /&gt;
	}	&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void tick(void) {&lt;br /&gt;
	ret_val = false;&lt;br /&gt;
	time++;&lt;br /&gt;
	while (heap.size() &amp;gt; 0 &amp;amp;&amp;amp; heap.top().0 &amp;lt;= time) {&lt;br /&gt;
		condition c = heap.top().1;&lt;br /&gt;
		heap.deleteTop();&lt;br /&gt;
		queue.remove(c);&lt;br /&gt;
		c.signal();&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== esercizio c2 ==&lt;br /&gt;
&lt;br /&gt;
= Prova 2020/02/20 =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== esercizio c2 ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;x^2&amp;lt;/math&amp;gt;&lt;/div&gt;</summary>
		<author><name>Gio</name></author>
	</entry>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=Prove_scritte_2020&amp;diff=2856</id>
		<title>Prove scritte 2020</title>
		<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php?title=Prove_scritte_2020&amp;diff=2856"/>
		<updated>2023-01-13T14:22:30Z</updated>

		<summary type="html">&lt;p&gt;Gio: /* Prova 2020/01/15 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Prova 2020/01/15 =&lt;br /&gt;
&lt;br /&gt;
== esercizio c1 == &lt;br /&gt;
&lt;br /&gt;
=== Soluzione proposta 1 ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
class TS{&lt;br /&gt;
&lt;br /&gt;
  int v=0;&lt;br /&gt;
  queue&amp;lt;(unsigned int,cond)&amp;gt; pq;&lt;br /&gt;
  usinged int timer;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
  void V(){&lt;br /&gt;
    if(pq.empty()){&lt;br /&gt;
      v++;&lt;br /&gt;
    }else{&lt;br /&gt;
      pq.pop().signal();&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  bool P(unsigned int timeout){&lt;br /&gt;
    if(v == 0){&lt;br /&gt;
      cond c = new condition();&lt;br /&gt;
      pq.push((timeout+timer,));&lt;br /&gt;
      c.wait();&lt;br /&gt;
      free(c);&lt;br /&gt;
      if timer== timeout+timer{&lt;br /&gt;
        return true;&lt;br /&gt;
      }&lt;br /&gt;
    }else{&lt;br /&gt;
      v--;&lt;br /&gt;
    }&lt;br /&gt;
    return false;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  void tick(){&lt;br /&gt;
    timer++;&lt;br /&gt;
    for [i,c] in pq.iter(){&lt;br /&gt;
      if( i &amp;lt;= timer) {&lt;br /&gt;
        c.signal();&lt;br /&gt;
        // la nostra stuttura dati supporta la rimozione durante lo scorrimento&lt;br /&gt;
        // per esempio può essere una lista&lt;br /&gt;
        pq.remove(c);&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;
=== Soluzione proposta 2 ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int value;&lt;br /&gt;
boolean ret_val;&lt;br /&gt;
int time;&lt;br /&gt;
min_heap&amp;lt;int, condition&amp;gt; heap;  // ordinato sul tempo minore.&lt;br /&gt;
vector&amp;lt;condition&amp;gt; queue; // vector utilizzato come queue, con rimozione anche nel mezzo.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
monitor {&lt;br /&gt;
	value = 0;&lt;br /&gt;
	time = 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void V(void) {&lt;br /&gt;
	if (heap.size() &amp;gt; 0) {&lt;br /&gt;
		condition c = queue.pop_back(); // remove and return&lt;br /&gt;
		heap.remove(c);  // rimuovi l'unico elemento con c.&lt;br /&gt;
		ret_val = true;&lt;br /&gt;
		c.signal();&lt;br /&gt;
	} else {&lt;br /&gt;
		value++;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
boolean P(unsigned int timeout) {	&lt;br /&gt;
	if (value &amp;gt; 0) {&lt;br /&gt;
		value--;&lt;br /&gt;
		return true;&lt;br /&gt;
	} else {&lt;br /&gt;
		int next_time = timeout + time;&lt;br /&gt;
		condition c = new condition();&lt;br /&gt;
		heap.insert(&amp;lt;next_time, c&amp;gt;);&lt;br /&gt;
		queue.push_back(c);&lt;br /&gt;
		c.wait();&lt;br /&gt;
		free(c);&lt;br /&gt;
		&lt;br /&gt;
		return ret_val;	&lt;br /&gt;
	}	&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void tick(void) {&lt;br /&gt;
	ret_val = false;&lt;br /&gt;
	time++;&lt;br /&gt;
	while (heap.size() &amp;gt; 0 &amp;amp;&amp;amp; heap.top().0 &amp;lt;= time) {&lt;br /&gt;
		condition c = heap.top().1;&lt;br /&gt;
		heap.deleteTop();&lt;br /&gt;
		queue.remove(c);&lt;br /&gt;
		c.signal();&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== esercizio c2 ==&lt;br /&gt;
&lt;br /&gt;
= Prova 2020/02/20 =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== esercizio c2 ==&lt;br /&gt;
&lt;br /&gt;
$x^2$&lt;/div&gt;</summary>
		<author><name>Gio</name></author>
	</entry>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=Prove_scritte_2020&amp;diff=2855</id>
		<title>Prove scritte 2020</title>
		<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php?title=Prove_scritte_2020&amp;diff=2855"/>
		<updated>2023-01-13T13:56:22Z</updated>

		<summary type="html">&lt;p&gt;Gio: /* esercizio c1 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Prova 2020/01/15 =&lt;br /&gt;
&lt;br /&gt;
== esercizio c1 == &lt;br /&gt;
&lt;br /&gt;
=== Soluzione proposta 1 ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
class TS{&lt;br /&gt;
&lt;br /&gt;
  int v=0;&lt;br /&gt;
  queue&amp;lt;(unsigned int,cond)&amp;gt; pq;&lt;br /&gt;
  usinged int timer;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
  void V(){&lt;br /&gt;
    if(pq.empty()){&lt;br /&gt;
      v++;&lt;br /&gt;
    }else{&lt;br /&gt;
      pq.pop().signal();&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  bool P(unsigned int timeout){&lt;br /&gt;
    if(v == 0){&lt;br /&gt;
      cond c = new condition();&lt;br /&gt;
      pq.push((timeout+timer,));&lt;br /&gt;
      c.wait();&lt;br /&gt;
      free(c);&lt;br /&gt;
      if timer== timeout+timer{&lt;br /&gt;
        return true;&lt;br /&gt;
      }&lt;br /&gt;
    }else{&lt;br /&gt;
      v--;&lt;br /&gt;
    }&lt;br /&gt;
    return false;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  void tick(){&lt;br /&gt;
    timer++;&lt;br /&gt;
    for [i,c] in pq.iter(){&lt;br /&gt;
      if( i &amp;lt;= timer) {&lt;br /&gt;
        c.signal();&lt;br /&gt;
        // la nostra stuttura dati supporta la rimozione durante lo scorrimento&lt;br /&gt;
        // per esempio può essere una lista&lt;br /&gt;
        pq.remove(c);&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;
=== Soluzione proposta 2 ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int value;&lt;br /&gt;
boolean ret_val;&lt;br /&gt;
int time;&lt;br /&gt;
min_heap&amp;lt;int, condition&amp;gt; heap;  // ordinato sul tempo minore.&lt;br /&gt;
vector&amp;lt;condition&amp;gt; queue; // vector utilizzato come queue, con rimozione anche nel mezzo.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
monitor {&lt;br /&gt;
	value = 0;&lt;br /&gt;
	time = 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void V(void) {&lt;br /&gt;
	if (heap.size() &amp;gt; 0) {&lt;br /&gt;
		condition c = queue.pop_back(); // remove and return&lt;br /&gt;
		heap.remove(c);  // rimuovi l'unico elemento con c.&lt;br /&gt;
		ret_val = true;&lt;br /&gt;
		c.signal();&lt;br /&gt;
	} else {&lt;br /&gt;
		value++;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
boolean P(unsigned int timeout) {	&lt;br /&gt;
	if (value &amp;gt; 0) {&lt;br /&gt;
		value--;&lt;br /&gt;
		return true;&lt;br /&gt;
	} else {&lt;br /&gt;
		int next_time = timeout + time;&lt;br /&gt;
		condition c = new condition();&lt;br /&gt;
		heap.insert(&amp;lt;next_time, c&amp;gt;);&lt;br /&gt;
		queue.push_back(c);&lt;br /&gt;
		c.wait();&lt;br /&gt;
		free(c);&lt;br /&gt;
		&lt;br /&gt;
		return ret_val;	&lt;br /&gt;
	}	&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void tick(void) {&lt;br /&gt;
	ret_val = false;&lt;br /&gt;
	time++;&lt;br /&gt;
	while (heap.size() &amp;gt; 0 &amp;amp;&amp;amp; heap.top().0 &amp;lt;= time) {&lt;br /&gt;
		condition c = heap.top().1;&lt;br /&gt;
		heap.deleteTop();&lt;br /&gt;
		queue.remove(c);&lt;br /&gt;
		c.signal();&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== esercizio c2 ==&lt;/div&gt;</summary>
		<author><name>Gio</name></author>
	</entry>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=Prove_scritte_2021&amp;diff=2845</id>
		<title>Prove scritte 2021</title>
		<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php?title=Prove_scritte_2021&amp;diff=2845"/>
		<updated>2023-01-13T11:02:47Z</updated>

		<summary type="html">&lt;p&gt;Gio: /* Prova 2021/05/26 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
= Prova 2021/09/15 =&lt;br /&gt;
&lt;br /&gt;
== Esercizio C1 == &lt;br /&gt;
&lt;br /&gt;
=== Consegna === &lt;br /&gt;
Esercizio c.1: Scrivere il monitor alrv (at least rendez-vous) che fornisce una sola procedure entry:&lt;br /&gt;
procedure entry void at_least(int n)&lt;br /&gt;
Quando un processo chiama la funzione at_least vuol dire che vuole sincronizzarsi con un insieme di almeno n&lt;br /&gt;
processi (incluso il chiamante).&lt;br /&gt;
Esempi:&lt;br /&gt;
Se un processo chiama at_least(1) non si blocca.&lt;br /&gt;
Se il processo p chiama at_least(2) si blocca, se poi il processo q chiama at_least(2) oppure at_least(1) si&lt;br /&gt;
sbloccano sia p sia q (la richiesta di p è soddisfatta, ne aspettava almeno 2, p e q)&lt;br /&gt;
Se il processo p chiama at_least(2) si blocca, se poi il processo q chiama at_least(3) si blocca anch'esso perché&lt;br /&gt;
sebbene la richiesta di p possa essere soddisfatta, q non può ancora sbloccarsi: ci sono solo 2 processi in attesa mentre&lt;br /&gt;
q ne vuole 3. Un terzo processo che chiami at_least(x) con x=1,2,3 li sblocca tutti.&lt;br /&gt;
Hint: sia w[k ] il numero dei processi in attesa di essere in almeno k (quelli che hanno chiamato at_least(k) e non&lt;br /&gt;
hanno completato l'esecuzione della funzione). Sia s[n]=∑&lt;br /&gt;
k=1&lt;br /&gt;
n&lt;br /&gt;
w[k ] (rappresenta il numero di processi soddisfacibili:&lt;br /&gt;
e.g. se ci sono 4 processi in attesa, potrebbero essere soddisfatte le richieste dei processi che ne aspettano almeno 2,&lt;br /&gt;
almeno 3 o almeno 4). Preso, se esiste, il massimo indice m tale che s[m]≥m tutti i processi in attesa di essere in n,&lt;br /&gt;
per n≤m possono essere sbloccati.&lt;br /&gt;
&lt;br /&gt;
=== 1. Soluzione proposta ===&lt;br /&gt;
Soluzione proposta da [https://so.v2.cs.unibo.it/wiki/index.php/User:Flecart Flecart]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
extern int MAX;  // il massimo numero di attesa&lt;br /&gt;
monitor alrv {&lt;br /&gt;
	int w[MAX];&lt;br /&gt;
	int s[MAX];&lt;br /&gt;
	condition c[MAX];&lt;br /&gt;
&lt;br /&gt;
	init() {&lt;br /&gt;
		for (int i = 0; i &amp;lt; MAX; i++) {&lt;br /&gt;
			w[i] = s[i] = 0;&lt;br /&gt;
		}&lt;br /&gt;
	}	&lt;br /&gt;
&lt;br /&gt;
procedure entry void at_least(int n) {&lt;br /&gt;
	if (n &amp;gt;= MAX || n &amp;lt;= 0) raise error;&lt;br /&gt;
	&lt;br /&gt;
	int i;&lt;br /&gt;
	for (i = n; i &amp;lt; MAX; i++) s[i]++;&lt;br /&gt;
	&lt;br /&gt;
	for (i = MAX - 1; i &amp;gt; 0; i--) {&lt;br /&gt;
		if (s[i] &amp;gt;= i) break;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	if (i &amp;gt; 0) {&lt;br /&gt;
		for (int j = 0; j &amp;lt;= i; j++) {&lt;br /&gt;
			while (w[j] &amp;gt; 0) {&lt;br /&gt;
				c[j].signal();&lt;br /&gt;
				w[j]--;&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
		&lt;br /&gt;
		s[0] = 0;&lt;br /&gt;
		for (int i = 1; i &amp;lt; MAX; i++) {&lt;br /&gt;
			s[i] = w[i] + s[i - 1];&lt;br /&gt;
		}&lt;br /&gt;
	} else {&lt;br /&gt;
		w[n]++;&lt;br /&gt;
		c[n].wait();&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Soluzione proposta da [https://so.v2.cs.unibo.it/wiki/index.php/User:Flecart Flecart frend],regalo a flecart la proprietà intellettuale di questa soluzione&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
class Monitor{&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
  min_heap&amp;lt;(int,cond)&amp;gt; h;&lt;br /&gt;
&lt;br /&gt;
  void at_least(int n){&lt;br /&gt;
    int sum=0;&lt;br /&gt;
    int max_to_sblock= -INF;&lt;br /&gt;
    cond c = new cond(n);&lt;br /&gt;
    h.push((n,c));&lt;br /&gt;
    // la heap viene visitata in maniera crescente&lt;br /&gt;
    for(auto f=h.begin_iter();null!=f.next();f++) {&lt;br /&gt;
        sum++;&lt;br /&gt;
        if(f.0&amp;lt;=sum){&lt;br /&gt;
          max_to_sblock =f.0;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    for(auto f=h.begin_iter();null!=f.next();f++) {&lt;br /&gt;
        if(f.0&amp;lt;=max_to_sblock){&lt;br /&gt;
          f.1.signal();&lt;br /&gt;
          h.remove(c);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    if(n&amp;gt;max_to_sblock){&lt;br /&gt;
      c.wait();&lt;br /&gt;
    }&lt;br /&gt;
    free(c)&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Prova 2021/06/23 =&lt;br /&gt;
&lt;br /&gt;
== Esercizio C1 == &lt;br /&gt;
&lt;br /&gt;
=== Consegna === &lt;br /&gt;
Esercizio c.1: Scrivere il monitor delayvalue con una sola procedure entry:&lt;br /&gt;
  int delay(int value);&lt;br /&gt;
Il monitor deve sospendere i primi NDELAY processi che chiamano la delay. Le successive chiamate di delay&lt;br /&gt;
devono mantenere costante il numero di processi sospesi, ogni successiva chiamata devo riattivare il primo&lt;br /&gt;
processo in attesa prima di sospendersi, la delay ritorna il valore passato come parametro dal processo che&lt;br /&gt;
ne ha riattivato l'esecuzione. e.g. se NDELAY è 2:&lt;br /&gt;
  P1: delay(44) -&amp;gt; P1 si sospende&lt;br /&gt;
  P2: delay(40) -&amp;gt; P2 si sospende&lt;br /&gt;
  P3: delay(42) -&amp;gt; P1 si riattiva e ritorna 42, P3 si sospende&lt;br /&gt;
  P4: delay(22) -&amp;gt; P2 si riattiva e ritorna 22, P4 si sospende&lt;br /&gt;
&lt;br /&gt;
=== Soluzione proposta 1 ===&lt;br /&gt;
Soluzione proposta da [https://so.v2.cs.unibo.it/wiki/index.php/User:Flecart Flecart], da controllare&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// variabile definita altrove.&lt;br /&gt;
extern int NDELAY;&lt;br /&gt;
&lt;br /&gt;
class Monitor {&lt;br /&gt;
    Queue&amp;lt;condition&amp;gt; stopped;&lt;br /&gt;
    int curr_value;&lt;br /&gt;
    Monitor {&lt;br /&gt;
        stopped = Queue&amp;lt;condition&amp;gt;();&lt;br /&gt;
        curr_value = 0;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    int delay(int value) {&lt;br /&gt;
        curr_value = value;&lt;br /&gt;
        if (stopped.size() == NDELAY) {&lt;br /&gt;
            condition first = stopped.dequeue();&lt;br /&gt;
            first.signal();&lt;br /&gt;
        }&lt;br /&gt;
        condition c = new condition();&lt;br /&gt;
        stopped.enqueue(c);&lt;br /&gt;
        c.wait();    &lt;br /&gt;
&lt;br /&gt;
        return curr_value;&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 c2 ==&lt;br /&gt;
&lt;br /&gt;
=== Consegna ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Esercizio c.2: Implementare usando semafori ordinari (fair, fifo) un servizio di semafori a priorità lifo che&lt;br /&gt;
fornisca le seguenti primitive:&lt;br /&gt;
 void PLP(int prio);&lt;br /&gt;
 void PLV()&lt;br /&gt;
PLP e PLV si devono comportare rispettivamente come P e V. Quando la PLV deve riattivare un processo&lt;br /&gt;
sceglie fra quelli in attesa quello a priorità massima, nel caso siano presenti più processi a priorità massima&lt;br /&gt;
sceglie quello in attesa da meno tempo. &lt;br /&gt;
&lt;br /&gt;
=== Soluzione proposta 1 ===&lt;br /&gt;
&lt;br /&gt;
Esercizio c2 (da controllare) da Flecart.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Stack&amp;lt;semaphore&amp;gt; stack[MAX_PRIORITY];&lt;br /&gt;
int num_V = 0;&lt;br /&gt;
semaphore mutex(1);&lt;br /&gt;
&lt;br /&gt;
void  PLP(int prio) {&lt;br /&gt;
    mutex.P();&lt;br /&gt;
    if (num_V &amp;gt; 0) {&lt;br /&gt;
        num_V--;&lt;br /&gt;
        mutex.V();&lt;br /&gt;
        return;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    semaphore sem = semaphore(0);&lt;br /&gt;
    stack[prio].push(sem);&lt;br /&gt;
    mutex.V();&lt;br /&gt;
    sem.P();&lt;br /&gt;
&lt;br /&gt;
    mutex.V();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void PLV() {&lt;br /&gt;
    mutex.P();&lt;br /&gt;
    &lt;br /&gt;
    for (int i = MAX_PRIORITY - 1; i &amp;gt;= 0; i--) {&lt;br /&gt;
        if (stack[i].size() &amp;gt; 0) {&lt;br /&gt;
            sem = stack[i].pop();&lt;br /&gt;
            sem.V();&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    num_V++;&lt;br /&gt;
&lt;br /&gt;
    mutex.V();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Prova 2021/05/26 =&lt;br /&gt;
&lt;br /&gt;
== Consegna c1 == &lt;br /&gt;
&lt;br /&gt;
Esercizio c.1: Un buffer sincrono strampalato (bss) ha due procedure entry:&lt;br /&gt;
void put(T value)&lt;br /&gt;
list of T get(void)&lt;br /&gt;
La entry put viene utilizzata per aggiungere un elemento e la entry get per leggere tutti quelli disponibili.&lt;br /&gt;
Se più processi chiamano la put quando nessun processo è in attesa per una get, rimangono tutti bloccati.&lt;br /&gt;
Quando successivamente un processo chiama la get riceve la lista di tutti gli elementi inseriti con le put e&lt;br /&gt;
tutti i processi vengono sbloccati.&lt;br /&gt;
Se il buffer è vuoto tutti i processi che chiamano la get rimangono bloccati. quando un processo chiama&lt;br /&gt;
successivamente la put tutti i processi in attesa per la get si sbloccano e ricevono lo stesso valore di ritorno:&lt;br /&gt;
una lista contenente il solo valore passato come parametro alla put. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Soluzione proposta 1 ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
int num = 0; // se è positiva rappresenta numero di gets che aspettano, se negativa, numero di puts&lt;br /&gt;
semaphore semput(0);&lt;br /&gt;
semaphore semget(0);&lt;br /&gt;
semaphore mutex(1);&lt;br /&gt;
list&amp;lt;T&amp;gt; global_list;&lt;br /&gt;
&lt;br /&gt;
void put(T value) {&lt;br /&gt;
    //&amp;lt; await(num &amp;gt; 0) --&amp;gt; global_list.add(value) &amp;gt;&lt;br /&gt;
    mutex.P();&lt;br /&gt;
    if (num &amp;lt;= 0) {&lt;br /&gt;
        num--;&lt;br /&gt;
        mutex.V();&lt;br /&gt;
        semput.P();&lt;br /&gt;
        num++;&lt;br /&gt;
    }&lt;br /&gt;
    global_list.add(value);&lt;br /&gt;
&lt;br /&gt;
    if (num &amp;lt; 0)&lt;br /&gt;
        semput.V();&lt;br /&gt;
    else &lt;br /&gt;
        semget.V();&lt;br /&gt;
&lt;br /&gt;
    return;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
list of T get() {&lt;br /&gt;
    list&amp;lt;T&amp;gt; local_list;&lt;br /&gt;
&lt;br /&gt;
    mutex.P();&lt;br /&gt;
    if (num &amp;gt;= 0) {&lt;br /&gt;
        num++;&lt;br /&gt;
        mutex.V();&lt;br /&gt;
        semget.P();&lt;br /&gt;
        num--;&lt;br /&gt;
    } else {&lt;br /&gt;
        semput.V();&lt;br /&gt;
        semget.P();&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    local_list = global_list; // fa deep copy&lt;br /&gt;
&lt;br /&gt;
    if (num &amp;gt; 0) {&lt;br /&gt;
        semget.V();&lt;br /&gt;
    } else {&lt;br /&gt;
        global_list = list&amp;lt;T&amp;gt;();&lt;br /&gt;
        mutex.V(); &lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    return local_list;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
class bss{&lt;br /&gt;
  int waiting_put=0;&lt;br /&gt;
  int waiting_get=0;&lt;br /&gt;
  cond cw,cg;&lt;br /&gt;
  queue&amp;lt;T&amp;gt; q;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
  void put(T value){&lt;br /&gt;
    q.push(T);&lt;br /&gt;
    if(waiting_get&amp;gt;0){&lt;br /&gt;
      cg.signal()&lt;br /&gt;
    }else{&lt;br /&gt;
      waiting_put++;&lt;br /&gt;
      cw.wait();&lt;br /&gt;
      waiting_put--;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  list&amp;lt;T&amp;gt; get(){&lt;br /&gt;
    if(waiting_put&amp;gt;0){&lt;br /&gt;
      while(waiting_put&amp;gt;0){&lt;br /&gt;
        cw.signal();&lt;br /&gt;
      }&lt;br /&gt;
    }else{&lt;br /&gt;
      waiting_get++;&lt;br /&gt;
      cg.wait();&lt;br /&gt;
      waiting_get--;&lt;br /&gt;
    }&lt;br /&gt;
    list&amp;lt;T&amp;gt; p= q.tolist();&lt;br /&gt;
    if(waiting_get&amp;gt;0){&lt;br /&gt;
      cg.signal();&lt;br /&gt;
    }&lt;br /&gt;
    q.removeAll();&lt;br /&gt;
    return p;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Gio</name></author>
	</entry>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=Prove_scritte_2021&amp;diff=2842</id>
		<title>Prove scritte 2021</title>
		<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php?title=Prove_scritte_2021&amp;diff=2842"/>
		<updated>2023-01-13T10:38:32Z</updated>

		<summary type="html">&lt;p&gt;Gio: /* 1. Soluzione proposta */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
= Prova 2021/09/15 =&lt;br /&gt;
&lt;br /&gt;
== Esercizio C1 == &lt;br /&gt;
&lt;br /&gt;
=== Consegna === &lt;br /&gt;
Esercizio c.1: Scrivere il monitor alrv (at least rendez-vous) che fornisce una sola procedure entry:&lt;br /&gt;
procedure entry void at_least(int n)&lt;br /&gt;
Quando un processo chiama la funzione at_least vuol dire che vuole sincronizzarsi con un insieme di almeno n&lt;br /&gt;
processi (incluso il chiamante).&lt;br /&gt;
Esempi:&lt;br /&gt;
Se un processo chiama at_least(1) non si blocca.&lt;br /&gt;
Se il processo p chiama at_least(2) si blocca, se poi il processo q chiama at_least(2) oppure at_least(1) si&lt;br /&gt;
sbloccano sia p sia q (la richiesta di p è soddisfatta, ne aspettava almeno 2, p e q)&lt;br /&gt;
Se il processo p chiama at_least(2) si blocca, se poi il processo q chiama at_least(3) si blocca anch'esso perché&lt;br /&gt;
sebbene la richiesta di p possa essere soddisfatta, q non può ancora sbloccarsi: ci sono solo 2 processi in attesa mentre&lt;br /&gt;
q ne vuole 3. Un terzo processo che chiami at_least(x) con x=1,2,3 li sblocca tutti.&lt;br /&gt;
Hint: sia w[k ] il numero dei processi in attesa di essere in almeno k (quelli che hanno chiamato at_least(k) e non&lt;br /&gt;
hanno completato l'esecuzione della funzione). Sia s[n]=∑&lt;br /&gt;
k=1&lt;br /&gt;
n&lt;br /&gt;
w[k ] (rappresenta il numero di processi soddisfacibili:&lt;br /&gt;
e.g. se ci sono 4 processi in attesa, potrebbero essere soddisfatte le richieste dei processi che ne aspettano almeno 2,&lt;br /&gt;
almeno 3 o almeno 4). Preso, se esiste, il massimo indice m tale che s[m]≥m tutti i processi in attesa di essere in n,&lt;br /&gt;
per n≤m possono essere sbloccati.&lt;br /&gt;
&lt;br /&gt;
=== 1. Soluzione proposta ===&lt;br /&gt;
Soluzione proposta da [https://so.v2.cs.unibo.it/wiki/index.php/User:Flecart Flecart]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
extern int MAX;  // il massimo numero di attesa&lt;br /&gt;
monitor alrv {&lt;br /&gt;
	int w[MAX];&lt;br /&gt;
	int s[MAX];&lt;br /&gt;
	condition c[MAX];&lt;br /&gt;
&lt;br /&gt;
	init() {&lt;br /&gt;
		for (int i = 0; i &amp;lt; MAX; i++) {&lt;br /&gt;
			w[i] = s[i] = 0;&lt;br /&gt;
		}&lt;br /&gt;
	}	&lt;br /&gt;
&lt;br /&gt;
procedure entry void at_least(int n) {&lt;br /&gt;
	if (n &amp;gt;= MAX || n &amp;lt;= 0) raise error;&lt;br /&gt;
	&lt;br /&gt;
	int i;&lt;br /&gt;
	for (i = n; i &amp;lt; MAX; i++) s[i]++;&lt;br /&gt;
	&lt;br /&gt;
	for (i = MAX - 1; i &amp;gt; 0; i--) {&lt;br /&gt;
		if (s[i] &amp;gt;= i) break;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	if (i &amp;gt; 0) {&lt;br /&gt;
		for (int j = 0; j &amp;lt;= i; j++) {&lt;br /&gt;
			while (w[j] &amp;gt; 0) {&lt;br /&gt;
				c[j].signal();&lt;br /&gt;
				w[j]--;&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
		&lt;br /&gt;
		s[0] = 0;&lt;br /&gt;
		for (int i = 1; i &amp;lt; MAX; i++) {&lt;br /&gt;
			s[i] = w[i] + s[i - 1];&lt;br /&gt;
		}&lt;br /&gt;
	} else {&lt;br /&gt;
		w[n]++;&lt;br /&gt;
		c[n].wait();&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Soluzione proposta da [https://so.v2.cs.unibo.it/wiki/index.php/User:Flecart Flecart frend],regalo a flecart la proprietà intellettuale di questa soluzione&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
class Monitor{&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
  min_heap&amp;lt;(int,cond)&amp;gt; h;&lt;br /&gt;
&lt;br /&gt;
  void at_least(int n){&lt;br /&gt;
    int sum=0;&lt;br /&gt;
    int max_to_sblock= -INF;&lt;br /&gt;
    cond c = new cond(n);&lt;br /&gt;
    h.push((n,c));&lt;br /&gt;
    // la heap viene visitata in maniera crescente&lt;br /&gt;
    for(auto f=h.begin_iter();null!=f.next();f++) {&lt;br /&gt;
        sum++;&lt;br /&gt;
        if(f.0&amp;lt;=sum){&lt;br /&gt;
          max_to_sblock =f.0;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    for(auto f=h.begin_iter();null!=f.next();f++) {&lt;br /&gt;
        if(f.0&amp;lt;=max_to_sblock){&lt;br /&gt;
          f.1.signal();&lt;br /&gt;
          h.remove(c);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    if(n&amp;gt;max_to_sblock){&lt;br /&gt;
      c.wait();&lt;br /&gt;
    }&lt;br /&gt;
    free(c)&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Prova 2021/06/23 =&lt;br /&gt;
&lt;br /&gt;
== Esercizio C1 == &lt;br /&gt;
&lt;br /&gt;
=== Consegna === &lt;br /&gt;
Esercizio c.1: Scrivere il monitor delayvalue con una sola procedure entry:&lt;br /&gt;
  int delay(int value);&lt;br /&gt;
Il monitor deve sospendere i primi NDELAY processi che chiamano la delay. Le successive chiamate di delay&lt;br /&gt;
devono mantenere costante il numero di processi sospesi, ogni successiva chiamata devo riattivare il primo&lt;br /&gt;
processo in attesa prima di sospendersi, la delay ritorna il valore passato come parametro dal processo che&lt;br /&gt;
ne ha riattivato l'esecuzione. e.g. se NDELAY è 2:&lt;br /&gt;
  P1: delay(44) -&amp;gt; P1 si sospende&lt;br /&gt;
  P2: delay(40) -&amp;gt; P2 si sospende&lt;br /&gt;
  P3: delay(42) -&amp;gt; P1 si riattiva e ritorna 42, P3 si sospende&lt;br /&gt;
  P4: delay(22) -&amp;gt; P2 si riattiva e ritorna 22, P4 si sospende&lt;br /&gt;
&lt;br /&gt;
=== Soluzione proposta 1 ===&lt;br /&gt;
Soluzione proposta da [https://so.v2.cs.unibo.it/wiki/index.php/User:Flecart Flecart], da controllare&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// variabile definita altrove.&lt;br /&gt;
extern int NDELAY;&lt;br /&gt;
&lt;br /&gt;
class Monitor {&lt;br /&gt;
    Queue&amp;lt;condition&amp;gt; stopped;&lt;br /&gt;
    int curr_value;&lt;br /&gt;
    Monitor {&lt;br /&gt;
        stopped = Queue&amp;lt;condition&amp;gt;();&lt;br /&gt;
        curr_value = 0;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    int delay(int value) {&lt;br /&gt;
        curr_value = value;&lt;br /&gt;
        if (stopped.size() == NDELAY) {&lt;br /&gt;
            condition first = stopped.dequeue();&lt;br /&gt;
            first.signal();&lt;br /&gt;
        }&lt;br /&gt;
        condition c = new condition();&lt;br /&gt;
        stopped.enqueue(c);&lt;br /&gt;
        c.wait();    &lt;br /&gt;
&lt;br /&gt;
        return curr_value;&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 c2 ==&lt;br /&gt;
&lt;br /&gt;
=== Consegna ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Esercizio c.2: Implementare usando semafori ordinari (fair, fifo) un servizio di semafori a priorità lifo che&lt;br /&gt;
fornisca le seguenti primitive:&lt;br /&gt;
 void PLP(int prio);&lt;br /&gt;
 void PLV()&lt;br /&gt;
PLP e PLV si devono comportare rispettivamente come P e V. Quando la PLV deve riattivare un processo&lt;br /&gt;
sceglie fra quelli in attesa quello a priorità massima, nel caso siano presenti più processi a priorità massima&lt;br /&gt;
sceglie quello in attesa da meno tempo. &lt;br /&gt;
&lt;br /&gt;
=== Soluzione proposta 1 ===&lt;br /&gt;
&lt;br /&gt;
Esercizio c2 (da controllare) da Flecart.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Stack&amp;lt;semaphore&amp;gt; stack[MAX_PRIORITY];&lt;br /&gt;
int num_V = 0;&lt;br /&gt;
semaphore mutex(1);&lt;br /&gt;
&lt;br /&gt;
void  PLP(int prio) {&lt;br /&gt;
    mutex.P();&lt;br /&gt;
    if (num_V &amp;gt; 0) {&lt;br /&gt;
        num_V--;&lt;br /&gt;
        mutex.V();&lt;br /&gt;
        return;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    semaphore sem = semaphore(0);&lt;br /&gt;
    stack[prio].push(sem);&lt;br /&gt;
    mutex.V();&lt;br /&gt;
    sem.P();&lt;br /&gt;
&lt;br /&gt;
    mutex.V();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void PLV() {&lt;br /&gt;
    mutex.P();&lt;br /&gt;
    &lt;br /&gt;
    for (int i = MAX_PRIORITY - 1; i &amp;gt;= 0; i--) {&lt;br /&gt;
        if (stack[i].size() &amp;gt; 0) {&lt;br /&gt;
            sem = stack[i].pop();&lt;br /&gt;
            sem.V();&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    num_V++;&lt;br /&gt;
&lt;br /&gt;
    mutex.V();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Gio</name></author>
	</entry>
</feed>