<?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=GabrieleCalarota</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=GabrieleCalarota"/>
	<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php/Special:Contributions/GabrieleCalarota"/>
	<updated>2026-05-03T03:46:17Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.35.5</generator>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=Prova_teorica_2014.06.03&amp;diff=1950</id>
		<title>Prova teorica 2014.06.03</title>
		<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php?title=Prova_teorica_2014.06.03&amp;diff=1950"/>
		<updated>2017-06-27T14:45:12Z</updated>

		<summary type="html">&lt;p&gt;GabrieleCalarota: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Testo: [http://www.cs.unibo.it/~renzo/so/compiti/2014.06.03.tot.pdf]&lt;br /&gt;
&lt;br /&gt;
== Esercizio c.1 ==&lt;br /&gt;
=== Soluzione di G.C. ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang =&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
int wait_enter[N][2] = {0,0,0,0,0,0,0,0,0,...,0}&lt;br /&gt;
int wait_exit[N] = {0,0,0, ... , 0}&lt;br /&gt;
&lt;br /&gt;
int n = 0;&lt;br /&gt;
&lt;br /&gt;
monitor sabelev{&lt;br /&gt;
	&lt;br /&gt;
	int current_floor = NULL;&lt;br /&gt;
	int current_dir = NULL;&lt;br /&gt;
	condition ok2enter[N][2], ok2exit[N];&lt;br /&gt;
	procedure entry atfloor(floor, dir){&lt;br /&gt;
		current_floor = floor;&lt;br /&gt;
		current_dir = dir;&lt;br /&gt;
		if (wait_enter[floor][dir]&amp;gt;0){&lt;br /&gt;
			ok2enter[floor][dir].signal();&lt;br /&gt;
		}&lt;br /&gt;
		if (wait_exit[floor]&amp;gt;0){&lt;br /&gt;
			ok2exit[floor].signal();&lt;br /&gt;
		}&lt;br /&gt;
		//elevator is moving from floor to floor+1 (or -1)&lt;br /&gt;
		current_floor = NULL;&lt;br /&gt;
	}&lt;br /&gt;
	procedure entry enter(from, to){&lt;br /&gt;
		int dir = from&amp;gt;to ? down : up;&lt;br /&gt;
		if (current_floor != from) || (current_dir != dir){&lt;br /&gt;
			wait_enter[from][dir]++;&lt;br /&gt;
			ok2enter[from][dir].wait();&lt;br /&gt;
			wait_enter[from][dir]--;&lt;br /&gt;
		}&lt;br /&gt;
		//process enter in the elevator&lt;br /&gt;
		n++;&lt;br /&gt;
		//wakes up the processes that are in this floor and going in its direction&lt;br /&gt;
		if (wait_enter[from][dir]&amp;gt;0){&lt;br /&gt;
			ok2enter[from][dir].signal();&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
	procedure entry exit(from,to){&lt;br /&gt;
		if (current_floor != to){&lt;br /&gt;
			wait_exit[to]++;&lt;br /&gt;
			ok2exit[to].wait();&lt;br /&gt;
			wait_exit[to]--;&lt;br /&gt;
		}&lt;br /&gt;
		//exit from the elevator&lt;br /&gt;
		n--;&lt;br /&gt;
		//wakes up the processes that have to exit on this floor&lt;br /&gt;
		if (wait_exit[to]&amp;gt;0){&lt;br /&gt;
			ok2exit[to].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;
== Esercizio c.2 ==&lt;br /&gt;
&lt;br /&gt;
Siano dati 4 processi:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Python&amp;quot;&amp;gt;&lt;br /&gt;
prchar=”IATL”&lt;br /&gt;
Process i: i=range(4)&lt;br /&gt;
while True:&lt;br /&gt;
 sync(i)&lt;br /&gt;
 print(prchar[i])&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Scrivere la funzione sync in modo che in un sistema di processi a memoria privata, usando message passing asincrono, l'unico&lt;br /&gt;
output possibile sia la stringa di lunghezza infinita: “ITALIAITALIAITALIA....”&lt;br /&gt;
&lt;br /&gt;
===Soluzione di S.G===&lt;br /&gt;
&lt;br /&gt;
Solo il processo 2 (lettera T) permette di iniziare la sincronizzazione dei processi.&lt;br /&gt;
&lt;br /&gt;
Oltre al processo 2 anche il processo 1 (lettera A) permette di riavviare la sequenza.&lt;br /&gt;
&lt;br /&gt;
''Nella descrizione di seguito chiameremo T il processo incaricato a stampare tale lettera, e cosi anche per gli altri.''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Python&amp;quot;&amp;gt;&lt;br /&gt;
def sync(i):&lt;br /&gt;
	if i == 0:			# Processo 0 (processo I)&lt;br /&gt;
		mittente = recv(*)			# Aspetto un messaggio da T, L o A&lt;br /&gt;
		if mittente == 2 or mittente == 1:	# Se il mittente è il processo T o A (avvio o riavvio sequenza)&lt;br /&gt;
			send(2, 0)			# Invio un messaggio al processo T&lt;br /&gt;
		&lt;br /&gt;
		elif mittente == 3:	# Se il mittente è il processo L&lt;br /&gt;
			send(1, 0)	# Invio un messaggio al processo A&lt;br /&gt;
	&lt;br /&gt;
	elif i == 1:		# Processo 1 (processo A)&lt;br /&gt;
		mittente = recv(*)	# Aspetto un messaggio dal processo T o I&lt;br /&gt;
		if mittente == 0:	# Se il mittente è il processo I&lt;br /&gt;
			send(0, 1)	# Invio un messaggio al processo I (riavvio la sequenza)&lt;br /&gt;
		elif mittente == 2:	# Se il mittente è il processo T&lt;br /&gt;
			send(3, 1)	# Invio un messaggio al processo L&lt;br /&gt;
	&lt;br /&gt;
	elif i == 2:		# Processo 2 (processo T)&lt;br /&gt;
		send (0, 2)		# Invio un messaggio al processo I (Avvia la sequenza)&lt;br /&gt;
		mittente = recv(0)	# Aspetto un messaggio dal processo I&lt;br /&gt;
		if mittente == 0:	# Se il mittente è il processo I&lt;br /&gt;
			send(1, 2)	# Invio un messaggio al processo A&lt;br /&gt;
	&lt;br /&gt;
	elif i == 3:		# Processo 3 (processo L)&lt;br /&gt;
		mittente = recv(1)	# Aspetto un messaggio dal processo A&lt;br /&gt;
		if mittente == 1:	# Se il mittente è il processo A&lt;br /&gt;
			send(0, 3)	# Invio un messaggio al processo I&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Una volta avviato T invierà un messaggio a I e si bloccherà in attesa di I.&lt;br /&gt;
&lt;br /&gt;
Il processo I in attesa riceverà un messaggio da T, allora sbloccherà T e stamperà I.&lt;br /&gt;
&lt;br /&gt;
A questo punto il processo T invierà un messaggio ad A, e stamperà T.&lt;br /&gt;
&lt;br /&gt;
A aspetterà messaggi da più mittenti, in questo caso riceverà un messaggio da T, invierà un messaggio ad L e stamperà A.&lt;br /&gt;
&lt;br /&gt;
L aspetterà il messaggio da A che appena ricevuto invierà un messaggio ad I, e stamperà L.&lt;br /&gt;
&lt;br /&gt;
Il processo I in attesa, riceverà un messaggio da L sbloccandosi invierà un messaggio ad A e stamperà I.&lt;br /&gt;
&lt;br /&gt;
A ancora una volta in attesa, riceverà un messaggio da I, risponderà ad I e stamperà A.&lt;br /&gt;
&lt;br /&gt;
I riceverà un messaggio da A, e riavvierà la sequenza.&lt;br /&gt;
[[User:S.G|S.G]] ([[User talk:S.G|talk]]) 10:35, 4 December 2016 (CET)&lt;br /&gt;
&lt;br /&gt;
===Soluzione di FedericoB===&lt;br /&gt;
Penso che la soluzione di S.G. sia sbagliata in quanto appena si fa una send un processo bloccato su una receive viene sbloccato. Quindi per esempio verrà stampato T prima di I. L'idea è di sbloccare T alla seconda chiamata di sync(0). Per sapere il numero della chiamata si può utilizzare un contatore statico, che mantiene il suo valore tra le chiamate di funzione e viene inizializzata a 0.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
sync(i)&lt;br /&gt;
	if i==0: #processo &amp;quot;I&amp;quot;&lt;br /&gt;
		if (count=1):&lt;br /&gt;
			send(2)&lt;br /&gt;
			recv(3)&lt;br /&gt;
		elif: (count=2)&lt;br /&gt;
			send(1)&lt;br /&gt;
			recv(1)&lt;br /&gt;
			count = 0&lt;br /&gt;
	elif i==1: #processo &amp;quot;A&amp;quot;&lt;br /&gt;
		if (count==0)&lt;br /&gt;
			recv(2)&lt;br /&gt;
		elif (count=1):&lt;br /&gt;
			send(3)&lt;br /&gt;
			recv(0)&lt;br /&gt;
		elif: (count=2)&lt;br /&gt;
			send(0)&lt;br /&gt;
			recv(2)&lt;br /&gt;
			count=0&lt;br /&gt;
	elif i==2: #processo &amp;quot;T&amp;quot;&lt;br /&gt;
		if (count==0)&lt;br /&gt;
			recv(0)&lt;br /&gt;
		elif (count=1):&lt;br /&gt;
			send(1)&lt;br /&gt;
			recv(0)&lt;br /&gt;
			count=0&lt;br /&gt;
	elif i==3: #processo &amp;quot;L&amp;quot;&lt;br /&gt;
		if (count==0)&lt;br /&gt;
			recv(1)&lt;br /&gt;
		elif (count=1):&lt;br /&gt;
			send(0)&lt;br /&gt;
			recv(1)&lt;br /&gt;
			count=0&lt;br /&gt;
	count++&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Sequenzialemente le chiamate sono in quest'ordine&lt;br /&gt;
&amp;lt;source lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
sync(0) non fa nulla&lt;br /&gt;
print(I)&lt;br /&gt;
sync(0) count=1 manda messaggio a T e si bloccherà in attesa di un messaggio da L&lt;br /&gt;
sync(2) count=0 aspetta messaggio da I&lt;br /&gt;
print(T)&lt;br /&gt;
sync(2) count = 1 manda messaggio a A e setto count=0&lt;br /&gt;
sync(1) count = 0 aspetta messaggio da T&lt;br /&gt;
print(A)&lt;br /&gt;
sync(1) count = 1 manda messaggio a L e aspetto un messaggio da I&lt;br /&gt;
sync(3) count=0 aspetta messaggio da A&lt;br /&gt;
print(L)&lt;br /&gt;
sync(3) count = 1 manda messaggio a I e setto count=0&lt;br /&gt;
print(I) #si sblocca per il messaggio da L&lt;br /&gt;
sync(0) count=2 mando un messaggio ad A e mi blocco in attesa di un messaggio da A quando lo ricevo metto count=0&lt;br /&gt;
print(A)&lt;br /&gt;
sync(1) count=2 mando messaggio a I e aspetto messaggio da T e quando mi arriverà imposto count=0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Ma in realtà è tutto in parallelo quindi:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Processo &amp;quot;I&amp;quot; !! Processo &amp;quot;A&amp;quot; !! Processo &amp;quot;T&amp;quot; !! Processo &amp;quot;L&amp;quot;&lt;br /&gt;
|- &lt;br /&gt;
|sync(0) non fa nulla &amp;lt;br&amp;gt; print(I) &amp;lt;br&amp;gt; sync(0) count=1 manda messaggio a T e si bloccherà in attesa di un messaggio da L &amp;lt;br&amp;gt; print(I) #si sblocca per il messaggio da L &amp;lt;br&amp;gt; sync(0) count=2 mando un messaggio ad A e mi blocco in attesa di un messaggio da A quando lo ricevo metto count=0&lt;br /&gt;
| sync(1) count = 0 aspetta messaggio da T &amp;lt;br&amp;gt; print(A) &amp;lt;br&amp;gt; sync(1) count = 1 manda messaggio a L e aspetto un messaggio da I &amp;lt;br&amp;gt; print(A) &amp;lt;br&amp;gt; sync(1) count=2 mando messaggio a I e aspetto messaggio da T e quando mi arriverà imposto count=0 &lt;br /&gt;
|sync(2) count=0 aspetta messaggio da I &amp;lt;br&amp;gt; print(T) &amp;lt;br&amp;gt; sync(2) count = 1 manda messaggio a A e setto count=0&lt;br /&gt;
|sync(3) count=0 aspetta messaggio da A &amp;lt;br&amp;gt; print(L) &amp;lt;br&amp;gt; sync(3) count = 1 manda messaggio a I e setto count=0&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>GabrieleCalarota</name></author>
	</entry>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=Prova_teorica_2015.02.14&amp;diff=1946</id>
		<title>Prova teorica 2015.02.14</title>
		<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php?title=Prova_teorica_2015.02.14&amp;diff=1946"/>
		<updated>2017-06-22T12:35:01Z</updated>

		<summary type="html">&lt;p&gt;GabrieleCalarota: /* Soluzione di Silas */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Testo: [http://www.cs.unibo.it/~renzo/so/compiti/2015.02.14.tot.pdf]&lt;br /&gt;
&lt;br /&gt;
== Esercizio c.1 ==&lt;br /&gt;
===Soluzione di Silas===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
#define MAX &lt;br /&gt;
&lt;br /&gt;
monitor altcolbb{&lt;br /&gt;
	queue buff;&lt;br /&gt;
	color_t last_color; //0: red, 1:blue, -1:&amp;quot;superstate&amp;quot;, means that both red and blue are accepted&lt;br /&gt;
	int wait_red, wait_blue;&lt;br /&gt;
	condition ok2read, redok, blueok;&lt;br /&gt;
&lt;br /&gt;
	void altcolbb(void){&lt;br /&gt;
		buff = new queue();&lt;br /&gt;
		last_color = -1;&lt;br /&gt;
		wait_red = wait_blue = 0;&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	procedure entry void write(color_t color, generic_type val){&lt;br /&gt;
		if(last_color == color || buff.length() == MAX){ //we can't enqueue if the colors are the same or if the buffer is full&lt;br /&gt;
			if(color == 0){ //enqueue to &amp;quot;reds&amp;quot;&lt;br /&gt;
				wait_red++;&lt;br /&gt;
				redok.wait();&lt;br /&gt;
				wait_red--;&lt;br /&gt;
			}else{ //enqueue to &amp;quot;blues&amp;quot;&lt;br /&gt;
				wait_blue++;&lt;br /&gt;
				blueok.wait();&lt;br /&gt;
				wait_blue--;&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
		buff.enqueue(val); //append val and update last_color&lt;br /&gt;
		last_color = color;&lt;br /&gt;
		ok2read.signal();&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	procedure entry generic_type read(void){&lt;br /&gt;
		if(buff.length() == 0)&lt;br /&gt;
			ok2read.wait();&lt;br /&gt;
		generic_type ret = buff.dequeue();&lt;br /&gt;
		if(buff.length() == 0)&lt;br /&gt;
			last_color = -1; //if buff is empty both colors can now be added&lt;br /&gt;
		switch(last_color){&lt;br /&gt;
			case -1: {&lt;br /&gt;
					if(wait_red&amp;gt;wait_blue) //if there are more &amp;quot;reds&amp;quot; waiting to write we signal them&lt;br /&gt;
						redok.signal();&lt;br /&gt;
					else&lt;br /&gt;
						blueok.signal(); //otherwise we signal &amp;quot;blues&amp;quot;&lt;br /&gt;
					break;&lt;br /&gt;
			}&lt;br /&gt;
			case 0: {&lt;br /&gt;
					blueok.signal();&lt;br /&gt;
					break;&lt;br /&gt;
			}&lt;br /&gt;
			case 1: {&lt;br /&gt;
					redok.signal();&lt;br /&gt;
					break;&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;
===Soluzione di MarcoNegrini===&lt;br /&gt;
I corrected Silas's version&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define MAX &lt;br /&gt;
 &lt;br /&gt;
monitor altcolbb{&lt;br /&gt;
	queue buff;&lt;br /&gt;
	color_t last_color; //0: red, 1:blue, -1:&amp;quot;superstate&amp;quot;, means that both red and blue are accepted&lt;br /&gt;
	condition ok2read, ok2write, redok, blueok;&lt;br /&gt;
&lt;br /&gt;
	void altcolbb(void){&lt;br /&gt;
		buff = new queue();&lt;br /&gt;
		last_color = -1;&lt;br /&gt;
	}&lt;br /&gt;
 &lt;br /&gt;
	procedure entry void write(color_t color, generic_type val){&lt;br /&gt;
		if(buff.length() == MAX){ //here waits if buff is full&lt;br /&gt;
			ok2write.wait();&lt;br /&gt;
		if(last_color==-1){ //if buff was empty it can just enqueue and exit&lt;br /&gt;
			buff.enqueue(val);&lt;br /&gt;
			last_color = color;&lt;br /&gt;
		}&lt;br /&gt;
		else{	&lt;br /&gt;
			if(color == 0){ //red section&lt;br /&gt;
				if (last_color == 0) //if last was red it needs to wait&lt;br /&gt;
					redok.wait();&lt;br /&gt;
				buff.enqueue(val); &lt;br /&gt;
				last_color = color; // it must set last color before signaling other writers&lt;br /&gt;
				blueok.signal(); //blue can now enqueue his value&lt;br /&gt;
			}else{ //blue section, same as above&lt;br /&gt;
				if (last_color == 1)&lt;br /&gt;
					blueok.wait();&lt;br /&gt;
				buff.enqueue(val);&lt;br /&gt;
				last_color = color;&lt;br /&gt;
				redok.signal();&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
		ok2read.signal(); // reader can now read&lt;br /&gt;
	}&lt;br /&gt;
 &lt;br /&gt;
	procedure entry generic_type read(void){&lt;br /&gt;
		//here waits if needed, then dequeue&lt;br /&gt;
		if(buff.length() == 0) &lt;br /&gt;
			ok2read.wait();&lt;br /&gt;
		generic_type ret = buff.dequeue();&lt;br /&gt;
&lt;br /&gt;
		//here signal the one that has been waiting for more time&lt;br /&gt;
		// it MUST be of the last_color color&lt;br /&gt;
		if(buff.length() == 0){&lt;br /&gt;
			color_t tmp=last_color;&lt;br /&gt;
			last_color = -1; &lt;br /&gt;
			// last color MUST be set to -1 here because &lt;br /&gt;
			// if there were writers waiting on ok2write.wait() (full buffer case)&lt;br /&gt;
			// they woundn't be signaled here, this happens if MAX=1&lt;br /&gt;
			&lt;br /&gt;
			if (tmp == 1) //&lt;br /&gt;
				blueok.signal();&lt;br /&gt;
			else&lt;br /&gt;
				redok.signal();&lt;br /&gt;
		}&lt;br /&gt;
		ok2write.signal();&lt;br /&gt;
	}&lt;br /&gt;
 &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
===Soluzione di FedericoB===&lt;br /&gt;
relating to Silas and Marco solution. A bounded buffer is a queue, so i think is wrong to use last_color as head element color when it's used as tail element color. &lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
#define MAX&lt;br /&gt;
&lt;br /&gt;
monitor altcobb {&lt;br /&gt;
	deque buffer&lt;br /&gt;
	condition waitRed, waitBlue, ok2read, ok2write&lt;br /&gt;
	altcobb() {&lt;br /&gt;
		buffer = new Deque()&lt;br /&gt;
		&lt;br /&gt;
	}&lt;br /&gt;
	procedure entry void write(colot_t color,generic_type val) {&lt;br /&gt;
		if (deque.getSize()==MAX) ok2write.wait()&lt;br /&gt;
		if (buffer.getSize==0) queue.addLast((val,color))&lt;br /&gt;
		else &lt;br /&gt;
			if (color==RED)&lt;br /&gt;
				if (buffer.getLast().color==BLUE)&lt;br /&gt;
					queue.addLast((val,color))&lt;br /&gt;
					waitRed.signal()&lt;br /&gt;
				else &lt;br /&gt;
					waitBlue.wait()&lt;br /&gt;
					queue.addLast((val,color))&lt;br /&gt;
			else&lt;br /&gt;
				if (buffer.getLast().color==RED)&lt;br /&gt;
					queue.addLast((val,color))&lt;br /&gt;
					waitBlue.signal()&lt;br /&gt;
				else &lt;br /&gt;
					waitRed.wait()&lt;br /&gt;
					queue.addLast((val,color))&lt;br /&gt;
		ok2read.signal()&lt;br /&gt;
	}&lt;br /&gt;
	procedure entry generic_type read() {&lt;br /&gt;
		if (deque.isEmpty()) ok2read.wait()&lt;br /&gt;
		element = deque.dequeueFirst();&lt;br /&gt;
		ok2write.signal()&lt;br /&gt;
		return element;&lt;br /&gt;
                #needed explanation: after the ok2write.signal() the current process will be put in wait state in the urgent stack, &lt;br /&gt;
                #but after the woke up process has exited the monitor this process will be woke up and it will return the element.&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Esercizio c.2 ==&lt;br /&gt;
===Soluzione di Silas===&lt;br /&gt;
I semafori garantiscono che A e B vengano eseguiti in maniera sequenziale e che accedano in maniera mutualmente esclusiva ad n, quindi l'unica variazione possibile è il thread di inizio per la sequenza. &amp;lt;br&amp;gt;&lt;br /&gt;
Nel caso sia A ad accedere per primo alla CS si ha: n = ((1*2)+2)*3 = 12 &amp;lt;br&amp;gt;&lt;br /&gt;
Nel caso sia invece B ad accedere per primo alla C si ha: n = (((0*2)+1)*3)+2 = 5 &amp;lt;br&amp;gt;&lt;br /&gt;
Quindi n = 12 e n = 5 sono i due possibili valori. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Anche secondo me è così --[[User:FedericoB|FedericoB]] ([[User talk:FedericoB|talk]]) 20:58, 13 June 2017 (CEST)&lt;br /&gt;
&lt;br /&gt;
In realtà i possibili valori sono: 12 5 9 e 8. In quanto è vero che possono solo alternarsi i due thread. ma i semafori partono da 1. pertanto al &amp;quot;secondo giro può partire chiunque dei due, in quanto avrà il suo semaforo a 1 e non bloccato nella P&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Le sequenze possibili sono: A AB A AB, AB A AB A, AB A A AB, A AB AB A&lt;/div&gt;</summary>
		<author><name>GabrieleCalarota</name></author>
	</entry>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=Prova_teorica_2015.02.14&amp;diff=1945</id>
		<title>Prova teorica 2015.02.14</title>
		<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php?title=Prova_teorica_2015.02.14&amp;diff=1945"/>
		<updated>2017-06-22T12:34:26Z</updated>

		<summary type="html">&lt;p&gt;GabrieleCalarota: /* Soluzione di Silas */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Testo: [http://www.cs.unibo.it/~renzo/so/compiti/2015.02.14.tot.pdf]&lt;br /&gt;
&lt;br /&gt;
== Esercizio c.1 ==&lt;br /&gt;
===Soluzione di Silas===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
#define MAX &lt;br /&gt;
&lt;br /&gt;
monitor altcolbb{&lt;br /&gt;
	queue buff;&lt;br /&gt;
	color_t last_color; //0: red, 1:blue, -1:&amp;quot;superstate&amp;quot;, means that both red and blue are accepted&lt;br /&gt;
	int wait_red, wait_blue;&lt;br /&gt;
	condition ok2read, redok, blueok;&lt;br /&gt;
&lt;br /&gt;
	void altcolbb(void){&lt;br /&gt;
		buff = new queue();&lt;br /&gt;
		last_color = -1;&lt;br /&gt;
		wait_red = wait_blue = 0;&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	procedure entry void write(color_t color, generic_type val){&lt;br /&gt;
		if(last_color == color || buff.length() == MAX){ //we can't enqueue if the colors are the same or if the buffer is full&lt;br /&gt;
			if(color == 0){ //enqueue to &amp;quot;reds&amp;quot;&lt;br /&gt;
				wait_red++;&lt;br /&gt;
				redok.wait();&lt;br /&gt;
				wait_red--;&lt;br /&gt;
			}else{ //enqueue to &amp;quot;blues&amp;quot;&lt;br /&gt;
				wait_blue++;&lt;br /&gt;
				blueok.wait();&lt;br /&gt;
				wait_blue--;&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
		buff.enqueue(val); //append val and update last_color&lt;br /&gt;
		last_color = color;&lt;br /&gt;
		ok2read.signal();&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	procedure entry generic_type read(void){&lt;br /&gt;
		if(buff.length() == 0)&lt;br /&gt;
			ok2read.wait();&lt;br /&gt;
		generic_type ret = buff.dequeue();&lt;br /&gt;
		if(buff.length() == 0)&lt;br /&gt;
			last_color = -1; //if buff is empty both colors can now be added&lt;br /&gt;
		switch(last_color){&lt;br /&gt;
			case -1: {&lt;br /&gt;
					if(wait_red&amp;gt;wait_blue) //if there are more &amp;quot;reds&amp;quot; waiting to write we signal them&lt;br /&gt;
						redok.signal();&lt;br /&gt;
					else&lt;br /&gt;
						blueok.signal(); //otherwise we signal &amp;quot;blues&amp;quot;&lt;br /&gt;
					break;&lt;br /&gt;
			}&lt;br /&gt;
			case 0: {&lt;br /&gt;
					blueok.signal();&lt;br /&gt;
					break;&lt;br /&gt;
			}&lt;br /&gt;
			case 1: {&lt;br /&gt;
					redok.signal();&lt;br /&gt;
					break;&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;
===Soluzione di MarcoNegrini===&lt;br /&gt;
I corrected Silas's version&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define MAX &lt;br /&gt;
 &lt;br /&gt;
monitor altcolbb{&lt;br /&gt;
	queue buff;&lt;br /&gt;
	color_t last_color; //0: red, 1:blue, -1:&amp;quot;superstate&amp;quot;, means that both red and blue are accepted&lt;br /&gt;
	condition ok2read, ok2write, redok, blueok;&lt;br /&gt;
&lt;br /&gt;
	void altcolbb(void){&lt;br /&gt;
		buff = new queue();&lt;br /&gt;
		last_color = -1;&lt;br /&gt;
	}&lt;br /&gt;
 &lt;br /&gt;
	procedure entry void write(color_t color, generic_type val){&lt;br /&gt;
		if(buff.length() == MAX){ //here waits if buff is full&lt;br /&gt;
			ok2write.wait();&lt;br /&gt;
		if(last_color==-1){ //if buff was empty it can just enqueue and exit&lt;br /&gt;
			buff.enqueue(val);&lt;br /&gt;
			last_color = color;&lt;br /&gt;
		}&lt;br /&gt;
		else{	&lt;br /&gt;
			if(color == 0){ //red section&lt;br /&gt;
				if (last_color == 0) //if last was red it needs to wait&lt;br /&gt;
					redok.wait();&lt;br /&gt;
				buff.enqueue(val); &lt;br /&gt;
				last_color = color; // it must set last color before signaling other writers&lt;br /&gt;
				blueok.signal(); //blue can now enqueue his value&lt;br /&gt;
			}else{ //blue section, same as above&lt;br /&gt;
				if (last_color == 1)&lt;br /&gt;
					blueok.wait();&lt;br /&gt;
				buff.enqueue(val);&lt;br /&gt;
				last_color = color;&lt;br /&gt;
				redok.signal();&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
		ok2read.signal(); // reader can now read&lt;br /&gt;
	}&lt;br /&gt;
 &lt;br /&gt;
	procedure entry generic_type read(void){&lt;br /&gt;
		//here waits if needed, then dequeue&lt;br /&gt;
		if(buff.length() == 0) &lt;br /&gt;
			ok2read.wait();&lt;br /&gt;
		generic_type ret = buff.dequeue();&lt;br /&gt;
&lt;br /&gt;
		//here signal the one that has been waiting for more time&lt;br /&gt;
		// it MUST be of the last_color color&lt;br /&gt;
		if(buff.length() == 0){&lt;br /&gt;
			color_t tmp=last_color;&lt;br /&gt;
			last_color = -1; &lt;br /&gt;
			// last color MUST be set to -1 here because &lt;br /&gt;
			// if there were writers waiting on ok2write.wait() (full buffer case)&lt;br /&gt;
			// they woundn't be signaled here, this happens if MAX=1&lt;br /&gt;
			&lt;br /&gt;
			if (tmp == 1) //&lt;br /&gt;
				blueok.signal();&lt;br /&gt;
			else&lt;br /&gt;
				redok.signal();&lt;br /&gt;
		}&lt;br /&gt;
		ok2write.signal();&lt;br /&gt;
	}&lt;br /&gt;
 &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
===Soluzione di FedericoB===&lt;br /&gt;
relating to Silas and Marco solution. A bounded buffer is a queue, so i think is wrong to use last_color as head element color when it's used as tail element color. &lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
#define MAX&lt;br /&gt;
&lt;br /&gt;
monitor altcobb {&lt;br /&gt;
	deque buffer&lt;br /&gt;
	condition waitRed, waitBlue, ok2read, ok2write&lt;br /&gt;
	altcobb() {&lt;br /&gt;
		buffer = new Deque()&lt;br /&gt;
		&lt;br /&gt;
	}&lt;br /&gt;
	procedure entry void write(colot_t color,generic_type val) {&lt;br /&gt;
		if (deque.getSize()==MAX) ok2write.wait()&lt;br /&gt;
		if (buffer.getSize==0) queue.addLast((val,color))&lt;br /&gt;
		else &lt;br /&gt;
			if (color==RED)&lt;br /&gt;
				if (buffer.getLast().color==BLUE)&lt;br /&gt;
					queue.addLast((val,color))&lt;br /&gt;
					waitRed.signal()&lt;br /&gt;
				else &lt;br /&gt;
					waitBlue.wait()&lt;br /&gt;
					queue.addLast((val,color))&lt;br /&gt;
			else&lt;br /&gt;
				if (buffer.getLast().color==RED)&lt;br /&gt;
					queue.addLast((val,color))&lt;br /&gt;
					waitBlue.signal()&lt;br /&gt;
				else &lt;br /&gt;
					waitRed.wait()&lt;br /&gt;
					queue.addLast((val,color))&lt;br /&gt;
		ok2read.signal()&lt;br /&gt;
	}&lt;br /&gt;
	procedure entry generic_type read() {&lt;br /&gt;
		if (deque.isEmpty()) ok2read.wait()&lt;br /&gt;
		element = deque.dequeueFirst();&lt;br /&gt;
		ok2write.signal()&lt;br /&gt;
		return element;&lt;br /&gt;
                #needed explanation: after the ok2write.signal() the current process will be put in wait state in the urgent stack, &lt;br /&gt;
                #but after the woke up process has exited the monitor this process will be woke up and it will return the element.&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Esercizio c.2 ==&lt;br /&gt;
===Soluzione di Silas===&lt;br /&gt;
I semafori garantiscono che A e B vengano eseguiti in maniera sequenziale e che accedano in maniera mutualmente esclusiva ad n, quindi l'unica variazione possibile è il thread di inizio per la sequenza. &amp;lt;br&amp;gt;&lt;br /&gt;
Nel caso sia A ad accedere per primo alla CS si ha: n = ((1*2)+2)*3 = 12 &amp;lt;br&amp;gt;&lt;br /&gt;
Nel caso sia invece B ad accedere per primo alla C si ha: n = (((0*2)+1)*3)+2 = 5 &amp;lt;br&amp;gt;&lt;br /&gt;
Quindi n = 12 e n = 5 sono i due possibili valori. &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Anche secondo me è così --[[User:FedericoB|FedericoB]] ([[User talk:FedericoB|talk]]) 20:58, 13 June 2017 (CEST)&lt;br /&gt;
&lt;br /&gt;
In realtà i possibili valori sono 4: 12 5 9 e 8. In quanto è vero che possono solo alternarsi i due thread. ma i semafori partono da 1. pertanto al &amp;quot;secondo giro può partire chiunque dei due, in quanto avrà il suo semaforo a 1 e non bloccato nella P&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Le sequenze possibili sono: A AB A AB, AB A AB A, AB A A AB, A AB AB A&lt;/div&gt;</summary>
		<author><name>GabrieleCalarota</name></author>
	</entry>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=Prova_pratica_2016.05.31&amp;diff=1889</id>
		<title>Prova pratica 2016.05.31</title>
		<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php?title=Prova_pratica_2016.05.31&amp;diff=1889"/>
		<updated>2017-05-21T20:07:14Z</updated>

		<summary type="html">&lt;p&gt;GabrieleCalarota: Corretto fork al posto di subprocess.popen() che non si può usare&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[http://www.cs.unibo.it/~renzo/so/pratiche/2016.05.31.pdf Link al testo]&lt;br /&gt;
&lt;br /&gt;
==Esercizio 1==&lt;br /&gt;
&amp;lt;source lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
Scrivere un programma che preso come parametro a linea comando il path di una directory elenchi solamente I file&lt;br /&gt;
che hanno un nome che ha come suffisso un numero (es. Prova.10). I file devono essere ordinati in ordine&lt;br /&gt;
numerico.&lt;br /&gt;
Esempio se la directory &lt;br /&gt;
test contiene I file prova5, giovanni, aaa.1000, bb.2000, ccc.dd.500 l'output del programma deve essere:&lt;br /&gt;
ccc.dd.500&lt;br /&gt;
aaa.1000&lt;br /&gt;
bb.2000&lt;br /&gt;
(in quanto 500 numericamente e' minore di 1000, prova5 non si considera: manca il punto prima del numero).&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
=== Soluzione di Alexp ===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;string.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;dirent.h&amp;gt;&lt;br /&gt;
#include &amp;lt;ctype.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdint.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/stat.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
Assumes that filename contains a digit in the suffix&lt;br /&gt;
*/&lt;br /&gt;
uint64_t getSuffixNumber(const char* filename){&lt;br /&gt;
    size_t len = strlen(filename)-1;&lt;br /&gt;
    size_t pos = len;&lt;br /&gt;
    uint64_t number = 0;&lt;br /&gt;
    uint64_t decimal = 1;&lt;br /&gt;
    //while there are digits to read&lt;br /&gt;
    while(pos&amp;gt;=0 &amp;amp;&amp;amp; isdigit(filename[pos])){&lt;br /&gt;
        //number+=digit converted to int, multiplied by decimal position&lt;br /&gt;
        number+=(filename[pos] - '0')*decimal;&lt;br /&gt;
        decimal*=10;&lt;br /&gt;
        pos--;&lt;br /&gt;
    }&lt;br /&gt;
    return number;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
Returns 1 if the given filename ends with a number, 0 otherwise&lt;br /&gt;
*/&lt;br /&gt;
int endsWithNumber(const char* filename){&lt;br /&gt;
    size_t len = strlen(filename)-1;&lt;br /&gt;
    size_t pos = len;&lt;br /&gt;
    //stating from last character, go backwards until there are digits&lt;br /&gt;
    while(pos&amp;gt;=0 &amp;amp;&amp;amp; isdigit(filename[pos])) pos--;&lt;br /&gt;
    //if the suffix is actually a number, preceeded by a '.'&lt;br /&gt;
    if(pos&amp;gt;=0 &amp;amp;&amp;amp; pos != len &amp;amp;&amp;amp; filename[pos] == '.') return 1;&lt;br /&gt;
    else return 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int sortbysuffix(const struct dirent **e1, const struct dirent **e2) {&lt;br /&gt;
    const char *a = (*e1)-&amp;gt;d_name;&lt;br /&gt;
    const char *b = (*e2)-&amp;gt;d_name;&lt;br /&gt;
    uint64_t suffixA = getSuffixNumber(a);&lt;br /&gt;
    uint64_t suffixB = getSuffixNumber(b);&lt;br /&gt;
    //compare two suffixes&lt;br /&gt;
    return suffixA &amp;lt; suffixB;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int filter(const struct dirent* ent){&lt;br /&gt;
    //exclude &amp;quot;.&amp;quot; and &amp;quot;..&amp;quot; and files not ending with a &amp;quot;.(number)+&amp;quot;&lt;br /&gt;
    if(strcmp(ent-&amp;gt;d_name,&amp;quot;.&amp;quot;) &amp;amp;&amp;amp; strcmp(ent-&amp;gt;d_name,&amp;quot;..&amp;quot;) &amp;amp;&amp;amp; endsWithNumber(ent-&amp;gt;d_name)){&lt;br /&gt;
        return 1;&lt;br /&gt;
    }&lt;br /&gt;
    else return 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void printFilenames(char* path){&lt;br /&gt;
    struct dirent **namelist;&lt;br /&gt;
    int n;&lt;br /&gt;
    n = scandir(path, &amp;amp;namelist, filter, sortbysuffix);&lt;br /&gt;
    if (n &amp;lt; 0)&lt;br /&gt;
        perror(&amp;quot;scandir&amp;quot;);&lt;br /&gt;
    else {&lt;br /&gt;
        while (n--) {&lt;br /&gt;
            printf(&amp;quot;%s\n&amp;quot;, namelist[n]-&amp;gt;d_name);&lt;br /&gt;
            free(namelist[n]);&lt;br /&gt;
        }&lt;br /&gt;
        free(namelist);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int isDirectory(const char *path) {&lt;br /&gt;
    struct stat statbuf;&lt;br /&gt;
    //if unable to get file status&lt;br /&gt;
    if (stat(path, &amp;amp;statbuf) != 0) return 0;&lt;br /&gt;
    //otherwise if we got the file status, check if it's a directory&lt;br /&gt;
    return S_ISDIR(statbuf.st_mode);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char* argv[]){&lt;br /&gt;
    if(argc == 2 &amp;amp;&amp;amp; isDirectory(argv[1])){&lt;br /&gt;
        printFilenames(argv[1]);&lt;br /&gt;
    }&lt;br /&gt;
    else{&lt;br /&gt;
        printf(&amp;quot;Error, input a directory name.\n&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Esercizio 2==&lt;br /&gt;
&amp;lt;source lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
Come nell'esercizio 1 occorre cercare in una directory (passata come parametro) I file che hanno come suffisso un&lt;br /&gt;
numero. Nell'esercizio 2 I file sono eseguibili e l numero indica il numero di millisecondi da attendere a partire dalla attivazione del programma prima di attivarli.&lt;br /&gt;
Nell'esempio dell'esercizio precedente occorre aspettare mezzo secondo e lanciare ccc.dd.500, poi a 1 secondo&lt;br /&gt;
dall'attivazione (cioe' dopo approssimativamente ulteriori 0.5 secondi) si lancia aaa.1000 e allo scadere del&lt;br /&gt;
secondo secondo bbb.2000.&lt;br /&gt;
I file eseguibili nella directory vengono eseguiti in background (non si attende la fine dell'esecuzione per&lt;br /&gt;
continuare). Quindi se due file hanno lo stesso prefisso numerico vengono eseguiti in modo concorrente.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
=== Soluzione di Alexp ===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;string.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;dirent.h&amp;gt;&lt;br /&gt;
#include &amp;lt;ctype.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdint.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/stat.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/wait.h&amp;gt;&lt;br /&gt;
#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
Assumes that filename contains a digit in the suffix&lt;br /&gt;
*/&lt;br /&gt;
uint64_t getSuffixNumber(const char* filename){&lt;br /&gt;
    size_t len = strlen(filename)-1;&lt;br /&gt;
    size_t pos = len;&lt;br /&gt;
    uint64_t number = 0;&lt;br /&gt;
    uint64_t decimal = 1;&lt;br /&gt;
    //while there are digits to read&lt;br /&gt;
    while(pos&amp;gt;=0 &amp;amp;&amp;amp; isdigit(filename[pos])){&lt;br /&gt;
        //number+=digit converted to int, multiplied by decimal position&lt;br /&gt;
        number+=(filename[pos] - '0')*decimal;&lt;br /&gt;
        decimal*=10;&lt;br /&gt;
        pos--;&lt;br /&gt;
    }&lt;br /&gt;
    return number;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int endsWithNumber(const char* filename){&lt;br /&gt;
    size_t len = strlen(filename)-1;&lt;br /&gt;
    size_t pos = len;&lt;br /&gt;
    //stating from last character, go backwards until there are digits&lt;br /&gt;
    while(pos&amp;gt;=0 &amp;amp;&amp;amp; isdigit(filename[pos])) pos--;&lt;br /&gt;
    //if the suffix is actually a number, preceeded by a '.'&lt;br /&gt;
    if(pos&amp;gt;=0 &amp;amp;&amp;amp; pos != len &amp;amp;&amp;amp; filename[pos] == '.') return 1;&lt;br /&gt;
    else return 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int sortbysuffix(const struct dirent **e1, const struct dirent **e2) {&lt;br /&gt;
    const char *a = (*e1)-&amp;gt;d_name;&lt;br /&gt;
    const char *b = (*e2)-&amp;gt;d_name;&lt;br /&gt;
    uint64_t suffixA = getSuffixNumber(a);&lt;br /&gt;
    uint64_t suffixB = getSuffixNumber(b);&lt;br /&gt;
    //compare two suffixes&lt;br /&gt;
    return suffixA &amp;lt; suffixB;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
Returns 1 if the file is an executable file, 0 otherwise&lt;br /&gt;
*/&lt;br /&gt;
int isExecutable(const char* path){&lt;br /&gt;
    struct stat buf;&lt;br /&gt;
    //if unable to get file status&lt;br /&gt;
    if (stat(path, &amp;amp;buf) != 0) return 0;&lt;br /&gt;
    //if the file is executable by user&lt;br /&gt;
    if (buf.st_mode &amp;amp; S_IXUSR) return 1;&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int filter(const struct dirent* ent){&lt;br /&gt;
    //exclude &amp;quot;.&amp;quot; and &amp;quot;..&amp;quot; and files not ending with a &amp;quot;.(number)+&amp;quot;&lt;br /&gt;
    if(strcmp(ent-&amp;gt;d_name,&amp;quot;.&amp;quot;) &amp;amp;&amp;amp; strcmp(ent-&amp;gt;d_name,&amp;quot;..&amp;quot;) &amp;amp;&amp;amp; endsWithNumber(ent-&amp;gt;d_name)){&lt;br /&gt;
        return 1;&lt;br /&gt;
    }&lt;br /&gt;
    else return 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void runExecutables(char* path){&lt;br /&gt;
    struct dirent **namelist;&lt;br /&gt;
    int n;&lt;br /&gt;
    //delay time in ms&lt;br /&gt;
    uint64_t waitingMS;&lt;br /&gt;
    char* fullpath;&lt;br /&gt;
    //forked child's pid&lt;br /&gt;
    pid_t pid;&lt;br /&gt;
    //used to wait all the children&lt;br /&gt;
    int status = 0;&lt;br /&gt;
    n = scandir(path, &amp;amp;namelist, filter, sortbysuffix);&lt;br /&gt;
    if (n &amp;lt; 0) perror(&amp;quot;scandir&amp;quot;);&lt;br /&gt;
    else {&lt;br /&gt;
        while (n--) {&lt;br /&gt;
            waitingMS = getSuffixNumber(namelist[n]-&amp;gt;d_name);&lt;br /&gt;
            //get the full dirname+filename path&lt;br /&gt;
            asprintf(&amp;amp;fullpath, &amp;quot;%s%s&amp;quot;, path, namelist[n]-&amp;gt;d_name);&lt;br /&gt;
            if(isExecutable(fullpath)){&lt;br /&gt;
                printf(&amp;quot;Calling %s\n&amp;quot;,fullpath);&lt;br /&gt;
                if( pid != fork() ){&lt;br /&gt;
                    //child&lt;br /&gt;
                    //wait for the required time(in microseconds)&lt;br /&gt;
          	    usleep(waitingMS*1000);&lt;br /&gt;
                    char *args[] = {fullpath,(char *)0};&lt;br /&gt;
                    printf(&amp;quot;Starting%s\n&amp;quot;, args[0]);&lt;br /&gt;
                    execvp(fullpath,args);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            free(fullpath);&lt;br /&gt;
            free(namelist[n]);&lt;br /&gt;
        }&lt;br /&gt;
        //wait till all the children terminate&lt;br /&gt;
        while ((pid = wait(&amp;amp;status)) &amp;gt; 0); &lt;br /&gt;
        free(namelist);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int isDirectory(const char *path) {&lt;br /&gt;
    struct stat statbuf;&lt;br /&gt;
    //if unable to get file status&lt;br /&gt;
    if (stat(path, &amp;amp;statbuf) != 0) return 0;&lt;br /&gt;
    //otherwise if we got the file status, check if it's a directory&lt;br /&gt;
    return S_ISDIR(statbuf.st_mode);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char* argv[]){&lt;br /&gt;
    if(argc == 2 &amp;amp;&amp;amp; isDirectory(argv[1])){&lt;br /&gt;
        runExecutables(argv[1]);&lt;br /&gt;
    }&lt;br /&gt;
    else{&lt;br /&gt;
        printf(&amp;quot;Error, input a directory name.\n&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
==Esercizio 3==&lt;br /&gt;
===Bash===&lt;br /&gt;
====Soluzione di G.C.====&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
&lt;br /&gt;
if [ $# -lt 1 ] ; then&lt;br /&gt;
	echo &amp;quot;Argument error&amp;quot;&lt;br /&gt;
	exit	&lt;br /&gt;
fi&lt;br /&gt;
tmp_file=file_tmp&lt;br /&gt;
touch $tmp_file&lt;br /&gt;
find $1 -type f | xargs basename -a | while read line&lt;br /&gt;
do&lt;br /&gt;
	#$line contains file name&lt;br /&gt;
	extension=&amp;quot;${line##*.}&amp;quot;&lt;br /&gt;
	#suffix contains only digits&lt;br /&gt;
	if [[ $extension =~ ^[0-9]+$ ]]&lt;br /&gt;
	then&lt;br /&gt;
	 	echo &amp;quot;$line:$extension&amp;quot; &amp;gt;&amp;gt; $tmp_file &lt;br /&gt;
	fi&lt;br /&gt;
done&lt;br /&gt;
&lt;br /&gt;
#sort by second column&lt;br /&gt;
tmp1_file=tmp1_file&lt;br /&gt;
cat $tmp_file | sort -t':' -nk2 &amp;gt; $tmp1_file&lt;br /&gt;
count=0&lt;br /&gt;
awk -F: '{print $1, $2}' $tmp1_file | while read line&lt;br /&gt;
do&lt;br /&gt;
	lineCols=( $line )&lt;br /&gt;
	#execute the first column in bg&lt;br /&gt;
	$1/${lineCols[0]} &amp;amp;&lt;br /&gt;
	#calculate the delay time from the last exec&lt;br /&gt;
	res=$((${lineCols[1]}-$count))&lt;br /&gt;
	count=${lineCols[1]}&lt;br /&gt;
	sleep $(($res / 1000))&lt;br /&gt;
done&lt;br /&gt;
rm $tmp_file $tmp1_file&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
===Python3===&lt;br /&gt;
====Soluzione di G.C.====&lt;br /&gt;
&amp;lt;source lang=&amp;quot;Python&amp;quot;&amp;gt;&lt;br /&gt;
import sys&lt;br /&gt;
import os&lt;br /&gt;
import time&lt;br /&gt;
import subprocess&lt;br /&gt;
&lt;br /&gt;
def getListOfFileAndTiming(d):&lt;br /&gt;
	listOfFile = [f for f in os.listdir(d) if os.path.isfile(os.path.join(d,f))]&lt;br /&gt;
	l = []&lt;br /&gt;
	for x in listOfFile:&lt;br /&gt;
		s = x.split('.')&lt;br /&gt;
		if s[0] != s[-1] and s[-1].isdigit():&lt;br /&gt;
			l.append((os.path.join(d,x),int(s[-1])))	&lt;br /&gt;
	return l&lt;br /&gt;
&lt;br /&gt;
def sleepAndExecute(l):&lt;br /&gt;
	l = sorted(l, key=lambda x:x[1])&lt;br /&gt;
	for x in l:&lt;br /&gt;
		print('starting %s '% (x[0]))&lt;br /&gt;
		if os.fork() == 0:&lt;br /&gt;
			subprocess.run([x[0]])&lt;br /&gt;
			sys.exit()&lt;br /&gt;
		print('sleeping %f s' % (x[1]/1000))&lt;br /&gt;
		time.sleep(x[1]/1000)&lt;br /&gt;
&lt;br /&gt;
if __name__ == '__main__':	&lt;br /&gt;
	try:&lt;br /&gt;
		if len(sys.argv) &amp;lt; 2:&lt;br /&gt;
			raise Exception(&amp;quot;Argument ERROR: input a directory&amp;quot;)&lt;br /&gt;
		directory = sys.argv[1]&lt;br /&gt;
		l = getListOfFileAndTiming(directory)&lt;br /&gt;
		sleepAndExecute(l)&lt;br /&gt;
	except Exception as inst:&lt;br /&gt;
		print(inst.args)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>GabrieleCalarota</name></author>
	</entry>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=Prova_pratica_2014.05.29&amp;diff=1888</id>
		<title>Prova pratica 2014.05.29</title>
		<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php?title=Prova_pratica_2014.05.29&amp;diff=1888"/>
		<updated>2017-05-19T10:40:27Z</updated>

		<summary type="html">&lt;p&gt;GabrieleCalarota: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Esercizio 1==&lt;br /&gt;
&amp;lt;source lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
Scrivere un programma con un solo parametro.&lt;br /&gt;
Come prima cosa il programma deve creare una directory con il path specificato nel parametro. Se la directory esiste gia' o si&lt;br /&gt;
verifica un errore nella creazione, il programma deve terminare. Chiameremo questa directory “directory-base”&lt;br /&gt;
Il programma usando inotify rimane in attesa e stampa una riga di log per ogni file o directory creato o cancellato nella&lt;br /&gt;
directory-base. (solo nella directory-base, non nelle sottodirectory).&lt;br /&gt;
Quando viene cancellata la directory-base il programma termina.&lt;br /&gt;
&lt;br /&gt;
Si estenda il programma dell'esercizio 1 per operare anche nelle sottodirectory. Quindi il programma “dovrebbe” stampare una&lt;br /&gt;
riga di log per ogni file o directory creata o cancellata in tutto il sottoalbero che ha nella directory-base la radice.&lt;br /&gt;
Nota: se necessario, usate strutture dati molto semplici come vettori o liste semplici, non preoccupatevi dell'efficienza.&lt;br /&gt;
In realta' per un problema nel design dell'API inotify, alcuni eventi di creazione di directory nidificate troppo vicini nel tempo&lt;br /&gt;
possono venir perduti.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Soluzione di Dado===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/stat.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/types.h&amp;gt;&lt;br /&gt;
#include &amp;lt;fcntl.h&amp;gt;&lt;br /&gt;
#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
#include &amp;lt;string.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/inotify.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#define EVENT_SIZE (sizeof(struct inotify_event))&lt;br /&gt;
#define BUFFER_SIZE (100*(EVENT_SIZE+16))&lt;br /&gt;
&lt;br /&gt;
/*dichiarazione di spy*/&lt;br /&gt;
int spy(char *path);&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char * argv[]){&lt;br /&gt;
	if(argc!=2){&lt;br /&gt;
	printf(&amp;quot;Numero argomenti sbagliato\n&amp;quot;);&lt;br /&gt;
	return -1;&lt;br /&gt;
	}else{&lt;br /&gt;
		int res=mkdir(argv[1],(mode_t)0777);&lt;br /&gt;
		if(res!=0)exit(-1);&lt;br /&gt;
		else return spy(argv[1]);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/*metodo che utilizza la inotify*/&lt;br /&gt;
int spy(char *path){&lt;br /&gt;
	int again=1;&lt;br /&gt;
	int fd;&lt;br /&gt;
	char buffer[BUFFER_SIZE];&lt;br /&gt;
	/*inizializzo il File Descriptor dell inotify*/&lt;br /&gt;
	fd=inotify_init();&lt;br /&gt;
	/*aggiungo &amp;quot;handler&amp;quot; per creazioni, eliminazioni all'interno della cartella path e per la sua eliminazione*/&lt;br /&gt;
	inotify_add_watch(fd,path, IN_CREATE | IN_DELETE | IN_DELETE_SELF);&lt;br /&gt;
	/*ciclo del programma di attesa dei valori*/&lt;br /&gt;
	printf(&amp;quot;Entro in ascolto della cartella %s\n&amp;quot;,path);&lt;br /&gt;
	while(again){&lt;br /&gt;
		int i=0;&lt;br /&gt;
		int len=read(fd,buffer,BUFFER_SIZE);&lt;br /&gt;
		while(i&amp;lt;len){&lt;br /&gt;
			/*gestisco un evento alla volta*/&lt;br /&gt;
			struct inotify_event *event =(struct inotify_event*)&amp;amp;buffer[i];&lt;br /&gt;
				/*controllo eventuale creazione di un file o di una cartella*/&lt;br /&gt;
      			if(event-&amp;gt;mask &amp;amp; IN_CREATE){&lt;br /&gt;
      				/*distinguo i due casi distinti*/&lt;br /&gt;
        			if(event-&amp;gt;mask &amp;amp; IN_ISDIR){&lt;br /&gt;
          				int pid;&lt;br /&gt;
          				printf( &amp;quot;Cartella %s creata in %s\n&amp;quot;,event-&amp;gt;name,path);&lt;br /&gt;
          				pid=fork();&lt;br /&gt;
          				if(!pid){&lt;br /&gt;
          					char *newpath=malloc((strlen(path))+event-&amp;gt;len+1); /*sommo 1 alla fine per lo /*/&lt;br /&gt;
          					strcpy(newpath,path);&lt;br /&gt;
          					strcat(newpath,&amp;quot;/&amp;quot;);&lt;br /&gt;
          					strcat(newpath,event-&amp;gt;name);&lt;br /&gt;
          					return spy(newpath);&lt;br /&gt;
          				}&lt;br /&gt;
        			}&lt;br /&gt;
        			else&lt;br /&gt;
          				printf(&amp;quot;File %s creato in %s\n&amp;quot;,event-&amp;gt;name,path);&lt;br /&gt;
      			}&lt;br /&gt;
      			/*controllo eventuale eliminazione di un file o di una cartella*/&lt;br /&gt;
      			else if(event-&amp;gt;mask &amp;amp; IN_DELETE){&lt;br /&gt;
      				/*distinguo i due casi distinti*/&lt;br /&gt;
        			if(!(event-&amp;gt;mask &amp;amp; IN_ISDIR))&lt;br /&gt;
          				printf(&amp;quot;File %s eliminato in %s\n&amp;quot;,event-&amp;gt;name,path);&lt;br /&gt;
          		}&lt;br /&gt;
          		/*controllo eventuale eliminazione della cartella che sto controllando*/&lt;br /&gt;
          		else if(event-&amp;gt;mask &amp;amp; IN_DELETE_SELF){&lt;br /&gt;
          			printf(&amp;quot;Cartella %s eliminata.\n&amp;quot;,path);&lt;br /&gt;
          			again=0;	/*fermo il ciclo più esterno che esegue le read*/&lt;br /&gt;
          		}&lt;br /&gt;
          	/*avanzo all'evento successivo, se c'è*/&lt;br /&gt;
    		i += EVENT_SIZE + event-&amp;gt;len;	&lt;br /&gt;
    	}&lt;br /&gt;
    }&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
==Esercizio 3==&lt;br /&gt;
&amp;lt;source lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
Il comando che dovrete implementare come script shell o programma python e' statlen.&lt;br /&gt;
Data una directory statlen fa una statistica sulla lunghezza dei nomi dei file presenti in tutto il sottoalbero con radice nella&lt;br /&gt;
directory passata come parametro.&lt;br /&gt;
es.&lt;br /&gt;
$ statlen /tmp&lt;br /&gt;
2: 2&lt;br /&gt;
3: 10&lt;br /&gt;
5: 4&lt;br /&gt;
...&lt;br /&gt;
significa che in tmp (e in tutte le sottodir.ectory di /tmp) ci sono 2 file con nome di due caratteri, 10 con nomi di 3 caratteri e&lt;br /&gt;
cosi' via.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
===Python3===&lt;br /&gt;
==== Soluzione di Krusty ====&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import os, sys&lt;br /&gt;
from stat import *&lt;br /&gt;
&lt;br /&gt;
def recScan(pathname,v):&lt;br /&gt;
	for f in os.listdir(pathname):&lt;br /&gt;
		path = os.path.join(pathname,f)&lt;br /&gt;
		s = os.stat(path)&lt;br /&gt;
		if S_ISREG(s.st_mode):&lt;br /&gt;
			l = len(f)&lt;br /&gt;
			if(l not in v):&lt;br /&gt;
				v[l]=1&lt;br /&gt;
			else:&lt;br /&gt;
				v[l] = v[l] + 1&lt;br /&gt;
		elif S_ISDIR(s.st_mode):	&lt;br /&gt;
			recScan(path,v)&lt;br /&gt;
&lt;br /&gt;
v = {}&lt;br /&gt;
recScan(sys.argv[1],v)	&lt;br /&gt;
for key in v:&lt;br /&gt;
	print(key, ':', v[key])&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
===Bash===&lt;br /&gt;
==== Soluzione di ababa ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
cd $1&lt;br /&gt;
files=`find -L`&lt;br /&gt;
declare -a stat&lt;br /&gt;
for file in $files; do&lt;br /&gt;
	file=`basename $file`&lt;br /&gt;
	len=`expr length &amp;quot;$file&amp;quot;`&lt;br /&gt;
	((stat[$len]++))&lt;br /&gt;
done&lt;br /&gt;
for i in ${!stat[@]}; do&lt;br /&gt;
	echo &amp;quot;${i} : ${stat[$i]}&amp;quot;&lt;br /&gt;
done&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mi piacerebbe sapere perché se lo lancio come eseguibile funziona senza problemi se lo lancio con il comando &amp;quot;sh statlen.sh .&amp;quot; invece mi da un sacco di errori.&lt;br /&gt;
&lt;br /&gt;
Perche' &amp;quot;sh&amp;quot; non e' bash ma e' la bourne shell che ha una sitassi meno ricca [[User:Renzo|Renzo]] ([[User talk:Renzo|talk]]) 22:12, 20 April 2015 (CEST)&lt;/div&gt;</summary>
		<author><name>GabrieleCalarota</name></author>
	</entry>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=Prova_Pratica_2014.06.17&amp;diff=1887</id>
		<title>Prova Pratica 2014.06.17</title>
		<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php?title=Prova_Pratica_2014.06.17&amp;diff=1887"/>
		<updated>2017-05-18T14:35:15Z</updated>

		<summary type="html">&lt;p&gt;GabrieleCalarota: /* Esercizio 3 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[http://www.cs.unibo.it/~renzo/so/pratiche/2014.06,17.pdf Link al testo]&lt;br /&gt;
==Esercizio 1==&lt;br /&gt;
&amp;lt;source lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
Occorre scrivere due programmi: mytar myuntar.&lt;br /&gt;
Mytar prende come parametro il nome di una directory e il nome di un file:&lt;br /&gt;
mytar ddd ddd.mytar&lt;br /&gt;
mytar crea il file indicato come secondo parametro e registra in esso tutti i file regolari presenti nella directory (ddd&lt;br /&gt;
nell'esempio). Ogni file e' registrato nel secondo il seguente formato:&lt;br /&gt;
nome del file (stringa ASCII terminata da un byte 0)&lt;br /&gt;
lunghezza del file (stringa ASCII terminata da 0, la lunghezza e' registrata come stringa in rappresentazione in base 10&lt;br /&gt;
per non avere problemi di endianess e di ampiezza dei campi)&lt;br /&gt;
contenuto del file (un numero di byte corrispondente alla lunghezza indicata sopra).&lt;br /&gt;
Myuntar fa l'operazione inversa:&lt;br /&gt;
myuntar ddd.mytar newddd&lt;br /&gt;
crea la directory indicata come secondo parametro e, in essa, tutti i file registrati in ddd.mytar.&lt;br /&gt;
Per provare i due programmi, al termine dell'esecuzione di due comandi simili a quelli degli esempi mostrati qui sopra per&lt;br /&gt;
mytar e myuntar, tutti i file regolari presenti in ddd devono esistere in newddd e devono avere tutti lo stesso contenuto.&lt;br /&gt;
Se create una directory ddd contenente solo file regolare l'output di “diff -R ddd newddd” deve essere vuoto.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Soluzione di Dado===&lt;br /&gt;
mytar e myuntar entrambi funzionanti&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
mytar.c&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;string.h&amp;gt;&lt;br /&gt;
#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/types.h&amp;gt;&lt;br /&gt;
#include &amp;lt;dirent.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/stat.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define MAX 20&lt;br /&gt;
#define MAXI 1024&lt;br /&gt;
&lt;br /&gt;
/*codice copiato da internet che ipotizzo funzioni :) */&lt;br /&gt;
&lt;br /&gt;
 void reverse(char s[])&lt;br /&gt;
 {&lt;br /&gt;
     int i, j;&lt;br /&gt;
     char c;&lt;br /&gt;
 &lt;br /&gt;
     for (i = 0, j = strlen(s)-1; i&amp;lt;j; i++, j--) {&lt;br /&gt;
         c = s[i];&lt;br /&gt;
         s[i] = s[j];&lt;br /&gt;
         s[j] = c;&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
void itoa(int n, char s[])&lt;br /&gt;
 {&lt;br /&gt;
     int i, sign;&lt;br /&gt;
 &lt;br /&gt;
     if ((sign = n) &amp;lt; 0)  /* record sign */&lt;br /&gt;
         n = -n;          /* make n positive */&lt;br /&gt;
     i = 0;&lt;br /&gt;
     do {       /* generate digits in reverse order */&lt;br /&gt;
         s[i++] = n % 10 + '0';   /* get next digit */&lt;br /&gt;
     } while ((n /= 10) &amp;gt; 0);     /* delete it */&lt;br /&gt;
     if (sign &amp;lt; 0)&lt;br /&gt;
         s[i++] = '-';&lt;br /&gt;
     s[i] = '\0';&lt;br /&gt;
     reverse(s);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/*mytar*/&lt;br /&gt;
int main(int argc, char * argv[]){&lt;br /&gt;
	if(argc!=3){&lt;br /&gt;
		fprintf(stderr, &amp;quot;Wrong arguments number\n&amp;quot;);&lt;br /&gt;
		return -1;&lt;br /&gt;
	}&lt;br /&gt;
	else{&lt;br /&gt;
		FILE *dest;&lt;br /&gt;
		FILE *temp;&lt;br /&gt;
		DIR *dir;&lt;br /&gt;
		char length[MAX];&lt;br /&gt;
		char *buf_read;&lt;br /&gt;
		char zero='\0';&lt;br /&gt;
		size_t n_readed;&lt;br /&gt;
		struct stat buf;&lt;br /&gt;
		struct dirent *entry;&lt;br /&gt;
		if((dir=opendir(argv[1]))==NULL){&lt;br /&gt;
			fprintf(stderr, &amp;quot;Error opendir\n&amp;quot;);&lt;br /&gt;
			exit(-1);&lt;br /&gt;
		}&lt;br /&gt;
		if((dest=fopen(argv[2],&amp;quot;w&amp;quot;))==NULL){&lt;br /&gt;
			fprintf(stderr, &amp;quot;Error fopen\n&amp;quot;);&lt;br /&gt;
			exit(-1);&lt;br /&gt;
		}&lt;br /&gt;
		while((entry=readdir(dir))!=NULL){&lt;br /&gt;
			buf_read=NULL;&lt;br /&gt;
			chdir(argv[1]);&lt;br /&gt;
			if(entry-&amp;gt;d_type==DT_REG){&lt;br /&gt;
				if(stat(entry-&amp;gt;d_name,&amp;amp;buf)==-1){&lt;br /&gt;
					fprintf(stderr, &amp;quot;Error stat\n&amp;quot;);&lt;br /&gt;
					exit(-1);&lt;br /&gt;
				}&lt;br /&gt;
				if((temp=fopen(entry-&amp;gt;d_name,&amp;quot;r&amp;quot;))==NULL){&lt;br /&gt;
					fprintf(stderr, &amp;quot;Error fopen_temp\n&amp;quot;);&lt;br /&gt;
					exit(-1);&lt;br /&gt;
				}&lt;br /&gt;
				write(fileno(dest),entry-&amp;gt;d_name,strlen(entry-&amp;gt;d_name)+1);&lt;br /&gt;
				itoa(buf.st_size-1,length);&lt;br /&gt;
				write(fileno(dest),length,strlen(length)+1);&lt;br /&gt;
				/*scrivere dati*/&lt;br /&gt;
				while(getdelim(&amp;amp;buf_read,&amp;amp;n_readed,EOF,temp)&amp;gt;0){&lt;br /&gt;
					write(fileno(dest),buf_read,strlen(buf_read)-1);&lt;br /&gt;
				}&lt;br /&gt;
				free(buf_read);&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
		printf(&amp;quot;File mytar creato con successo!\n&amp;quot;);&lt;br /&gt;
		return 0;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
myuntar.c&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;string.h&amp;gt;&lt;br /&gt;
#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/types.h&amp;gt;&lt;br /&gt;
#include &amp;lt;dirent.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/stat.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char * argv[]){&lt;br /&gt;
	if(argc!=3){&lt;br /&gt;
		fprintf(stderr, &amp;quot;Wrong arguments number\n&amp;quot;);&lt;br /&gt;
		exit(-1);&lt;br /&gt;
	}else{&lt;br /&gt;
		FILE *mytar;&lt;br /&gt;
		FILE *tmp;&lt;br /&gt;
		char nome[256];&lt;br /&gt;
		int dim, i;&lt;br /&gt;
		char readed[2],length[20];&lt;br /&gt;
		nome[0]=length[0]=0;&lt;br /&gt;
		readed[1]=0;&lt;br /&gt;
		if(mkdir(argv[2],(mode_t)0777)==-1){&lt;br /&gt;
			fprintf(stderr, &amp;quot;Error mkdir\n&amp;quot;);&lt;br /&gt;
			exit(-1);&lt;br /&gt;
		}&lt;br /&gt;
		if((mytar=fopen(argv[1],&amp;quot;r&amp;quot;))==NULL){&lt;br /&gt;
			fprintf(stderr, &amp;quot;Error fopen\n&amp;quot;);&lt;br /&gt;
			exit(-1);&lt;br /&gt;
		}&lt;br /&gt;
		if(chdir(argv[2])==-1){&lt;br /&gt;
			fprintf(stderr, &amp;quot;Errore chdir\n&amp;quot;);&lt;br /&gt;
			exit(-1);&lt;br /&gt;
		}&lt;br /&gt;
		while((fread(&amp;amp;readed,1,1,mytar))){&lt;br /&gt;
			strcat(nome,readed);&lt;br /&gt;
			while((fread(&amp;amp;readed,1,1,mytar))){&lt;br /&gt;
				if(readed[0]=='\0') break;&lt;br /&gt;
				strcat(nome,readed);&lt;br /&gt;
			}&lt;br /&gt;
			printf(&amp;quot;Nome trovato: %s\n&amp;quot;,nome);&lt;br /&gt;
			if((tmp=fopen(nome,&amp;quot;w&amp;quot;))==NULL){&lt;br /&gt;
				fprintf(stderr, &amp;quot;Error fopen files\n&amp;quot;);&lt;br /&gt;
				exit(-1);&lt;br /&gt;
			}&lt;br /&gt;
			while((fread(&amp;amp;readed,1,1,mytar))){&lt;br /&gt;
				if(readed[0]=='\0') break;&lt;br /&gt;
				strcat(length,readed);&lt;br /&gt;
			}&lt;br /&gt;
			dim=atoi(length);&lt;br /&gt;
			printf(&amp;quot;Lunghezza trovata: %s\n&amp;quot;,length);&lt;br /&gt;
			for(i=0; i&amp;lt;dim; i++){&lt;br /&gt;
				fread(&amp;amp;readed,1,1,mytar);&lt;br /&gt;
				write(fileno(tmp),&amp;amp;readed,1);&lt;br /&gt;
			}&lt;br /&gt;
		fclose(tmp);&lt;br /&gt;
		nome[0]=0;&lt;br /&gt;
		length[0]=0;&lt;br /&gt;
		}&lt;br /&gt;
	fclose(mytar);&lt;br /&gt;
	printf(&amp;quot;File myuntar scompattato correttamente, credo\n&amp;quot;);&lt;br /&gt;
	return 0;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Soluzione di MV ===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
Per ora ho fatto solo la prima parte, cioè mytar.&lt;br /&gt;
L'unico problema che non riesco a capire è che entra in un loop infinito (scrivendo all'infinito sul file che crea!) se viene usato nella cartella dell'eseguibile stesso...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
/*-------------------------------------MYTAR.C--------------------------------------------*/&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;string.h&amp;gt;&lt;br /&gt;
#include &amp;lt;errno.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/types.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/stat.h&amp;gt;&lt;br /&gt;
#include &amp;lt;dirent.h&amp;gt;&lt;br /&gt;
#include &amp;lt;fcntl.h&amp;gt;&lt;br /&gt;
#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define BUF_DIM 512&lt;br /&gt;
&lt;br /&gt;
/* scrive nome, dimensione e contenuto del file indicato da src nel file dest (già aperto in scrittura) */&lt;br /&gt;
int filecpy(const char *src, const int dest, off_t size);&lt;br /&gt;
&lt;br /&gt;
/* ---------------------------------- MAIN ------------------------------- */&lt;br /&gt;
int main(int argc, char* argv[])&lt;br /&gt;
{	&lt;br /&gt;
	DIR *ddd;&lt;br /&gt;
	int f;&lt;br /&gt;
	struct dirent *entry;&lt;br /&gt;
	struct stat dest_st;&lt;br /&gt;
	int e,i,len;&lt;br /&gt;
	char buf[BUF_DIM];&lt;br /&gt;
	&lt;br /&gt;
	if(argc != 3)&lt;br /&gt;
	{&lt;br /&gt;
		printf(&amp;quot;Error: needed 2 parameters\n&amp;quot;);&lt;br /&gt;
		return 1;&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	umask(0001);&lt;br /&gt;
	/* Creo il file passato come secondo parametro */&lt;br /&gt;
	if((f = open(argv[2], O_WRONLY|O_CREAT|O_TRUNC, 0666)) == -1)&lt;br /&gt;
	{&lt;br /&gt;
		printf(&amp;quot;Error in open(): %s (%i)\n&amp;quot;,strerror(errno),errno);&lt;br /&gt;
		return errno;&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	/* Apro la directory passata come primo parametro, se c'è */&lt;br /&gt;
	if((ddd = opendir(argv[1])) == NULL)&lt;br /&gt;
	{&lt;br /&gt;
		printf(&amp;quot;Error in opendir(%s): %s (%i)\n&amp;quot;,argv[1],strerror(errno),errno);&lt;br /&gt;
		return errno;&lt;br /&gt;
	}&lt;br /&gt;
	/* mi sposto in quella directory */&lt;br /&gt;
	if(chdir(argv[1]) == -1)&lt;br /&gt;
	{&lt;br /&gt;
		printf(&amp;quot;Error in chdir(%s): %s (%i)\n&amp;quot;,argv[1],strerror(errno),errno);&lt;br /&gt;
		return errno;&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	e = errno;&lt;br /&gt;
	i = 0;	/* in i mantengo il numero totale di file copiati */&lt;br /&gt;
	/* leggo lo stat del file che ho creato */&lt;br /&gt;
	if(fstat(f, &amp;amp;dest_st) == -1)&lt;br /&gt;
	{&lt;br /&gt;
		printf(&amp;quot;Error in stat(%s): %s (%i)\n&amp;quot;,buf,strerror(errno),errno);&lt;br /&gt;
		return errno;&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	/* leggo le entry della directory finchè ce ne sono */&lt;br /&gt;
	while((entry = readdir(ddd)) != NULL)&lt;br /&gt;
	{&lt;br /&gt;
		struct stat st;&lt;br /&gt;
		&lt;br /&gt;
		strcpy(buf, entry-&amp;gt;d_name);&lt;br /&gt;
		&lt;br /&gt;
		if(stat(buf, &amp;amp;st) == -1)&lt;br /&gt;
		{&lt;br /&gt;
			printf(&amp;quot;Error in stat(%s): %s (%i)\n&amp;quot;,buf,strerror(errno),errno);&lt;br /&gt;
			return errno;&lt;br /&gt;
		}&lt;br /&gt;
		else if(st.st_mode &amp;amp; S_IFREG)	/* è un file */&lt;br /&gt;
		{	&lt;br /&gt;
			/* verifico che il file in questione sia diverso da quello aperto in scrittura, per evitare che scriva su se stesso all'infinito */&lt;br /&gt;
			if((st.st_ino == dest_st.st_ino) &amp;amp;&amp;amp; (st.st_rdev == dest_st.st_rdev))&lt;br /&gt;
				continue;&lt;br /&gt;
			&lt;br /&gt;
			if(filecpy(buf, f, st.st_size) == -1)&lt;br /&gt;
			{&lt;br /&gt;
				printf(&amp;quot;Error in filecpy(%s, %i)\n&amp;quot;,buf,f);&lt;br /&gt;
				return -1;&lt;br /&gt;
			}&lt;br /&gt;
			printf(&amp;quot;%s inserito.\n&amp;quot;, buf);&lt;br /&gt;
			i++;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	if(e != errno)	/* sono uscito dal ciclo a causa di un errore */&lt;br /&gt;
	{&lt;br /&gt;
		printf(&amp;quot;Error in readdir(): %s (%i)\n&amp;quot;,strerror(errno),errno);&lt;br /&gt;
		return errno;			&lt;br /&gt;
	}&lt;br /&gt;
	else	/* perchè ho visitato tutte le entrate della directory */&lt;br /&gt;
		printf(&amp;quot;end of directory, %i entry found.\n&amp;quot;, i);&lt;br /&gt;
	&lt;br /&gt;
	return 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int filecpy(const char *src, const int dest, off_t size)&lt;br /&gt;
{&lt;br /&gt;
	/* NB: dest è già aperto in scrittura */&lt;br /&gt;
	int s, len, tot;&lt;br /&gt;
	char buf[BUF_DIM];&lt;br /&gt;
	&lt;br /&gt;
	if((s = open(src,O_RDONLY,0)) == -1)	/* apro src in lettura */&lt;br /&gt;
		return -1;&lt;br /&gt;
	&lt;br /&gt;
	tot = write(dest, src, strlen(src)+1);	/* per prima cosa copio il titolo del file src */&lt;br /&gt;
							/* NB: faccio tot+1 per copiare anche lo 0 terminatore */&lt;br /&gt;
	sprintf(buf, &amp;quot;%i&amp;quot;, (int)size);	/* poi copio la dimensione */&lt;br /&gt;
	tot += write(dest, buf, strlen(buf)+1);&lt;br /&gt;
	&lt;br /&gt;
	/* infine copio tutto il contenuto */&lt;br /&gt;
	while( (len = read(s,buf,BUF_DIM)) != 0)&lt;br /&gt;
	{&lt;br /&gt;
		if(len == -1)&lt;br /&gt;
		{&lt;br /&gt;
			printf(&amp;quot;Error in read(): %s (%i)\n&amp;quot;,strerror(errno),errno);&lt;br /&gt;
			return -1;&lt;br /&gt;
		}&lt;br /&gt;
		/*else printf(&amp;quot;%i\n&amp;quot;,len);*/&lt;br /&gt;
		tot += write(dest, buf, len);&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	return tot;	/* restituisce il numero totale di byte scritti */&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Esercizio 3==&lt;br /&gt;
&amp;lt;source lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
Il comando che dovrete implementare come script shell o programma python e' maxfreq.&lt;br /&gt;
Maxfreq ha come parametro un carattere alfanumerico e una directory.&lt;br /&gt;
Es:&lt;br /&gt;
maxfreq q mydir&lt;br /&gt;
Cerca in tutto il sottoalbero del file system originato da mydir il file che ha la maggior frequenza della lettera indicata (in&lt;br /&gt;
questo caso la maggior frequenza di 'q'). Fornisce in output il nome del file e la frequenza in percentuale.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
===Bash===&lt;br /&gt;
====Soluzione di Davide Quadrelli====&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#! /bin/bash&lt;br /&gt;
if [[ -z $1 ]] ; then&lt;br /&gt;
	echo &amp;quot;maxfreq [char da contare] [directory]&amp;quot;&lt;br /&gt;
	exit&lt;br /&gt;
fi&lt;br /&gt;
if [[ -n $2 ]] ; then&lt;br /&gt;
	files=`find -L $2`&lt;br /&gt;
else&lt;br /&gt;
	echo if2&lt;br /&gt;
	echo &amp;quot;maxfreq [char da contare] [directory]&amp;quot;&lt;br /&gt;
	exit&lt;br /&gt;
fi&lt;br /&gt;
max=0&lt;br /&gt;
file=&amp;quot;&amp;quot;&lt;br /&gt;
for var in $files; do&lt;br /&gt;
	tmp=`cat $var 2&amp;gt; /dev/null | grep -c $1 2&amp;gt; /dev/null`&lt;br /&gt;
	if [[ max -le tmp ]]; then&lt;br /&gt;
		max=$tmp&lt;br /&gt;
		file=$var&lt;br /&gt;
	fi&lt;br /&gt;
done&lt;br /&gt;
dim=`ls -l $file | cut -d &amp;quot; &amp;quot; -f 5`&lt;br /&gt;
echo &amp;quot;( ${max} * 100 ) / ${dim}&amp;quot; &amp;gt; tmp&lt;br /&gt;
echo &amp;quot;quit&amp;quot; &amp;gt;&amp;gt; tmp&lt;br /&gt;
perc=`bc -q tmp`&lt;br /&gt;
rm tmp&lt;br /&gt;
echo &amp;quot;Il file $file contiene ${perc}% di $1 ($max su $dim caratteri)&amp;quot;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Ho sfruttato il comando bc per calcolare la percentuale. Utilizzo il parametro -q per impedire che stampi il &amp;quot;saluto&amp;quot; del programma e metto tutto il codice da eseguire nel file tmp. Oltre al comando, inserisco un &amp;quot;quit&amp;quot; per terminare il comando bc, che avrà restituito alla variabile soltanto il risultato del calcolo. Elimino poi ovviamente il file tmp.&lt;br /&gt;
&lt;br /&gt;
=====Nota di Maldus=====&lt;br /&gt;
grep -c $1 conta il numero di righe in cui si trovano le occorrenze; questo significa che se in una riga abbiamo 2 ( o più ) occorrenze viene comunque contata come 1.&lt;br /&gt;
Per contare tutte le occorrenze ( anche nella stessa riga ) si potrebbe sostituire la riga&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
tmp=`cat $var 2&amp;gt; /dev/null | grep -c $1 2&amp;gt; /dev/null`&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
con&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
tmp=`cat $var 2&amp;gt; /dev/null | grep -o $1 2&amp;gt; /dev/null | wc -l`&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Soluzione di G.C. ====&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
&lt;br /&gt;
#input check &lt;br /&gt;
&lt;br /&gt;
if [ $# -lt 2 ] ; then&lt;br /&gt;
	echo &amp;quot;Arguments Error. Usage ./maxfreq character directory&amp;quot;&lt;br /&gt;
	exit&lt;br /&gt;
fi&lt;br /&gt;
if [[ &amp;quot;$1&amp;quot; =~ [^a-zA-Z0-9] ]]; then&lt;br /&gt;
	echo &amp;quot;invalid character&amp;quot;&lt;br /&gt;
	exit&lt;br /&gt;
fi&lt;br /&gt;
if ! [ -d $2 ] ; then&lt;br /&gt;
	echo &amp;quot;invalid directory as second argument&amp;quot;&lt;br /&gt;
	exit&lt;br /&gt;
fi &lt;br /&gt;
&lt;br /&gt;
tmp_file=/tmp/maxfreq$$&lt;br /&gt;
&lt;br /&gt;
#recursively find of $2 directory&lt;br /&gt;
find $2 -type f | while read line&lt;br /&gt;
do&lt;br /&gt;
	num=$(cat $line | grep -o $1 | wc -l)&lt;br /&gt;
	echo &amp;quot;$num:$line&amp;quot; &amp;gt;&amp;gt; $tmp_file&lt;br /&gt;
done&lt;br /&gt;
&lt;br /&gt;
#file of &amp;quot;numOccurency:FileName&amp;quot;&lt;br /&gt;
&lt;br /&gt;
ord_tmp_file=/tmp/ord_tmp_file$$&lt;br /&gt;
&lt;br /&gt;
#reverse ordering of the file and rewriting&lt;br /&gt;
cat $tmp_file | sort -r &amp;gt; $ord_tmp_file&lt;br /&gt;
rm $tmp_file&lt;br /&gt;
&lt;br /&gt;
#take first line (major file occurency of char $1)&lt;br /&gt;
num=$(head -1 $ord_tmp_file | awk -F: '{print $1}')&lt;br /&gt;
file=$(head -1 $ord_tmp_file | awk -F: '{print $2}')&lt;br /&gt;
&lt;br /&gt;
#count all char in $file of the first line&lt;br /&gt;
max=$(cat $file | wc -c)&lt;br /&gt;
&lt;br /&gt;
#basename of file name (this is not mandatory)&lt;br /&gt;
base=$(basename $file)&lt;br /&gt;
&lt;br /&gt;
#math to calculate % num/max&lt;br /&gt;
tmp_math_file=/tmp/math$$&lt;br /&gt;
echo &amp;quot;( ${num} *100) / ${max}&amp;quot; &amp;gt; $tmp_math_file&lt;br /&gt;
echo &amp;quot;quit&amp;quot; &amp;gt;&amp;gt; $tmp_math_file&lt;br /&gt;
freq=$(bc -q $tmp_math_file)&lt;br /&gt;
rm $tmp_math_file&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
echo &amp;quot;File: $base Freq '$1' of $freq %&amp;quot;&lt;br /&gt;
&lt;br /&gt;
rm $ord_tmp_file&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Python3===&lt;br /&gt;
====Soluzione di G.C.====&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import sys&lt;br /&gt;
import os&lt;br /&gt;
&lt;br /&gt;
def checkFile(char, d):&lt;br /&gt;
	e = []&lt;br /&gt;
	for x in os.listdir(d):&lt;br /&gt;
		if os.path.isdir(os.path.join(d,x)):&lt;br /&gt;
			e.append(checkFile(char,os.path.join(d,x)))&lt;br /&gt;
		else:&lt;br /&gt;
			f = open(os.path.join(d,x),&amp;quot;r&amp;quot;)&lt;br /&gt;
			e.append((os.path.join(d,x),f.read().count(char)))&lt;br /&gt;
			f.close()&lt;br /&gt;
	return e&lt;br /&gt;
&lt;br /&gt;
def sortAndPrint(d):&lt;br /&gt;
	d.sort(key=lambda tup: tup[1], reverse=True)&lt;br /&gt;
	fileName= d[0][0]&lt;br /&gt;
	num = d[0][1]&lt;br /&gt;
	f = open(fileName,&amp;quot;r&amp;quot;)&lt;br /&gt;
	max_c = len(f.read())&lt;br /&gt;
	f.close()&lt;br /&gt;
	return fileName, num/max_c*100&lt;br /&gt;
&lt;br /&gt;
if __name__=='__main__':&lt;br /&gt;
	try:&lt;br /&gt;
		if len(sys.argv) &amp;lt; 3:&lt;br /&gt;
			raise Exception(&amp;quot;Too few arguments. Usage ./maxfreq char dir&amp;quot;)&lt;br /&gt;
		if not sys.argv[1].isalnum():&lt;br /&gt;
			raise Exception(&amp;quot;Char not alphanumeric passed&amp;quot;)&lt;br /&gt;
		if not os.path.isdir(sys.argv[2]):&lt;br /&gt;
			raise Exception(&amp;quot;%s is not a directory&amp;quot; % (sys.argv[2]))&lt;br /&gt;
		d = checkFile(sys.argv[1],sys.argv[2])&lt;br /&gt;
		f,p = sortAndPrint(d)&lt;br /&gt;
		print(&amp;quot;Maxfreq occurency of %s was in %s with a percentage of %f %%&amp;quot; % (sys.argv[1],f,p))&lt;br /&gt;
	except Exception as inst:&lt;br /&gt;
		print(inst.args)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>GabrieleCalarota</name></author>
	</entry>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=Prova_pratica_2016.09.13&amp;diff=1886</id>
		<title>Prova pratica 2016.09.13</title>
		<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php?title=Prova_pratica_2016.09.13&amp;diff=1886"/>
		<updated>2017-05-17T10:17:50Z</updated>

		<summary type="html">&lt;p&gt;GabrieleCalarota: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[http://www.cs.unibo.it/~renzo/so/pratiche/2016.09.13.pdf Link al testo] (è sbagliata la data nel titolo ma il testo è quello giusto)&lt;br /&gt;
==Esercizio 1==&lt;br /&gt;
&amp;lt;source lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
Scrivere un programma che mostri il funzionamento del file locking.&lt;br /&gt;
In particolare il programma cplk avra’ due argomenti che I pathname di due file. Il contenuto del primo file deve&lt;br /&gt;
essere copiato nel secondo usando la system call sendfile.&lt;br /&gt;
Prima di iniziare la copia occorre usare la system call fcntl per bloccare il file di output (write lock).&lt;br /&gt;
Completata la copia occorre chiamare nuovamente la fcntl per sbloccare il file.&lt;br /&gt;
Inserire un ritardo (sleep) con valore casuale da 1 a 10 secondi sia prima sia dopo aver sbloccato il file e&lt;br /&gt;
stampe di controllo che indichino quando il file viene bloccato e sbloccato.&lt;br /&gt;
In questo modo lanciando piu’ esecuzioni concorrenti con output sullo stesso file deve apparire che l’accesso in&lt;br /&gt;
scrittura e’ mutualmente esclusivo.&lt;br /&gt;
Es. di output:&lt;br /&gt;
$ cplk cplk.c out&lt;br /&gt;
locked attende da 1 a 10 sec&lt;br /&gt;
unlocked attende da 1 a 10 sec&lt;br /&gt;
$&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
===Soluzione di FedericoB===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define _GNU_SOURCE&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/sendfile.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;fcntl.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/stat.h&amp;gt;&lt;br /&gt;
#include &amp;lt;time.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char* argv[]) {&lt;br /&gt;
    if (argc == 3) {&lt;br /&gt;
        //get file descriptors&lt;br /&gt;
        int fdFile2 = open(argv[2], O_WRONLY);&lt;br /&gt;
        int fdFile1 = open(argv[1], O_RDONLY);&lt;br /&gt;
        //create structure for file locking&lt;br /&gt;
        struct flock flock;&lt;br /&gt;
        struct stat stat_buf;&lt;br /&gt;
        fstat(fdFile1, &amp;amp;stat_buf);&lt;br /&gt;
        //type = write lock&lt;br /&gt;
        flock.l_type = F_WRLCK;&lt;br /&gt;
        flock.l_start = 0;&lt;br /&gt;
        //set l_start relative of beginning of file&lt;br /&gt;
        flock.l_whence = SEEK_SET;&lt;br /&gt;
        flock.l_len = stat_buf.st_size;&lt;br /&gt;
        flock.l_pid = getpid();&lt;br /&gt;
        fcntl(fdFile2, F_SETLKW, &amp;amp;flock);&lt;br /&gt;
        //print &amp;quot;locked&amp;quot;&lt;br /&gt;
        printf(&amp;quot;locked\n&amp;quot;);&lt;br /&gt;
        //use sendfile for copy, use fdFile1 offset and copy all file 1&lt;br /&gt;
        sendfile(fdFile2, fdFile1, NULL, stat_buf.st_size);&lt;br /&gt;
        //wait for a random time between 1 and 10 seconds&lt;br /&gt;
        srand(time(NULL));&lt;br /&gt;
        int r = rand() % 10 + 1;&lt;br /&gt;
        sleep(r);&lt;br /&gt;
        //unclock second file&lt;br /&gt;
        flock.l_type = F_UNLCK;&lt;br /&gt;
        fcntl(fdFile2, F_SETLKW, &amp;amp;flock);&lt;br /&gt;
        //print &amp;quot;unlocked&amp;quot;&lt;br /&gt;
        printf(&amp;quot;unlocked\n&amp;quot;);&lt;br /&gt;
        //wait for a random time between 1 and 10 second&lt;br /&gt;
        r = rand() % 10 + 1;&lt;br /&gt;
        sleep(r);&lt;br /&gt;
        return 0;&lt;br /&gt;
    } else {&lt;br /&gt;
        printf(&amp;quot;wrong number of arguments!&amp;quot;);&lt;br /&gt;
        return -1;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
==Esercizio 2 ==&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
==Esercizio 3==&lt;br /&gt;
===Bash===&lt;br /&gt;
====Soluzione di G.C. ====&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
&lt;br /&gt;
if [ $# -lt 1 ] ; then&lt;br /&gt;
	echo &amp;quot;Argument error&amp;quot;&lt;br /&gt;
	exit&lt;br /&gt;
fi&lt;br /&gt;
a=0&lt;br /&gt;
find $1 -type f,p,d,c,b,s | (while read line&lt;br /&gt;
do&lt;br /&gt;
	a=$((a+1))&lt;br /&gt;
done&lt;br /&gt;
&lt;br /&gt;
echo &amp;quot;Number: $a&amp;quot;)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
===Python3===&lt;br /&gt;
====Soluzione di G.C. ====&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import sys&lt;br /&gt;
import os&lt;br /&gt;
&lt;br /&gt;
def countFile(d):&lt;br /&gt;
	count = 1&lt;br /&gt;
	for x in os.listdir(d):&lt;br /&gt;
		if os.path.isdir(os.path.join(d,x)):&lt;br /&gt;
			count += countFile(os.path.join(d,x))&lt;br /&gt;
		else:&lt;br /&gt;
			if not os.path.islink(os.path.join(d,x)):&lt;br /&gt;
				count+=1&lt;br /&gt;
	return count&lt;br /&gt;
&lt;br /&gt;
if __name__ == '__main__':&lt;br /&gt;
	if len(sys.argv) &amp;lt; 2:&lt;br /&gt;
		print(&amp;quot;Argument Error&amp;quot;)&lt;br /&gt;
		sys.exit()&lt;br /&gt;
	directory = sys.argv[1]&lt;br /&gt;
	count = countFile(directory)&lt;br /&gt;
	print(&amp;quot;Count: &amp;quot;,count)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>GabrieleCalarota</name></author>
	</entry>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=Prova_pratica_2016.09.13&amp;diff=1885</id>
		<title>Prova pratica 2016.09.13</title>
		<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php?title=Prova_pratica_2016.09.13&amp;diff=1885"/>
		<updated>2017-05-17T09:39:43Z</updated>

		<summary type="html">&lt;p&gt;GabrieleCalarota: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[http://www.cs.unibo.it/~renzo/so/pratiche/2016.09.13.pdf Link al testo] (è sbagliata la data nel titolo ma il testo è quello giusto)&lt;br /&gt;
==Esercizio 1==&lt;br /&gt;
&amp;lt;source lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
Scrivere un programma che mostri il funzionamento del file locking.&lt;br /&gt;
In particolare il programma cplk avra’ due argomenti che I pathname di due file. Il contenuto del primo file deve&lt;br /&gt;
essere copiato nel secondo usando la system call sendfile.&lt;br /&gt;
Prima di iniziare la copia occorre usare la system call fcntl per bloccare il file di output (write lock).&lt;br /&gt;
Completata la copia occorre chiamare nuovamente la fcntl per sbloccare il file.&lt;br /&gt;
Inserire un ritardo (sleep) con valore casuale da 1 a 10 secondi sia prima sia dopo aver sbloccato il file e&lt;br /&gt;
stampe di controllo che indichino quando il file viene bloccato e sbloccato.&lt;br /&gt;
In questo modo lanciando piu’ esecuzioni concorrenti con output sullo stesso file deve apparire che l’accesso in&lt;br /&gt;
scrittura e’ mutualmente esclusivo.&lt;br /&gt;
Es. di output:&lt;br /&gt;
$ cplk cplk.c out&lt;br /&gt;
locked attende da 1 a 10 sec&lt;br /&gt;
unlocked attende da 1 a 10 sec&lt;br /&gt;
$&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
===Soluzione di FedericoB===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define _GNU_SOURCE&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/sendfile.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;fcntl.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/stat.h&amp;gt;&lt;br /&gt;
#include &amp;lt;time.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char* argv[]) {&lt;br /&gt;
    if (argc == 3) {&lt;br /&gt;
        //get file descriptors&lt;br /&gt;
        int fdFile2 = open(argv[2], O_WRONLY);&lt;br /&gt;
        int fdFile1 = open(argv[1], O_RDONLY);&lt;br /&gt;
        //create structure for file locking&lt;br /&gt;
        struct flock flock;&lt;br /&gt;
        struct stat stat_buf;&lt;br /&gt;
        fstat(fdFile1, &amp;amp;stat_buf);&lt;br /&gt;
        //type = write lock&lt;br /&gt;
        flock.l_type = F_WRLCK;&lt;br /&gt;
        flock.l_start = 0;&lt;br /&gt;
        //set l_start relative of beginning of file&lt;br /&gt;
        flock.l_whence = SEEK_SET;&lt;br /&gt;
        flock.l_len = stat_buf.st_size;&lt;br /&gt;
        flock.l_pid = getpid();&lt;br /&gt;
        fcntl(fdFile2, F_SETLKW, &amp;amp;flock);&lt;br /&gt;
        //print &amp;quot;locked&amp;quot;&lt;br /&gt;
        printf(&amp;quot;locked\n&amp;quot;);&lt;br /&gt;
        //use sendfile for copy, use fdFile1 offset and copy all file 1&lt;br /&gt;
        sendfile(fdFile2, fdFile1, NULL, stat_buf.st_size);&lt;br /&gt;
        //wait for a random time between 1 and 10 seconds&lt;br /&gt;
        srand(time(NULL));&lt;br /&gt;
        int r = rand() % 10 + 1;&lt;br /&gt;
        sleep(r);&lt;br /&gt;
        //unclock second file&lt;br /&gt;
        flock.l_type = F_UNLCK;&lt;br /&gt;
        fcntl(fdFile2, F_SETLKW, &amp;amp;flock);&lt;br /&gt;
        //print &amp;quot;unlocked&amp;quot;&lt;br /&gt;
        printf(&amp;quot;unlocked\n&amp;quot;);&lt;br /&gt;
        //wait for a random time between 1 and 10 second&lt;br /&gt;
        r = rand() % 10 + 1;&lt;br /&gt;
        sleep(r);&lt;br /&gt;
        return 0;&lt;br /&gt;
    } else {&lt;br /&gt;
        printf(&amp;quot;wrong number of arguments!&amp;quot;);&lt;br /&gt;
        return -1;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
==Esercizio 2 ==&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
==Esercizio 3==&lt;br /&gt;
===Bash===&lt;br /&gt;
====Soluzione di G.C. ====&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
&lt;br /&gt;
if [ $# -lt 1 ] ; then&lt;br /&gt;
	echo &amp;quot;Argument error&amp;quot;&lt;br /&gt;
	exit&lt;br /&gt;
fi&lt;br /&gt;
a=0&lt;br /&gt;
find $1 -type f,p,d,c,b,s | (while read line&lt;br /&gt;
do&lt;br /&gt;
	a=$((a+1))&lt;br /&gt;
done&lt;br /&gt;
&lt;br /&gt;
echo &amp;quot;Number: $a&amp;quot;)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
===Python3===&lt;br /&gt;
====Soluzione di G.C. ====&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import sys&lt;br /&gt;
import os&lt;br /&gt;
&lt;br /&gt;
def countFile(d):&lt;br /&gt;
	count = 1&lt;br /&gt;
	for x in os.listdir(d):&lt;br /&gt;
		if os.path.isdir(os.path.join(d,x)):&lt;br /&gt;
			count += countFile(os.path.join(d,x))&lt;br /&gt;
		else:&lt;br /&gt;
			if not os.path.islink(os.path.join(d,x)):&lt;br /&gt;
				count+=1&lt;br /&gt;
	return count&lt;br /&gt;
&lt;br /&gt;
if __name__ == '__main__':&lt;br /&gt;
	if len(sys.argv) &amp;lt; 2:&lt;br /&gt;
		print(&amp;quot;Argument Error&amp;quot;)&lt;br /&gt;
		sys.exit()&lt;br /&gt;
	directory = sys.argv[1]&lt;br /&gt;
	count = countFile(directory)&lt;br /&gt;
	print(&amp;quot;Count: &amp;quot;,count)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
--[[User:GabrieleCalarota|GabrieleCalarota]] ([[User talk:GabrieleCalarota|talk]]) 11:39, 17 May 2017 (CEST)&lt;/div&gt;</summary>
		<author><name>GabrieleCalarota</name></author>
	</entry>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=Prova_pratica_2016.05.31&amp;diff=1879</id>
		<title>Prova pratica 2016.05.31</title>
		<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php?title=Prova_pratica_2016.05.31&amp;diff=1879"/>
		<updated>2017-05-16T08:22:53Z</updated>

		<summary type="html">&lt;p&gt;GabrieleCalarota: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[http://www.cs.unibo.it/~renzo/so/pratiche/2016.05.31.pdf Link al testo]&lt;br /&gt;
&lt;br /&gt;
==Esercizio 1==&lt;br /&gt;
&amp;lt;source lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
Scrivere un programma che preso come parametro a linea comando il path di una directory elenchi solamente I file&lt;br /&gt;
che hanno un nome che ha come suffisso un numero (es. Prova.10). I file devono essere ordinati in ordine&lt;br /&gt;
numerico.&lt;br /&gt;
Esempio se la directory &lt;br /&gt;
test contiene I file prova5, giovanni, aaa.1000, bb.2000, ccc.dd.500 l'output del programma deve essere:&lt;br /&gt;
ccc.dd.500&lt;br /&gt;
aaa.1000&lt;br /&gt;
bb.2000&lt;br /&gt;
(in quanto 500 numericamente e' minore di 1000, prova5 non si considera: manca il punto prima del numero).&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
=== Soluzione di Alexp ===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;string.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;dirent.h&amp;gt;&lt;br /&gt;
#include &amp;lt;ctype.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdint.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/stat.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
Assumes that filename contains a digit in the suffix&lt;br /&gt;
*/&lt;br /&gt;
uint64_t getSuffixNumber(const char* filename){&lt;br /&gt;
    size_t len = strlen(filename)-1;&lt;br /&gt;
    size_t pos = len;&lt;br /&gt;
    uint64_t number = 0;&lt;br /&gt;
    uint64_t decimal = 1;&lt;br /&gt;
    //while there are digits to read&lt;br /&gt;
    while(pos&amp;gt;=0 &amp;amp;&amp;amp; isdigit(filename[pos])){&lt;br /&gt;
        //number+=digit converted to int, multiplied by decimal position&lt;br /&gt;
        number+=(filename[pos] - '0')*decimal;&lt;br /&gt;
        decimal*=10;&lt;br /&gt;
        pos--;&lt;br /&gt;
    }&lt;br /&gt;
    return number;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
Returns 1 if the given filename ends with a number, 0 otherwise&lt;br /&gt;
*/&lt;br /&gt;
int endsWithNumber(const char* filename){&lt;br /&gt;
    size_t len = strlen(filename)-1;&lt;br /&gt;
    size_t pos = len;&lt;br /&gt;
    //stating from last character, go backwards until there are digits&lt;br /&gt;
    while(pos&amp;gt;=0 &amp;amp;&amp;amp; isdigit(filename[pos])) pos--;&lt;br /&gt;
    //if the suffix is actually a number, preceeded by a '.'&lt;br /&gt;
    if(pos&amp;gt;=0 &amp;amp;&amp;amp; pos != len &amp;amp;&amp;amp; filename[pos] == '.') return 1;&lt;br /&gt;
    else return 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int sortbysuffix(const struct dirent **e1, const struct dirent **e2) {&lt;br /&gt;
    const char *a = (*e1)-&amp;gt;d_name;&lt;br /&gt;
    const char *b = (*e2)-&amp;gt;d_name;&lt;br /&gt;
    uint64_t suffixA = getSuffixNumber(a);&lt;br /&gt;
    uint64_t suffixB = getSuffixNumber(b);&lt;br /&gt;
    //compare two suffixes&lt;br /&gt;
    return suffixA &amp;lt; suffixB;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int filter(const struct dirent* ent){&lt;br /&gt;
    //exclude &amp;quot;.&amp;quot; and &amp;quot;..&amp;quot; and files not ending with a &amp;quot;.(number)+&amp;quot;&lt;br /&gt;
    if(strcmp(ent-&amp;gt;d_name,&amp;quot;.&amp;quot;) &amp;amp;&amp;amp; strcmp(ent-&amp;gt;d_name,&amp;quot;..&amp;quot;) &amp;amp;&amp;amp; endsWithNumber(ent-&amp;gt;d_name)){&lt;br /&gt;
        return 1;&lt;br /&gt;
    }&lt;br /&gt;
    else return 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void printFilenames(char* path){&lt;br /&gt;
    struct dirent **namelist;&lt;br /&gt;
    int n;&lt;br /&gt;
    n = scandir(path, &amp;amp;namelist, filter, sortbysuffix);&lt;br /&gt;
    if (n &amp;lt; 0)&lt;br /&gt;
        perror(&amp;quot;scandir&amp;quot;);&lt;br /&gt;
    else {&lt;br /&gt;
        while (n--) {&lt;br /&gt;
            printf(&amp;quot;%s\n&amp;quot;, namelist[n]-&amp;gt;d_name);&lt;br /&gt;
            free(namelist[n]);&lt;br /&gt;
        }&lt;br /&gt;
        free(namelist);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int isDirectory(const char *path) {&lt;br /&gt;
    struct stat statbuf;&lt;br /&gt;
    //if unable to get file status&lt;br /&gt;
    if (stat(path, &amp;amp;statbuf) != 0) return 0;&lt;br /&gt;
    //otherwise if we got the file status, check if it's a directory&lt;br /&gt;
    return S_ISDIR(statbuf.st_mode);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char* argv[]){&lt;br /&gt;
    if(argc == 2 &amp;amp;&amp;amp; isDirectory(argv[1])){&lt;br /&gt;
        printFilenames(argv[1]);&lt;br /&gt;
    }&lt;br /&gt;
    else{&lt;br /&gt;
        printf(&amp;quot;Error, input a directory name.\n&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Esercizio 2==&lt;br /&gt;
&amp;lt;source lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
Come nell'esercizio 1 occorre cercare in una directory (passata come parametro) I file che hanno come suffisso un&lt;br /&gt;
numero. Nell'esercizio 2 I file sono eseguibili e l numero indica il numero di millisecondi da attendere a partire dalla attivazione del programma prima di attivarli.&lt;br /&gt;
Nell'esempio dell'esercizio precedente occorre aspettare mezzo secondo e lanciare ccc.dd.500, poi a 1 secondo&lt;br /&gt;
dall'attivazione (cioe' dopo approssimativamente ulteriori 0.5 secondi) si lancia aaa.1000 e allo scadere del&lt;br /&gt;
secondo secondo bbb.2000.&lt;br /&gt;
I file eseguibili nella directory vengono eseguiti in background (non si attende la fine dell'esecuzione per&lt;br /&gt;
continuare). Quindi se due file hanno lo stesso prefisso numerico vengono eseguiti in modo concorrente.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
=== Soluzione di Alexp ===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;string.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;dirent.h&amp;gt;&lt;br /&gt;
#include &amp;lt;ctype.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdint.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/stat.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/wait.h&amp;gt;&lt;br /&gt;
#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
Assumes that filename contains a digit in the suffix&lt;br /&gt;
*/&lt;br /&gt;
uint64_t getSuffixNumber(const char* filename){&lt;br /&gt;
    size_t len = strlen(filename)-1;&lt;br /&gt;
    size_t pos = len;&lt;br /&gt;
    uint64_t number = 0;&lt;br /&gt;
    uint64_t decimal = 1;&lt;br /&gt;
    //while there are digits to read&lt;br /&gt;
    while(pos&amp;gt;=0 &amp;amp;&amp;amp; isdigit(filename[pos])){&lt;br /&gt;
        //number+=digit converted to int, multiplied by decimal position&lt;br /&gt;
        number+=(filename[pos] - '0')*decimal;&lt;br /&gt;
        decimal*=10;&lt;br /&gt;
        pos--;&lt;br /&gt;
    }&lt;br /&gt;
    return number;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int endsWithNumber(const char* filename){&lt;br /&gt;
    size_t len = strlen(filename)-1;&lt;br /&gt;
    size_t pos = len;&lt;br /&gt;
    //stating from last character, go backwards until there are digits&lt;br /&gt;
    while(pos&amp;gt;=0 &amp;amp;&amp;amp; isdigit(filename[pos])) pos--;&lt;br /&gt;
    //if the suffix is actually a number, preceeded by a '.'&lt;br /&gt;
    if(pos&amp;gt;=0 &amp;amp;&amp;amp; pos != len &amp;amp;&amp;amp; filename[pos] == '.') return 1;&lt;br /&gt;
    else return 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int sortbysuffix(const struct dirent **e1, const struct dirent **e2) {&lt;br /&gt;
    const char *a = (*e1)-&amp;gt;d_name;&lt;br /&gt;
    const char *b = (*e2)-&amp;gt;d_name;&lt;br /&gt;
    uint64_t suffixA = getSuffixNumber(a);&lt;br /&gt;
    uint64_t suffixB = getSuffixNumber(b);&lt;br /&gt;
    //compare two suffixes&lt;br /&gt;
    return suffixA &amp;lt; suffixB;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
Returns 1 if the file is an executable file, 0 otherwise&lt;br /&gt;
*/&lt;br /&gt;
int isExecutable(const char* path){&lt;br /&gt;
    struct stat buf;&lt;br /&gt;
    //if unable to get file status&lt;br /&gt;
    if (stat(path, &amp;amp;buf) != 0) return 0;&lt;br /&gt;
    //if the file is executable by user&lt;br /&gt;
    if (buf.st_mode &amp;amp; S_IXUSR) return 1;&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int filter(const struct dirent* ent){&lt;br /&gt;
    //exclude &amp;quot;.&amp;quot; and &amp;quot;..&amp;quot; and files not ending with a &amp;quot;.(number)+&amp;quot;&lt;br /&gt;
    if(strcmp(ent-&amp;gt;d_name,&amp;quot;.&amp;quot;) &amp;amp;&amp;amp; strcmp(ent-&amp;gt;d_name,&amp;quot;..&amp;quot;) &amp;amp;&amp;amp; endsWithNumber(ent-&amp;gt;d_name)){&lt;br /&gt;
        return 1;&lt;br /&gt;
    }&lt;br /&gt;
    else return 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void runExecutables(char* path){&lt;br /&gt;
    struct dirent **namelist;&lt;br /&gt;
    int n;&lt;br /&gt;
    //delay time in ms&lt;br /&gt;
    uint64_t waitingMS;&lt;br /&gt;
    char* fullpath;&lt;br /&gt;
    //forked child's pid&lt;br /&gt;
    pid_t pid;&lt;br /&gt;
    //used to wait all the children&lt;br /&gt;
    int status = 0;&lt;br /&gt;
    n = scandir(path, &amp;amp;namelist, filter, sortbysuffix);&lt;br /&gt;
    if (n &amp;lt; 0) perror(&amp;quot;scandir&amp;quot;);&lt;br /&gt;
    else {&lt;br /&gt;
        while (n--) {&lt;br /&gt;
            waitingMS = getSuffixNumber(namelist[n]-&amp;gt;d_name);&lt;br /&gt;
            //get the full dirname+filename path&lt;br /&gt;
            asprintf(&amp;amp;fullpath, &amp;quot;%s%s&amp;quot;, path, namelist[n]-&amp;gt;d_name);&lt;br /&gt;
            if(isExecutable(fullpath)){&lt;br /&gt;
                printf(&amp;quot;Calling %s\n&amp;quot;,fullpath);&lt;br /&gt;
                if( pid != fork() ){&lt;br /&gt;
                    //child&lt;br /&gt;
                    //wait for the required time(in microseconds)&lt;br /&gt;
          	    usleep(waitingMS*1000);&lt;br /&gt;
                    char *args[] = {fullpath,(char *)0};&lt;br /&gt;
                    printf(&amp;quot;Starting%s\n&amp;quot;, args[0]);&lt;br /&gt;
                    execvp(fullpath,args);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            free(fullpath);&lt;br /&gt;
            free(namelist[n]);&lt;br /&gt;
        }&lt;br /&gt;
        //wait till all the children terminate&lt;br /&gt;
        while ((pid = wait(&amp;amp;status)) &amp;gt; 0); &lt;br /&gt;
        free(namelist);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int isDirectory(const char *path) {&lt;br /&gt;
    struct stat statbuf;&lt;br /&gt;
    //if unable to get file status&lt;br /&gt;
    if (stat(path, &amp;amp;statbuf) != 0) return 0;&lt;br /&gt;
    //otherwise if we got the file status, check if it's a directory&lt;br /&gt;
    return S_ISDIR(statbuf.st_mode);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char* argv[]){&lt;br /&gt;
    if(argc == 2 &amp;amp;&amp;amp; isDirectory(argv[1])){&lt;br /&gt;
        runExecutables(argv[1]);&lt;br /&gt;
    }&lt;br /&gt;
    else{&lt;br /&gt;
        printf(&amp;quot;Error, input a directory name.\n&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
==Esercizio 3==&lt;br /&gt;
===Bash===&lt;br /&gt;
====Soluzione di G.C.====&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
&lt;br /&gt;
if [ $# -lt 1 ] ; then&lt;br /&gt;
	echo &amp;quot;Argument error&amp;quot;&lt;br /&gt;
	exit	&lt;br /&gt;
fi&lt;br /&gt;
tmp_file=file_tmp&lt;br /&gt;
touch $tmp_file&lt;br /&gt;
find $1 -type f | xargs basename -a | while read line&lt;br /&gt;
do&lt;br /&gt;
	#$line contains file name&lt;br /&gt;
	extension=&amp;quot;${line##*.}&amp;quot;&lt;br /&gt;
	#suffix contains only digits&lt;br /&gt;
	if [[ $extension =~ ^[0-9]+$ ]]&lt;br /&gt;
	then&lt;br /&gt;
	 	echo &amp;quot;$line:$extension&amp;quot; &amp;gt;&amp;gt; $tmp_file &lt;br /&gt;
	fi&lt;br /&gt;
done&lt;br /&gt;
&lt;br /&gt;
#sort by second column&lt;br /&gt;
tmp1_file=tmp1_file&lt;br /&gt;
cat $tmp_file | sort -t':' -nk2 &amp;gt; $tmp1_file&lt;br /&gt;
count=0&lt;br /&gt;
awk -F: '{print $1, $2}' $tmp1_file | while read line&lt;br /&gt;
do&lt;br /&gt;
	lineCols=( $line )&lt;br /&gt;
	#execute the first column in bg&lt;br /&gt;
	$1/${lineCols[0]} &amp;amp;&lt;br /&gt;
	#calculate the delay time from the last exec&lt;br /&gt;
	res=$((${lineCols[1]}-$count))&lt;br /&gt;
	count=${lineCols[1]}&lt;br /&gt;
	sleep $(($res / 1000))&lt;br /&gt;
done&lt;br /&gt;
rm $tmp_file $tmp1_file&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
===Python3===&lt;br /&gt;
====Soluzione di G.C.====&lt;br /&gt;
&amp;lt;source lang=&amp;quot;Python&amp;quot;&amp;gt;&lt;br /&gt;
import sys&lt;br /&gt;
import os&lt;br /&gt;
import time&lt;br /&gt;
import subprocess&lt;br /&gt;
&lt;br /&gt;
def getListOfFileAndTiming(d):&lt;br /&gt;
	listOfFile = [f for f in os.listdir(d) if os.path.isfile(os.path.join(d,f))]&lt;br /&gt;
	l = []&lt;br /&gt;
	for x in listOfFile:&lt;br /&gt;
		s = x.split('.')&lt;br /&gt;
		if s[0] != s[-1] and s[-1].isdigit():&lt;br /&gt;
			l.append((os.path.join(d,x),int(s[-1])))	&lt;br /&gt;
	return l&lt;br /&gt;
&lt;br /&gt;
def sleepAndExecute(l):&lt;br /&gt;
	l = sorted(l, key=lambda x:x[1])&lt;br /&gt;
	for x in l:&lt;br /&gt;
		print('starting %s '% (x[0]))&lt;br /&gt;
		subprocess.Popen([x[0]])&lt;br /&gt;
		print('sleeping %f s' % (x[1]/1000))&lt;br /&gt;
		time.sleep(x[1]/1000)&lt;br /&gt;
&lt;br /&gt;
if __name__ == '__main__':	&lt;br /&gt;
	try:&lt;br /&gt;
		if len(sys.argv) &amp;lt; 2:&lt;br /&gt;
			raise Exception(&amp;quot;Argument ERROR: input a directory&amp;quot;)&lt;br /&gt;
		directory = sys.argv[1]&lt;br /&gt;
		l = getListOfFileAndTiming(directory)&lt;br /&gt;
		sleepAndExecute(l)&lt;br /&gt;
	except Exception as inst:&lt;br /&gt;
		print(inst.args)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>GabrieleCalarota</name></author>
	</entry>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=Prova_pratica_2017.01.17&amp;diff=1877</id>
		<title>Prova pratica 2017.01.17</title>
		<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php?title=Prova_pratica_2017.01.17&amp;diff=1877"/>
		<updated>2017-05-15T10:17:20Z</updated>

		<summary type="html">&lt;p&gt;GabrieleCalarota: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Esercizio1==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;dirent.h&amp;gt;&lt;br /&gt;
#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/types.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/stat.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
struct fileelem {&lt;br /&gt;
	dev_t dev; &lt;br /&gt;
	ino_t ino;&lt;br /&gt;
	struct fileelem *next;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
int addfile(struct fileelem **head, dev_t dev, ino_t ino) {&lt;br /&gt;
	if (*head == NULL) {&lt;br /&gt;
		*head = malloc(sizeof(struct fileelem));&lt;br /&gt;
		(*head)-&amp;gt;dev = dev;&lt;br /&gt;
		(*head)-&amp;gt;ino = ino;&lt;br /&gt;
		(*head)-&amp;gt;next = NULL;&lt;br /&gt;
		return 1;&lt;br /&gt;
	} else if ((*head)-&amp;gt;dev == dev &amp;amp;&amp;amp; (*head)-&amp;gt;ino == ino) {&lt;br /&gt;
		return 0;&lt;br /&gt;
	} else {&lt;br /&gt;
		return addfile(&amp;amp;((*head)-&amp;gt;next), dev, ino);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int filt(const struct dirent *elem) {&lt;br /&gt;
	if (strcmp(elem-&amp;gt;d_name,&amp;quot;.&amp;quot;) == 0 ||&lt;br /&gt;
			strcmp(elem-&amp;gt;d_name,&amp;quot;..&amp;quot;) == 0)&lt;br /&gt;
		return 0;&lt;br /&gt;
	else {&lt;br /&gt;
		return 1;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int recscan(char *path, struct fileelem **head) {&lt;br /&gt;
	struct dirent **list;&lt;br /&gt;
	int count = 0;&lt;br /&gt;
	int n = scandir(path, &amp;amp;list, filt, alphasort);&lt;br /&gt;
	int i;&lt;br /&gt;
	for (i = 0; i &amp;lt; n; i++) {&lt;br /&gt;
		struct stat buf;&lt;br /&gt;
		char *filepath;&lt;br /&gt;
		asprintf(&amp;amp;filepath,&amp;quot;%s/%s&amp;quot;,path,list[i]-&amp;gt;d_name);&lt;br /&gt;
		stat(filepath, &amp;amp;buf);&lt;br /&gt;
		switch (buf.st_mode &amp;amp; S_IFMT) {&lt;br /&gt;
			case S_IFREG:&lt;br /&gt;
				count += addfile(head, buf.st_dev, buf.st_ino);&lt;br /&gt;
				printf(&amp;quot;file %s %ld %ld ... %d\n&amp;quot;,filepath,buf.st_dev,buf.st_ino,count);&lt;br /&gt;
				break;&lt;br /&gt;
			case S_IFDIR:&lt;br /&gt;
				count = count + recscan(filepath, head);&lt;br /&gt;
				break;&lt;br /&gt;
		}&lt;br /&gt;
		free(filepath);&lt;br /&gt;
		free(list[i]);&lt;br /&gt;
	}&lt;br /&gt;
	free(list);&lt;br /&gt;
	return count;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char *argv[]) {&lt;br /&gt;
	struct fileelem *head = NULL;&lt;br /&gt;
	int result;&lt;br /&gt;
	if (argc &amp;gt; 1)&lt;br /&gt;
		chdir(argv[1]);&lt;br /&gt;
	result = recscan(&amp;quot;.&amp;quot;, &amp;amp;head);&lt;br /&gt;
	printf(&amp;quot;Num of independent files: %d\n&amp;quot;, result);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Esercizio 3:==&lt;br /&gt;
===Python===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=Python&amp;gt;&lt;br /&gt;
def merge():  # dati due path di due directory, fa la merge in una terza directory&lt;br /&gt;
    # 1=pathprimo 2=pathsecondo 3=pathdestinazione&lt;br /&gt;
    if (len(sys.argv) &amp;gt; 3):&lt;br /&gt;
        for d, _, fl in os.walk(sys.argv[1]):&lt;br /&gt;
            for f in fl:&lt;br /&gt;
                path = os.path.join(d, f)&lt;br /&gt;
                if (os.path.isfile(path)):  # e' un file e non una directory allora copio tutto&lt;br /&gt;
                    shutil.copy2(path, sys.argv[3])&lt;br /&gt;
        for d, _, fl in os.walk(sys.argv[2]):&lt;br /&gt;
            for f in fl:&lt;br /&gt;
                path = os.path.join(d, f)&lt;br /&gt;
                if (os.path.isfile(path)):  # e' un file e non una directory in path2&lt;br /&gt;
                    esistenza = os.path.join(sys.argv[3], f)&lt;br /&gt;
                    if (not os.path.isfile(esistenza)):  # se non esiste un file con quel nome&lt;br /&gt;
                        shutil.copy2(path, sys.argv[3])&lt;br /&gt;
                    else:&lt;br /&gt;
                        if (os.stat(path).st_mtime &amp;gt; os.stat(&lt;br /&gt;
                                esistenza).st_mtime):  # e' piu recente tempo del file in path2 rispetto a path3&lt;br /&gt;
                            shutil.copy2(path, sys.argv[3])&lt;br /&gt;
    else:&lt;br /&gt;
        print(&amp;quot;Mancano degli argomenti&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Bash===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=Bash&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
&lt;br /&gt;
if [ $# -lt 3 ] ; then&lt;br /&gt;
	echo &amp;quot;ERROR: example merge a b c&amp;quot;&lt;br /&gt;
	exit 1&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
a=$1&lt;br /&gt;
b=$2&lt;br /&gt;
c=$3&lt;br /&gt;
tmp_file=file_tmp&lt;br /&gt;
&lt;br /&gt;
touch $tmp_file&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
find $a -type f -print0 | xargs -0 basename -a &amp;gt;&amp;gt; $tmp_file&lt;br /&gt;
find $b -type f -print0 | xargs -0 basename -a &amp;gt;&amp;gt; $tmp_file&lt;br /&gt;
&lt;br /&gt;
#univoci&lt;br /&gt;
#echo &amp;quot;UNIQ&amp;quot;&lt;br /&gt;
sort $tmp_file | uniq -u | while read line&lt;br /&gt;
do&lt;br /&gt;
	&lt;br /&gt;
	#now $line contains the basename of the file&lt;br /&gt;
	ls &amp;quot;$a/$line&amp;quot; &amp;amp;&amp;gt;/dev/null &amp;amp;&amp;amp; mv -v &amp;quot;$a/$line&amp;quot; &amp;quot;$c/$line&amp;quot;&lt;br /&gt;
	ls &amp;quot;$b/$line&amp;quot; &amp;amp;&amp;gt;/dev/null &amp;amp;&amp;amp; mv -v &amp;quot;$b/$line&amp;quot; &amp;quot;$c/$line&amp;quot;&lt;br /&gt;
done&lt;br /&gt;
&lt;br /&gt;
#echo &amp;quot;DOUBLE&amp;quot;&lt;br /&gt;
sort $tmp_file | uniq -d | while read line&lt;br /&gt;
do&lt;br /&gt;
	#now $line contains the basename of both of the filename&lt;br /&gt;
	file1=&amp;quot;$(stat -c %Y $a/$line)&amp;quot;&lt;br /&gt;
	file2=&amp;quot;$(stat -c %Y $b/$line)&amp;quot;&lt;br /&gt;
	if [ $file1 -lt $file2 ] ; then&lt;br /&gt;
		#echo &amp;quot;$line chose from $b&amp;quot;&lt;br /&gt;
		mv -v &amp;quot;$b/$line&amp;quot; &amp;quot;$c/$line&amp;quot;&lt;br /&gt;
	else&lt;br /&gt;
		#echo &amp;quot;$line chose from $a&amp;quot;&lt;br /&gt;
		mv -v &amp;quot;$a/$line&amp;quot; &amp;quot;$c/$line&amp;quot;&lt;br /&gt;
	fi&lt;br /&gt;
done&lt;br /&gt;
&lt;br /&gt;
rm $tmp_file  &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
--[[User:GabrieleCalarota|GabrieleCalarota]] ([[User talk:GabrieleCalarota|talk]]) 12:17, 15 May 2017 (CEST)&lt;/div&gt;</summary>
		<author><name>GabrieleCalarota</name></author>
	</entry>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=Prova_pratica_2015.05.20&amp;diff=1874</id>
		<title>Prova pratica 2015.05.20</title>
		<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php?title=Prova_pratica_2015.05.20&amp;diff=1874"/>
		<updated>2017-05-13T08:26:57Z</updated>

		<summary type="html">&lt;p&gt;GabrieleCalarota: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[http://www.cs.unibo.it/~renzo/so/pratiche/2015.05.29.pdf Link al testo]&lt;br /&gt;
&lt;br /&gt;
==Esercizio 1==&lt;br /&gt;
&amp;lt;source lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
Scrivere un programma catsig che copi lo standard input nello standard output (come il comando cat senza&lt;br /&gt;
parametri, per intenderci) e che stampi la scritta “ho ricevuto un segnale” quando riceve un segnale SIGUSR1.&lt;br /&gt;
La particolarita' di questo programma e' che per la gestione dei segnali deve usare la chiamata di sistema&lt;br /&gt;
signalfd (e non la signal o la sigaction)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Soluzione di FedericoB===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/signalfd.h&amp;gt;&lt;br /&gt;
#include &amp;lt;signal.h&amp;gt;&lt;br /&gt;
#include &amp;lt;poll.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char* argv[]) {&lt;br /&gt;
    //declare a mask for signal&lt;br /&gt;
    sigset_t mask;&lt;br /&gt;
    //initialize signal mask&lt;br /&gt;
    sigemptyset(&amp;amp;mask);&lt;br /&gt;
    sigaddset(&amp;amp;mask, SIGUSR1);&lt;br /&gt;
    //create a file descriptor for signal USR1&lt;br /&gt;
    int signalFileDescriptor = signalfd(-1, &amp;amp;mask, 0);&lt;br /&gt;
    //remove default handler for SIGURS1&lt;br /&gt;
    sigprocmask(SIG_BLOCK, &amp;amp;mask, NULL);&lt;br /&gt;
    struct pollfd pollstruct[2];&lt;br /&gt;
    pollstruct[0].fd = signalFileDescriptor;&lt;br /&gt;
    pollstruct[0].events = POLLIN;&lt;br /&gt;
    pollstruct[1].fd = STDIN_FILENO;&lt;br /&gt;
    pollstruct[1].events = POLLIN;&lt;br /&gt;
    while (1) {&lt;br /&gt;
        poll(pollstruct, 2, -1);&lt;br /&gt;
        //is signal USR1 is received&lt;br /&gt;
        if (pollstruct[0].revents &amp;amp; POLLIN) {&lt;br /&gt;
            struct signalfd_siginfo siginfo;&lt;br /&gt;
            //read signal information from signal file descriptor&lt;br /&gt;
            read(signalFileDescriptor, &amp;amp;siginfo, sizeof(struct signalfd_siginfo));&lt;br /&gt;
            printf(&amp;quot;ho ricevuto un segnale\n&amp;quot;);&lt;br /&gt;
            //set event as handled&lt;br /&gt;
            pollstruct[0].revents = 0;&lt;br /&gt;
        }&lt;br /&gt;
        //if there is something to read in standard input&lt;br /&gt;
        if (pollstruct[1].revents &amp;amp; POLLIN) {&lt;br /&gt;
            char character;&lt;br /&gt;
            //read one character until there is a character to read&lt;br /&gt;
            while (read(fileno(stdin), &amp;amp;character, 1) &amp;gt; 0) {&lt;br /&gt;
                //print that character to standard output&lt;br /&gt;
                write(fileno(stdout), &amp;amp;character, 1);&lt;br /&gt;
            }&lt;br /&gt;
            //set event as handled&lt;br /&gt;
            pollstruct[1].revents = 0;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Esercizio 2==&lt;br /&gt;
&amp;lt;source lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
Ora, prendendospunto dall'esercizio 1 occorre scrivere due programmi:&lt;br /&gt;
sigsend e sigreceive.&lt;br /&gt;
Sigreceive non ha come parametri. Per prima cosa stampa il suo pid poi entra in un ciclo in cui:&lt;br /&gt;
• aspetta un segnale SIGUSR1&lt;br /&gt;
• stampa su stdout (visualizza) il file con nome /tmp/giroXXXX (dove XXXX e' il proprio pid)&lt;br /&gt;
• cancella il file /tmp/giroXXXX&lt;br /&gt;
• Manda un segnale SIGUSR1 al processo dal quale lo ha ricevuto nella operazione due righe sopra&lt;br /&gt;
questa.&lt;br /&gt;
Sigreceive termina quando riceve in SIGUSR2.&lt;br /&gt;
Sigsend ha come parametro il pid del processo ricevente. Per ogni riga posta in input da stdin fa le seguenti azioni:&lt;br /&gt;
• crea un file /tmp/giroXXXX (dove XXXX e' il pid del processo ricevente), vi scrive la riga letta e lo chiude.&lt;br /&gt;
• Spedisce un segnale SIGUSR1 al ricevente&lt;br /&gt;
• Aspetta dallo stesso un SIGUSR1.&lt;br /&gt;
Quando lo stdin termina (^D da tastiera) manda un SIGUSR2 al ricevente.&lt;br /&gt;
All'attivazione scrive nel file il proprio pid e aspetta un segnale sigusr1.Quando riceve il segnale legge&lt;br /&gt;
Anche in questo esercizio occorre usare solo la signalfd e non la signal o la sigaction.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
===Soluzione di FedericoB===&lt;br /&gt;
sigreceive&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
#define _GNU_SOURCE&lt;br /&gt;
#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/signalfd.h&amp;gt;&lt;br /&gt;
#include &amp;lt;signal.h&amp;gt;&lt;br /&gt;
#include &amp;lt;poll.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char* argv[]) {&lt;br /&gt;
    int pid = getpid();&lt;br /&gt;
    printf(&amp;quot;pid: %d\n&amp;quot;,pid);&lt;br /&gt;
    char* path;&lt;br /&gt;
    //create path with format giroXXXX&lt;br /&gt;
    asprintf(&amp;amp;path, &amp;quot;/tmp/giro%d&amp;quot;, pid);&lt;br /&gt;
    sigset_t mask;&lt;br /&gt;
    //initialize signal mask&lt;br /&gt;
    sigemptyset(&amp;amp;mask);&lt;br /&gt;
    sigaddset(&amp;amp;mask, SIGUSR1);&lt;br /&gt;
    sigaddset(&amp;amp;mask, SIGUSR2);&lt;br /&gt;
    //block default handler for SIGUSR1 and SIGUSR2&lt;br /&gt;
    sigprocmask(SIG_BLOCK, &amp;amp;mask, NULL);&lt;br /&gt;
    int fd;&lt;br /&gt;
    //get a file descript for signal SIGUSR2 and SIGUS2&lt;br /&gt;
    fd = signalfd(-1,&amp;amp;mask,0);&lt;br /&gt;
    //create a poll structur for waiting signal USR1 and USR2&lt;br /&gt;
    struct pollfd polls = {.fd = fd,.events=POLLIN};&lt;br /&gt;
    //bool for checking is a sigsr2 arrived&lt;br /&gt;
    int sigusr2 = 0;&lt;br /&gt;
    while (!sigusr2) {&lt;br /&gt;
        //wait for signal&lt;br /&gt;
        poll(&amp;amp;polls,1,-1);&lt;br /&gt;
        //if a signal arrived&lt;br /&gt;
        if (polls.revents &amp;amp; POLLIN) {&lt;br /&gt;
            struct signalfd_siginfo siginfo;&lt;br /&gt;
            //read signal information from signal file descriptor&lt;br /&gt;
            read(fd, &amp;amp;siginfo, sizeof(struct signalfd_siginfo));&lt;br /&gt;
            if (siginfo.ssi_signo == SIGUSR1) {&lt;br /&gt;
                FILE* file = fopen(path, &amp;quot;r&amp;quot;);&lt;br /&gt;
                if (file!=NULL) {&lt;br /&gt;
                    char* buffer = malloc(50);&lt;br /&gt;
                    //read from file&lt;br /&gt;
                    fgets(buffer, 50, file);&lt;br /&gt;
                    //print to standard output&lt;br /&gt;
                    printf(&amp;quot;%s&amp;quot;, buffer);&lt;br /&gt;
                    free(buffer);&lt;br /&gt;
                    fclose(file);&lt;br /&gt;
                    //remove file&lt;br /&gt;
                    remove(path);&lt;br /&gt;
                    //send a USR2 signal to sender of signal&lt;br /&gt;
                    kill(siginfo.ssi_pid, SIGUSR2);&lt;br /&gt;
                } else {&lt;br /&gt;
                    printf(&amp;quot;Error opening the file %s \n&amp;quot;,path);&lt;br /&gt;
                }&lt;br /&gt;
            } else if (siginfo.ssi_signo == SIGUSR2 ) {&lt;br /&gt;
                sigusr2 = 1;&lt;br /&gt;
            }&lt;br /&gt;
            polls.revents = 0;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
sigsend&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
#define _GNU_SOURCE&lt;br /&gt;
#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/signalfd.h&amp;gt;&lt;br /&gt;
#include &amp;lt;signal.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char* argv[]) {&lt;br /&gt;
    if (argc == 2) {&lt;br /&gt;
        //get pid from program arguments&lt;br /&gt;
        int receiverPid = atoi(argv[1]);&lt;br /&gt;
        char* path;&lt;br /&gt;
        //create path with format giroXXXX&lt;br /&gt;
        asprintf(&amp;amp;path, &amp;quot;/tmp/giro%d&amp;quot;, receiverPid);&lt;br /&gt;
        char* buffer;&lt;br /&gt;
        do {&lt;br /&gt;
            buffer = malloc(200);&lt;br /&gt;
            //read standard input&lt;br /&gt;
            buffer = fgets(buffer, 200, stdin);&lt;br /&gt;
            //fgets return NULL on ^D&lt;br /&gt;
            if (buffer != NULL) {&lt;br /&gt;
                FILE* file = fopen(path, &amp;quot;w&amp;quot;);&lt;br /&gt;
                if (file != NULL) {&lt;br /&gt;
                    fputs(buffer, file);&lt;br /&gt;
                    free(buffer);&lt;br /&gt;
                    fclose(file);&lt;br /&gt;
                    //send signal SIGURS1 to receiver&lt;br /&gt;
                    kill(receiverPid, SIGUSR1);&lt;br /&gt;
                    sigset_t mask;&lt;br /&gt;
                    //initialize signal mask&lt;br /&gt;
                    sigemptyset(&amp;amp;mask);&lt;br /&gt;
                    sigaddset(&amp;amp;mask, SIGUSR2);&lt;br /&gt;
                    //block default handler for SIGUSR2&lt;br /&gt;
                    sigprocmask(SIG_BLOCK, &amp;amp;mask, NULL);&lt;br /&gt;
                    int sig;&lt;br /&gt;
                    //wait for a SIGURS2&lt;br /&gt;
                    sigwait(&amp;amp;mask, &amp;amp;sig);&lt;br /&gt;
                } else {&lt;br /&gt;
                    printf(&amp;quot;Error opening the file %s \n&amp;quot;, path);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        } while (buffer != NULL);&lt;br /&gt;
        //send a SIGUSR2 to receiver&lt;br /&gt;
        kill(receiverPid, SIGUSR2);&lt;br /&gt;
    } else {&lt;br /&gt;
        printf(&amp;quot;Parameters error: pid required\n&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
==Esercizio 3==&lt;br /&gt;
&amp;lt;source lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
===Soluzione di G.C.===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import sys&lt;br /&gt;
import os&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
if __name__ == '__main__':&lt;br /&gt;
	files = [f for f in os.listdir('.') if os.path.isfile(f)]&lt;br /&gt;
	d = {}&lt;br /&gt;
	outputList = []&lt;br /&gt;
	for f in files:&lt;br /&gt;
		#all files&lt;br /&gt;
		try:&lt;br /&gt;
			if f == 'es3.py':&lt;br /&gt;
				raise Exception()&lt;br /&gt;
			with open(f,&amp;quot;r&amp;quot;) as out:&lt;br /&gt;
				lines = out.readlines()&lt;br /&gt;
				i = 0&lt;br /&gt;
				for x in lines:&lt;br /&gt;
					l = x.lstrip()&lt;br /&gt;
					if l in list(d.keys()):&lt;br /&gt;
						e = {}&lt;br /&gt;
						e['content'] = l.strip('\n')&lt;br /&gt;
						e['file'] = f&lt;br /&gt;
						e['numRiga'] = i&lt;br /&gt;
						outputList.append(e)&lt;br /&gt;
					else:&lt;br /&gt;
						d[l] = 1&lt;br /&gt;
					i +=1&lt;br /&gt;
		except:&lt;br /&gt;
			print(&amp;quot;es3.py founded!\n&amp;quot;)&lt;br /&gt;
	for x in outputList:&lt;br /&gt;
		print('Nel file: %s\tAlla riga: %s\tContenuto: %s\n' % (x['file'],x['numRiga'],x['content']))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>GabrieleCalarota</name></author>
	</entry>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=Zibaldone&amp;diff=1715</id>
		<title>Zibaldone</title>
		<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php?title=Zibaldone&amp;diff=1715"/>
		<updated>2016-12-15T15:54:15Z</updated>

		<summary type="html">&lt;p&gt;GabrieleCalarota: /* == */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Monitor: Ponte a senso Unico ==&lt;br /&gt;
Proposta di soluzione: esercizio 1 esame 22/01/2014&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
//&lt;br /&gt;
//  20140122_bridge&lt;br /&gt;
//&lt;br /&gt;
/*   Esercizio c.1:&lt;br /&gt;
 *&lt;br /&gt;
 *   Per colpa delle frane un ponte veicolare e' rimasto danneggiato.&lt;br /&gt;
 *   I veicoli possono ora percorrerlo solo in senso unico alternato e, per non eccedere la portata,&lt;br /&gt;
 *   al piu' ci possono essere sul ponte N veicoli contemporaneamente.&lt;br /&gt;
 *   Scrivere il monitor bridge sapendo che i veicoli chiameranno il monitor prima di entrare nel&lt;br /&gt;
 *   ponte e dopo averlo attraversato.&lt;br /&gt;
 *   I veicoli che entrano dal lato est escono dal lato ovest e viceversa.&lt;br /&gt;
 *   Quindi i (numerosi) veicoli eseguiranno uno dei due frammenti di codice seguenti:&lt;br /&gt;
 *&lt;br /&gt;
 *&lt;br /&gt;
 *   bridge.enter(E)                      bridge.enter(W)&lt;br /&gt;
 *   //cross the bridge                   //cross the bridge&lt;br /&gt;
 *   bridge.exit(W)                       bridge.exit(E)&lt;br /&gt;
 *&lt;br /&gt;
 *&lt;br /&gt;
 *   La soluzione proposta deve evitare deadlock e deve essere efficiente.&lt;br /&gt;
 *   (controesempio: una soluzione che prevedesse l'attraversamento del ponte da parte di un solo veicolo alla volta&lt;br /&gt;
 *   sebbene rispetti tutti i vincoli sarebbe considerata errata poiche' inefficiente).&lt;br /&gt;
 *   Oltre al codice si richiede una descrizione degli accorgimenti adottati per rendere la soluzione efficiente.&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;quot;monitor.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
#define CAPACITY 7 //capacità del bridge&lt;br /&gt;
#define BALANCE 9  &lt;br /&gt;
#define NCAR 15&lt;br /&gt;
&lt;br /&gt;
enum dest{&lt;br /&gt;
    E = 0,&lt;br /&gt;
    W = 1&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
int ncrossing_we = 0; //n car che stanno attraversando il bridge da W-&amp;gt;E&lt;br /&gt;
int ncrossing_ew = 0; //n car che stanno attraversando il bridge da E-&amp;gt;W&lt;br /&gt;
&lt;br /&gt;
int nwaiting_we = 0; //n car che aspettano di attraversare da W-&amp;gt;E&lt;br /&gt;
int nwaiting_ew = 0;  //n car che aspettano di attraversare da E-&amp;gt;W&lt;br /&gt;
&lt;br /&gt;
int priority = BALANCE;&lt;br /&gt;
&lt;br /&gt;
int crossed_we = 0; //n volte che il ponte è stato attraversato da W-&amp;gt;E&lt;br /&gt;
int crossed_ew = 0; //n volte che il ponte è stato attraversato da E-&amp;gt;W&lt;br /&gt;
&lt;br /&gt;
condition ok2goW; // capacity &amp;gt; 0 &amp;amp;&amp;amp; (ncrossing_ew == 0 || priority &amp;gt; 0)&lt;br /&gt;
condition ok2goE; // capacity &amp;gt; 0 &amp;amp;&amp;amp; (ncrossing_we == 0 || prioriti &amp;gt; 0 )&lt;br /&gt;
monitor bridge;&lt;br /&gt;
&lt;br /&gt;
void bridge_create(void){&lt;br /&gt;
    bridge = monitor_create();&lt;br /&gt;
    ok2goW = condition_create(bridge);&lt;br /&gt;
    ok2goE = condition_create(bridge);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void bridge_enter(enum dest d){&lt;br /&gt;
    monitor_enter(bridge);&lt;br /&gt;
    if (d == W) {&lt;br /&gt;
        nwaiting_we++;&lt;br /&gt;
        if (ncrossing_we &amp;gt;= CAPACITY || ncrossing_ew &amp;gt; 0 || (nwaiting_ew &amp;gt; 0 &amp;amp;&amp;amp; priority &amp;lt;= 0)) {&lt;br /&gt;
            condition_wait(ok2goW);&lt;br /&gt;
        }&lt;br /&gt;
        priority--;&lt;br /&gt;
        nwaiting_we--;&lt;br /&gt;
        ncrossing_we++;&lt;br /&gt;
        if (ncrossing_we &amp;lt; CAPACITY &amp;amp;&amp;amp; priority &amp;gt; 0) {&lt;br /&gt;
            condition_signal(ok2goW);&lt;br /&gt;
        }&lt;br /&gt;
    }else if(d == E){&lt;br /&gt;
        nwaiting_ew++;&lt;br /&gt;
        if (ncrossing_ew &amp;gt;= CAPACITY || ncrossing_we &amp;gt; 0 || (nwaiting_we &amp;gt; 0 &amp;amp;&amp;amp; priority &amp;lt;= 0)){&lt;br /&gt;
            condition_wait(ok2goE);&lt;br /&gt;
        }&lt;br /&gt;
        priority--;&lt;br /&gt;
        nwaiting_ew--;&lt;br /&gt;
        ncrossing_ew++;&lt;br /&gt;
        if (ncrossing_ew &amp;lt; CAPACITY &amp;amp;&amp;amp; priority &amp;gt; 0) {&lt;br /&gt;
            condition_signal(ok2goE);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    monitor_exit(bridge);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void bridge_exit(enum dest d){&lt;br /&gt;
    monitor_enter(bridge);&lt;br /&gt;
    if (d == E) {&lt;br /&gt;
        ncrossing_we--;&lt;br /&gt;
        crossed_we++;&lt;br /&gt;
        if (ncrossing_we &amp;lt; CAPACITY &amp;amp;&amp;amp; nwaiting_we &amp;gt; 0 &amp;amp;&amp;amp; (nwaiting_ew == 0 || priority &amp;gt; 0)) {&lt;br /&gt;
            condition_signal(ok2goW);&lt;br /&gt;
        }else if (ncrossing_we == 0 &amp;amp;&amp;amp; nwaiting_ew &amp;gt; 0 ) {&lt;br /&gt;
            priority = BALANCE;&lt;br /&gt;
            condition_signal(ok2goE);&lt;br /&gt;
        }&lt;br /&gt;
    } else if (d == W){&lt;br /&gt;
        ncrossing_ew--;&lt;br /&gt;
        crossed_ew++;&lt;br /&gt;
        if (ncrossing_ew &amp;lt; CAPACITY &amp;amp;&amp;amp; nwaiting_ew &amp;gt; 0 &amp;amp;&amp;amp; (nwaiting_we == 0 || priority &amp;gt; 0)) {&lt;br /&gt;
            condition_signal(ok2goE);&lt;br /&gt;
        }else if (ncrossing_ew == 0 &amp;amp;&amp;amp; nwaiting_we &amp;gt; 0) {&lt;br /&gt;
            priority = BALANCE;&lt;br /&gt;
            condition_signal(ok2goW);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    monitor_exit(bridge);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void *crossEW(void* arg){&lt;br /&gt;
    while (1) {&lt;br /&gt;
        printf(&amp;quot;waitW: %d |-|%d|-&amp;gt;  &amp;lt;-|%d|-| waitE: %d  || crossed W-&amp;gt;E: %d crossed E-&amp;gt;W: %d||\n&amp;quot;, nwaiting_we, ncrossing_we, ncrossing_ew, nwaiting_ew, crossed_we, crossed_ew);&lt;br /&gt;
        usleep(random() % 200000);&lt;br /&gt;
        bridge_enter(E);&lt;br /&gt;
        usleep(random() % 20000);&lt;br /&gt;
        bridge_exit(W);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void *crossWE(void* arg){&lt;br /&gt;
    while (1) {&lt;br /&gt;
        printf(&amp;quot;waitW: %d |-|%d|-&amp;gt;  &amp;lt;-|%d|-| waitE: %d  || crossed W-&amp;gt;E: %d crossed E-&amp;gt;W: %d||\n&amp;quot;, nwaiting_we, ncrossing_we, ncrossing_ew, nwaiting_ew, crossed_we, crossed_ew);&lt;br /&gt;
        usleep(random() % 200000);&lt;br /&gt;
        bridge_enter(W);&lt;br /&gt;
        usleep(random() % 20000);&lt;br /&gt;
        bridge_exit(E);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main(int argc, const char * argv[]) {&lt;br /&gt;
    pthread_t e_w_t[NCAR];&lt;br /&gt;
    pthread_t w_e_t[NCAR];&lt;br /&gt;
    bridge_create();&lt;br /&gt;
&lt;br /&gt;
    srandom(time(NULL));&lt;br /&gt;
    for (int i = 0; i &amp;lt; NCAR; i++) {&lt;br /&gt;
        pthread_create(&amp;amp;e_w_t[i], NULL, crossEW, NULL);&lt;br /&gt;
        pthread_create(&amp;amp;w_e_t[i], NULL, crossWE, NULL);&lt;br /&gt;
&lt;br /&gt;
    }&lt;br /&gt;
    for (int i = 0; i &amp;lt; NCAR; i++) {&lt;br /&gt;
        pthread_join(w_e_t[i], NULL);&lt;br /&gt;
        pthread_join(e_w_t[i], NULL);&lt;br /&gt;
    }&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Dal testo dell'esercizio si evincono le seguenti condizioni basilari per poter attraversare il ponte:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
   (capacità&amp;gt;0 &amp;amp;&amp;amp; ncrossing_OppositeDirection == 0)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Per rendere la soluzione efficiente ho introdotto, così, la variabile priority settata al valore BALANCE ottenendo la seguente condizione:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
priority &amp;gt; 0 || nwaitingOppositeDirection == 0; &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
e.i. fin quando il mio senso (e.g. W-&amp;gt;E) ha ancora priorità di attraversare  O non ci sono macchine nella &lt;br /&gt;
direzione opposta che attendono, continuo a dare il via alle macchine che vanno nella mia stessa direzione.&lt;br /&gt;
Priority viene decrementata ad ogni macchina che attraversa il ponte.&lt;br /&gt;
&lt;br /&gt;
Non appena tale condizione viene interrotta, priority viene restaurata al valore BALANCE e la sua gestione viene ceduta al senso opposto.&lt;br /&gt;
Notare che anche questa soluzione non gestisce il caso in cui &amp;quot;il mio senso ha priorità ma non c'è nessuno che vuole attraversare&amp;quot;, &lt;br /&gt;
sarebbe inutile far attendere e maccchine della direzione opposta.&lt;br /&gt;
Allora il tutto viene gestito come segue:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
   bridge.enter()&lt;br /&gt;
    if (ncrossing_MyDirection &amp;lt;= CAPACITY &amp;amp;&amp;amp; ncrossing_OppositeDirection == 0 &amp;amp;&amp;amp; (mypriority &amp;gt; 0 || nwaitingOppositeDirection == 0)){&lt;br /&gt;
					 attraverso il ponte;&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
    bridge.exit()&lt;br /&gt;
	if (ncrossing_MyDirection &amp;lt; CAPACITY &amp;amp;&amp;amp; nwaiting_MyDirection &amp;gt; 0 &amp;amp;&amp;amp; (nwaiting_OppositeDirection == 0 || mypriority &amp;gt; 0)) {&lt;br /&gt;
            		do il via a chi attende di attraversare nella mia stessa direzione;&lt;br /&gt;
        }else if (ncrossing_MyDirection == 0 &amp;amp;&amp;amp; nwaiting_OppositeDirection &amp;gt; 0 ) {&lt;br /&gt;
            		restauro priority e lascio il comando alle macchine nella direzione opposta;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
L’ultima possibilità è che nessuno vuole attraversare il bridge, in questo caso nn faccio nulla. &lt;br /&gt;
Il comando resta alla direzione che per ultima ha attraversato il bridge&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Ponte a senso unico (2) ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;monitor.h&amp;gt;&lt;br /&gt;
#include &amp;lt;pthread.h&amp;gt;&lt;br /&gt;
#include &amp;lt;string.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
const int NCAR_E=8;&lt;br /&gt;
const int NCAR_W=8;&lt;br /&gt;
const int MAX_CAR = 7;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
enum dir{E,W,N};&lt;br /&gt;
int n_carcross = 0;&lt;br /&gt;
int waiting[2] = {0,0}; //[0] = [E] ; [1] = [W]&lt;br /&gt;
enum dir curr_dir = N; &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
monitor bridge;&lt;br /&gt;
condition ok2go[2];&lt;br /&gt;
&lt;br /&gt;
void bridge_create(){&lt;br /&gt;
	bridge = monitor_create();&lt;br /&gt;
	ok2go[0] = condition_create(bridge);&lt;br /&gt;
	ok2go[1] = condition_create(bridge);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void print_bridge(){&lt;br /&gt;
	if (curr_dir == E)&lt;br /&gt;
		printf(&amp;quot;%d W &amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;%d&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt; E %d\n&amp;quot;,waiting[1],n_carcross,waiting[0]);&lt;br /&gt;
	else&lt;br /&gt;
		printf(&amp;quot;%d W &amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;%d&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; E %d\n&amp;quot;,waiting[1],n_carcross,waiting[0]);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void bridge_enter(enum dir d){&lt;br /&gt;
	monitor_enter(bridge);&lt;br /&gt;
	int i = (int) d;&lt;br /&gt;
	if (curr_dir == N){&lt;br /&gt;
		curr_dir = d;&lt;br /&gt;
	}&lt;br /&gt;
	if ((curr_dir != d) || (n_carcross &amp;gt;= MAX_CAR) || (waiting[1-i]&amp;gt;0)){&lt;br /&gt;
			waiting[i]++;&lt;br /&gt;
			condition_wait(ok2go[i]);&lt;br /&gt;
			waiting[i]--;&lt;br /&gt;
	}&lt;br /&gt;
	n_carcross++;&lt;br /&gt;
	print_bridge();&lt;br /&gt;
	if (n_carcross &amp;lt; MAX_CAR){&lt;br /&gt;
		if (waiting[i]&amp;gt;0)&lt;br /&gt;
			condition_signal(ok2go[i]);&lt;br /&gt;
	}&lt;br /&gt;
	monitor_exit(bridge);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void bridge_exit(enum dir d){&lt;br /&gt;
 monitor_enter(bridge);&lt;br /&gt;
 int i = (int) d;&lt;br /&gt;
 n_carcross--;&lt;br /&gt;
 print_bridge();&lt;br /&gt;
 if (waiting[i]&amp;gt;0){&lt;br /&gt;
 	if (n_carcross == 0){&lt;br /&gt;
 		curr_dir = (enum dir) (1 - curr_dir);&lt;br /&gt;
 		condition_signal(ok2go[i]);&lt;br /&gt;
 	}&lt;br /&gt;
 }&lt;br /&gt;
 else&lt;br /&gt;
       If (waiting [1-i]&amp;gt;0)&lt;br /&gt;
 	   condition_signal(ok2go[1-i]);&lt;br /&gt;
       Else &lt;br /&gt;
           curr_dir = N; &lt;br /&gt;
 monitor_exit(bridge);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void *cross(void* arg){&lt;br /&gt;
	enum dir d = (enum dir) arg;&lt;br /&gt;
	while (1) {&lt;br /&gt;
	        usleep(random() % 2000000);&lt;br /&gt;
	        bridge_enter(d);&lt;br /&gt;
	        usleep(random() % 2000000);&lt;br /&gt;
	        bridge_exit((enum dir)(1-d));&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main(int argc, const char * argv[]) {&lt;br /&gt;
    pthread_t e_t[NCAR_E];&lt;br /&gt;
    pthread_t w_t[NCAR_W];&lt;br /&gt;
    &lt;br /&gt;
    bridge_create();&lt;br /&gt;
 &lt;br /&gt;
    srandom(time(NULL));&lt;br /&gt;
&lt;br /&gt;
    for (int i = 0; i &amp;lt; NCAR_E; i++) {&lt;br /&gt;
        pthread_create(&amp;amp;e_t[i], NULL, cross,(void*) E); &lt;br /&gt;
    }&lt;br /&gt;
    for (int i = 0; i &amp;lt; NCAR_W; i++) {&lt;br /&gt;
        pthread_create(&amp;amp;w_t[i], NULL, cross, (void*) W);&lt;br /&gt;
    }&lt;br /&gt;
    for (int i = 0; i &amp;lt; NCAR_E; i++) {&lt;br /&gt;
        pthread_join(e_t[i], NULL);&lt;br /&gt;
    }&lt;br /&gt;
    for (int i = 0; i &amp;lt; NCAR_W; i++) {&lt;br /&gt;
        pthread_join(w_t[i], NULL);&lt;br /&gt;
    }&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Questa è la prima soluzione che mi è venuta in mente cercando di rimanere sul più semplice possibile ... ho adottato alcuni accorgimenti per evitare di avere un programma lungo ma con &amp;quot;doppioni&amp;quot; --[[User:GabrieleCalarota|GabrieleCalarota]] ([[User talk:GabrieleCalarota|talk]]) 18:35, 14 December 2016 (CET)&lt;br /&gt;
&lt;br /&gt;
== Monitor: Cospirazione dei filosofi ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;monitor.h&amp;gt;&lt;br /&gt;
#include &amp;lt;pthread.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdint.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
monitor dp;&lt;br /&gt;
condition philo_wait[5]; /* status[np(i,1)] == 'T' &amp;amp;&amp;amp; status[np(i,-1)] == 'T' */&lt;br /&gt;
char status[] = &amp;quot;TTTTT&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
int np(int i, int off) {&lt;br /&gt;
        return (i+5+off) % 5;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void dp_create(void) {&lt;br /&gt;
        int i;&lt;br /&gt;
        dp = monitor_create();&lt;br /&gt;
        for (i=0; i&amp;lt;5; i++)&lt;br /&gt;
                philo_wait[i] = condition_create(dp);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void dp_starteat(int i) {&lt;br /&gt;
        monitor_enter(dp);&lt;br /&gt;
        if (status[np(i,1)] != 'T' || status[np(i,-1)] != 'T')&lt;br /&gt;
                condition_wait(philo_wait[i]);&lt;br /&gt;
        status[i] = 'E';&lt;br /&gt;
        printf(&amp;quot;%s\n&amp;quot;,status);&lt;br /&gt;
        monitor_exit(dp);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void dp_endeat(int i) {&lt;br /&gt;
        monitor_enter(dp);&lt;br /&gt;
        status[i] = 'T';&lt;br /&gt;
        printf(&amp;quot;%s\n&amp;quot;,status);&lt;br /&gt;
        if (status[np(i,2)] == 'T')&lt;br /&gt;
                condition_signal(philo_wait[np(i,1)]);&lt;br /&gt;
        if (status[np(i,-2)] == 'T')&lt;br /&gt;
                condition_signal(philo_wait[np(i,-1)]);&lt;br /&gt;
        monitor_exit(dp);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
monitor cospy;&lt;br /&gt;
condition wait2eat;&lt;br /&gt;
int cospy_count;&lt;br /&gt;
&lt;br /&gt;
void cospy_create(void) {&lt;br /&gt;
        cospy = monitor_create();&lt;br /&gt;
        wait2eat = condition_create(cospy);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void cospy_starteat(void) {&lt;br /&gt;
        monitor_enter(cospy);&lt;br /&gt;
        cospy_count++;&lt;br /&gt;
        condition_signal(wait2eat);&lt;br /&gt;
        monitor_exit(cospy);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void cospy_endeat(void) {&lt;br /&gt;
        monitor_enter(cospy);&lt;br /&gt;
        cospy_count--;&lt;br /&gt;
        if (cospy_count == 0)&lt;br /&gt;
                condition_wait(wait2eat);&lt;br /&gt;
        monitor_exit(cospy);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void *philo(void *arg) {&lt;br /&gt;
        int i = (uintptr_t) arg;&lt;br /&gt;
        while (1) {&lt;br /&gt;
                usleep(random() % 2000000);&lt;br /&gt;
                dp_starteat(i);&lt;br /&gt;
                if (i == 1 || i == 3)&lt;br /&gt;
                        cospy_starteat();&lt;br /&gt;
                usleep(random() % 2000000);&lt;br /&gt;
                if (i == 1 || i == 3)&lt;br /&gt;
                        cospy_endeat();&lt;br /&gt;
                dp_endeat(i);&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char *argv[]) {&lt;br /&gt;
        pthread_t philo_t[5];&lt;br /&gt;
        uintptr_t i;&lt;br /&gt;
        dp_create();&lt;br /&gt;
        cospy_create();&lt;br /&gt;
        srandom(time(NULL));&lt;br /&gt;
        for (i=0; i&amp;lt;5; i++)&lt;br /&gt;
                pthread_create(&amp;amp;philo_t[i], NULL, philo, (void *) i );&lt;br /&gt;
        while(1)&lt;br /&gt;
                pause();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
--[[User:FedericoB|FedericoB]] ([[User talk:FedericoB|talk]]) 11:27, 25 November 2016 (CET)Veniva creata la condizione di cospirazione collegata al monitor dp invece che cospy. Quindi con il signal il processo veniva messo nell'urgent stack sbagliato e chiamando monitor_exit su cospy non si risvegliava il processo nell' urgent stack di dp.&lt;br /&gt;
&lt;br /&gt;
== RW errato ==&lt;br /&gt;
Codice '''ERRATO''' dei lettori scrittori che dovrebbe non soffrire di problemi di starvation...&lt;br /&gt;
Esercizio: trovare gli errori.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
#include&amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include&amp;lt;stdint.h&amp;gt;&lt;br /&gt;
#include&amp;lt;pthread.h&amp;gt;&lt;br /&gt;
#include&amp;lt;semaphore.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define NREADER 3&lt;br /&gt;
#define NWRITER 3&lt;br /&gt;
semaphore mutex;&lt;br /&gt;
semaphore ok2read;&lt;br /&gt;
semaphore ok2write;&lt;br /&gt;
&lt;br /&gt;
int nr=0;&lt;br /&gt;
int nw=0;&lt;br /&gt;
int wr=0;&lt;br /&gt;
int ww=0;&lt;br /&gt;
int w_last;&lt;br /&gt;
&lt;br /&gt;
// (nw == 0 &amp;amp;&amp;amp; nr == 0) || (nr &amp;gt; 0 &amp;amp;&amp;amp; nw == 0) || nw == 1&lt;br /&gt;
// (nw == 0 &amp;amp;&amp;amp; nr &amp;gt;= 0) || nw == 1&lt;br /&gt;
&lt;br /&gt;
// this &amp;quot;baton&amp;quot; function has been left for reference only.&lt;br /&gt;
// code to implement &amp;quot;passing the baton&amp;quot; has been copied at the end of&lt;br /&gt;
// each ({start}|{end})({read}|{write}) function and reduced.&lt;br /&gt;
void baton(void) {&lt;br /&gt;
        if (nw == 0 &amp;amp;&amp;amp; nr == 0 &amp;amp;&amp;amp; ww &amp;gt; 0)&lt;br /&gt;
                semaphore_V(ok2write);&lt;br /&gt;
        else if (nw == 0 &amp;amp;&amp;amp; wr &amp;gt; 0 )&lt;br /&gt;
                semaphore_V(ok2read);&lt;br /&gt;
        else&lt;br /&gt;
                semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void startread(void) {&lt;br /&gt;
// &amp;lt;await nw == 0 -&amp;gt; nr++&amp;gt;&lt;br /&gt;
        semaphore_P(mutex);&lt;br /&gt;
        if (nw &amp;gt; 0 &amp;amp;&amp;amp; ww == 0) {&lt;br /&gt;
                wr++;&lt;br /&gt;
                semaphore_V(mutex);&lt;br /&gt;
                semaphore_P(ok2read);&lt;br /&gt;
                wr--;&lt;br /&gt;
        }&lt;br /&gt;
        nr++;&lt;br /&gt;
        w_last=0;&lt;br /&gt;
        printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, nr, nw, wr, ww);&lt;br /&gt;
        if (wr &amp;gt; 0 )&lt;br /&gt;
                semaphore_V(ok2read);&lt;br /&gt;
        else&lt;br /&gt;
                semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void endread(void) {&lt;br /&gt;
// &amp;lt;nr--&amp;gt;&lt;br /&gt;
        semaphore_P(mutex);&lt;br /&gt;
        nr--;&lt;br /&gt;
        printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, nr, nw, wr, ww);&lt;br /&gt;
        if (nr == 0 &amp;amp;&amp;amp; ww &amp;gt; 0)&lt;br /&gt;
                semaphore_V(ok2write);&lt;br /&gt;
        else&lt;br /&gt;
                semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void startwrite(void) {&lt;br /&gt;
// &amp;lt;await nw == 0 &amp;amp;&amp;amp; nr == 0 -&amp;gt; nw++&amp;gt;&lt;br /&gt;
        semaphore_P(mutex);&lt;br /&gt;
        if (nw &amp;gt; 0 || nr &amp;gt; 0) {&lt;br /&gt;
                ww++;&lt;br /&gt;
                semaphore_V(mutex);&lt;br /&gt;
                semaphore_P(ok2write);&lt;br /&gt;
                ww--;&lt;br /&gt;
        }&lt;br /&gt;
        nw++;&lt;br /&gt;
        w_last=1;&lt;br /&gt;
        printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, nr, nw, wr, ww);&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void endwrite(void) {&lt;br /&gt;
// &amp;lt;nw--&amp;gt;&lt;br /&gt;
        semaphore_P(mutex);&lt;br /&gt;
        nw--;&lt;br /&gt;
        printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, nr, nw, wr, ww);&lt;br /&gt;
        if (wr &amp;gt; 0 &amp;amp;&amp;amp; (ww == 0 || w_last))&lt;br /&gt;
                semaphore_V(ok2read);&lt;br /&gt;
        else if (ww &amp;gt; 0 &amp;amp;&amp;amp; (wr == 0 || !w_last))&lt;br /&gt;
                semaphore_V(ok2write);&lt;br /&gt;
        else&lt;br /&gt;
                semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void *reader(void *arg) {&lt;br /&gt;
        int i = (uintptr_t)arg;&lt;br /&gt;
        while (1) {&lt;br /&gt;
                //other code&lt;br /&gt;
                usleep(random() % 200000);&lt;br /&gt;
                startread();&lt;br /&gt;
                //read&lt;br /&gt;
                usleep(random() % 200000);&lt;br /&gt;
                endread();&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void *writer(void *arg) {&lt;br /&gt;
        int i = (uintptr_t)arg;&lt;br /&gt;
        while (1) {&lt;br /&gt;
                //other code&lt;br /&gt;
                usleep(random() % 200000);&lt;br /&gt;
                startwrite();&lt;br /&gt;
                //write&lt;br /&gt;
                usleep(random() % 200000);&lt;br /&gt;
                endwrite();&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//printf(&amp;quot;philo thinking: %d\n&amp;quot;,i);&lt;br /&gt;
/*while*/&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char *argv[]) {&lt;br /&gt;
        int i;&lt;br /&gt;
        pthread_t t;&lt;br /&gt;
        srandom(time(NULL));&lt;br /&gt;
        mutex=semaphore_create(1);&lt;br /&gt;
        ok2read=semaphore_create(0);&lt;br /&gt;
        ok2write=semaphore_create(0);&lt;br /&gt;
        for (i=0; i&amp;lt;NREADER; i++)&lt;br /&gt;
                pthread_create(&amp;amp;t, NULL, reader, (void *)(uintptr_t) i);&lt;br /&gt;
        for (i=0; i&amp;lt;NWRITER; i++)&lt;br /&gt;
                pthread_create(&amp;amp;t, NULL, writer, (void *)(uintptr_t) i);&lt;br /&gt;
        while(1)&lt;br /&gt;
                pause();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== RW di FedericoB ==&lt;br /&gt;
Propongo la seguente soluzione. Mi sembra che funzioni ma devo ancora capire perchè e documentarla bene. Ho provato prima a cercare il bug ma non ci sono riuscito. Ho quindi modificato il codice secondo ciò che mi sembrava sensato in base alle condizioni del problema. Ne possiamo parlare in aula oggi. --[[User:FedericoB|FedericoB]] ([[User talk:FedericoB|talk]]) 12:48, 11 November 2016 (CET)&lt;br /&gt;
Ho notato che l'errore non si manifesta più eliminando il controllo che ci siano scrittori in attesa quando un lettore vuole iniziare a scrivere. Non capisco come questo possa essere collegato al bug. --[[User:FedericoB|FedericoB]] ([[User talk:FedericoB|talk]]) 15:10, 11 November 2016 (CET)&lt;br /&gt;
&lt;br /&gt;
FedericoB, questa soluzione &amp;amp;egrave; quella con priorit&amp;amp;agrave; ai lettori, no? Se continuano ad arrivare lettori numberOfReaders non sar&amp;amp;agrave; mai zero e quindi gli scrittori non scriveranno mai. [[User:Renzo|Renzo]] ([[User talk:Renzo|talk]]) 10:34, 12 November 2016 (CET)&lt;br /&gt;
&lt;br /&gt;
SFIDA: ho trovato il modo di togliere la starvation aggiungendo 4 token (parole chiave, nomi di variabili, operatori, costanti) a questa soluzione di FedericoB. Chi trova la soluzione? [[User:Renzo|Renzo]] ([[User talk:Renzo|talk]]) 10:43, 12 November 2016 (CET) Ah! ho appena trovato una soluzione che prevede 2 soli token in pi&amp;amp;ugrave;! [[User:Renzo|Renzo]] ([[User talk:Renzo|talk]]) 10:47, 12 November 2016 (CET)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
#include&amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include&amp;lt;stdint.h&amp;gt;&lt;br /&gt;
#include&amp;lt;pthread.h&amp;gt;&lt;br /&gt;
#include&amp;lt;semaphore.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define NUMBER_OF_READERS 3&lt;br /&gt;
#define NUMBER_OF_WRITERS 3&lt;br /&gt;
semaphore mutex;&lt;br /&gt;
semaphore ok2read;&lt;br /&gt;
semaphore ok2write;&lt;br /&gt;
&lt;br /&gt;
int numberOfReaders=0;&lt;br /&gt;
int numberOfWriters=0;&lt;br /&gt;
int waitingReaders=0;&lt;br /&gt;
int waitingWriters=0;&lt;br /&gt;
&lt;br /&gt;
// (nw == 0 &amp;amp;&amp;amp; nr == 0) || (nr &amp;gt; 0 &amp;amp;&amp;amp; nw == 0) || nw == 1&lt;br /&gt;
// (nw == 0 &amp;amp;&amp;amp; nr &amp;gt;= 0) || nw == 1&lt;br /&gt;
&lt;br /&gt;
void startread(void) {&lt;br /&gt;
// &amp;lt;await nw == 0 -&amp;gt; nr++&amp;gt;&lt;br /&gt;
    semaphore_P(mutex);&lt;br /&gt;
    if (numberOfWriters &amp;gt; 0) {&lt;br /&gt;
        waitingReaders++;&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
        semaphore_P(ok2read);&lt;br /&gt;
        waitingReaders--;&lt;br /&gt;
    }&lt;br /&gt;
    numberOfReaders++;&lt;br /&gt;
    printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, numberOfReaders, numberOfWriters, waitingReaders, waitingWriters);&lt;br /&gt;
    if (waitingReaders &amp;gt; 0 )&lt;br /&gt;
        semaphore_V(ok2read);&lt;br /&gt;
    else&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void endread(void) {&lt;br /&gt;
// &amp;lt;nr--&amp;gt;&lt;br /&gt;
    semaphore_P(mutex);&lt;br /&gt;
    numberOfReaders--;&lt;br /&gt;
    printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, numberOfReaders, numberOfWriters, waitingReaders, waitingWriters);&lt;br /&gt;
    if (numberOfReaders == 0 &amp;amp;&amp;amp; waitingWriters &amp;gt; 0)&lt;br /&gt;
        semaphore_V(ok2write);&lt;br /&gt;
    else&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void startwrite(void) {&lt;br /&gt;
// &amp;lt;await nw == 0 &amp;amp;&amp;amp; nr == 0 -&amp;gt; nw++&amp;gt;&lt;br /&gt;
    semaphore_P(mutex);&lt;br /&gt;
    if (numberOfWriters &amp;gt; 0 || numberOfReaders &amp;gt; 0) {&lt;br /&gt;
        waitingWriters++;&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
        semaphore_P(ok2write);&lt;br /&gt;
        waitingWriters--;&lt;br /&gt;
    }&lt;br /&gt;
    numberOfWriters++;&lt;br /&gt;
    printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, numberOfReaders, numberOfWriters, waitingReaders, waitingWriters);&lt;br /&gt;
    semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void endwrite(void) {&lt;br /&gt;
// &amp;lt;nw--&amp;gt;&lt;br /&gt;
    semaphore_P(mutex);&lt;br /&gt;
    numberOfWriters--;&lt;br /&gt;
    printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, numberOfReaders, numberOfWriters, waitingReaders, waitingWriters);&lt;br /&gt;
    if (waitingReaders &amp;gt; 0)&lt;br /&gt;
        semaphore_V(ok2read);&lt;br /&gt;
    else if (waitingWriters &amp;gt; 0)&lt;br /&gt;
        semaphore_V(ok2write);&lt;br /&gt;
    else&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void *reader(void *arg) {&lt;br /&gt;
    int i = (uintptr_t)arg;&lt;br /&gt;
    while (1) {&lt;br /&gt;
        //other code&lt;br /&gt;
        usleep(random() % 200000);&lt;br /&gt;
        startread();&lt;br /&gt;
        //read&lt;br /&gt;
        usleep(random() % 200000);&lt;br /&gt;
        endread();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void *writer(void *arg) {&lt;br /&gt;
    int i = (uintptr_t)arg;&lt;br /&gt;
    while (1) {&lt;br /&gt;
        //other code&lt;br /&gt;
        usleep(random() % 200000);&lt;br /&gt;
        startwrite();&lt;br /&gt;
        //write&lt;br /&gt;
        usleep(random() % 200000);&lt;br /&gt;
        endwrite();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//printf(&amp;quot;philo thinking: %d\n&amp;quot;,i);&lt;br /&gt;
/*while*/&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char *argv[]) {&lt;br /&gt;
    int i;&lt;br /&gt;
    pthread_t t;&lt;br /&gt;
    srandom(time(NULL));&lt;br /&gt;
    mutex=semaphore_create(1);&lt;br /&gt;
    ok2read=semaphore_create(0);&lt;br /&gt;
    ok2write=semaphore_create(0);&lt;br /&gt;
    for (i=0; i&amp;lt;NUMBER_OF_READERS; i++)&lt;br /&gt;
        pthread_create(&amp;amp;t, NULL, reader, (void *)(uintptr_t) i);&lt;br /&gt;
    for (i=0; i&amp;lt;NUMBER_OF_WRITERS; i++)&lt;br /&gt;
        pthread_create(&amp;amp;t, NULL, writer, (void *)(uintptr_t) i);&lt;br /&gt;
    while(1)&lt;br /&gt;
        pause();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== RW2 ==&lt;br /&gt;
Buongiorno, guardando il codice visto a lezione mi sembra che cambiando la condizione del primo if nella startread() da &amp;quot;if (nw &amp;gt; 0 &amp;amp;&amp;amp; ww == 0)&amp;quot; a &amp;quot;if (nw &amp;gt; 0 || ww &amp;gt; 0)&amp;quot; la situazione migliori. In particolare con l'and tra quelle due condizioni si aveva che non veniva fatta la P sull'ok2read anche quando si aveva nw&amp;gt;0 (con ww!=0), cosa che invece dovrebbe fare. Lasciando il resto del codice uguale mi sembra che faccia quello che deve fare.. .&lt;br /&gt;
&lt;br /&gt;
Matteo.pincherle: Perch&amp;amp;eacute; non modifichi in programma di FedericoB, lo provi e pubblichi qui la patch? [[User:Renzo|Renzo]] ([[User talk:Renzo|talk]]) 10:42, 13 November 2016 (CET)&lt;br /&gt;
&lt;br /&gt;
'''Perchè quel AND permetteva di avere 2 scrittori?''' &amp;lt;br&amp;gt;&lt;br /&gt;
Permetteva in primis di avere dei lettori in contemporanea a uno scrittore. In quanto se succedeva che un lettore volesse entrare mentre non c'erano degli scrittori in attesa ma scrittori in scrittura, veniva saltato il blocco che mandava il lettore in attesa e risultava un lettore in contemporanea a uno scrittore. &amp;lt;br&amp;gt;&lt;br /&gt;
Questo lettore poi poteva finire di leggere prima che lo scrittore in contemporanea a lui finisse di scrivere. &amp;lt;br&amp;gt;&lt;br /&gt;
Il lettore in uscita se non c'erano altri lettori con lui e non c'erano scrittori in attesa dava il permesso per far accedere un altro scrittore. &amp;lt;br&amp;gt;&lt;br /&gt;
A questo punto un altro scrittore che avesse voluto entrare poteva entrare, con il risultato di avere 2 scrittori in contemporanea.&lt;br /&gt;
--[[User:FedericoB|FedericoB]] ([[User talk:FedericoB|talk]]) 19:25, 13 November 2016 (CET)&lt;br /&gt;
&lt;br /&gt;
== Patch ==&lt;br /&gt;
Così, se non sbaglio, quando c'è almeno uno scrittore in attesa non lascia entrare altri lettori. Fa esaurire la lettura dei presenti e poi lascia scrivere lo scrittore.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include&amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include&amp;lt;stdint.h&amp;gt;&lt;br /&gt;
#include&amp;lt;pthread.h&amp;gt;&lt;br /&gt;
#include&amp;lt;semaphore.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define NUMBER_OF_READERS 3&lt;br /&gt;
#define NUMBER_OF_WRITERS 3&lt;br /&gt;
semaphore mutex;&lt;br /&gt;
semaphore ok2read;&lt;br /&gt;
semaphore ok2write;&lt;br /&gt;
&lt;br /&gt;
int numberOfReaders=0;&lt;br /&gt;
int numberOfWriters=0;&lt;br /&gt;
int waitingReaders=0;&lt;br /&gt;
int waitingWriters=0;&lt;br /&gt;
int w_last;&lt;br /&gt;
&lt;br /&gt;
// (nw == 0 &amp;amp;&amp;amp; nr == 0) || (nr &amp;gt; 0 &amp;amp;&amp;amp; nw == 0) || nw == 1&lt;br /&gt;
// (nw == 0 &amp;amp;&amp;amp; nr &amp;gt;= 0) || nw == 1&lt;br /&gt;
&lt;br /&gt;
void startread(void) {&lt;br /&gt;
    // &amp;lt;await nw == 0 -&amp;gt; nr++&amp;gt;&lt;br /&gt;
    semaphore_P(mutex);&lt;br /&gt;
    if (numberOfWriters &amp;gt; 0 || waitingWriters&amp;gt;0) {&lt;br /&gt;
        waitingReaders++;&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
        semaphore_P(ok2read);&lt;br /&gt;
        waitingReaders--;&lt;br /&gt;
    }&lt;br /&gt;
    numberOfReaders++;&lt;br /&gt;
    w_last=0;&lt;br /&gt;
    printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, numberOfReaders, numberOfWriters, waitingReaders, waitingWriters);&lt;br /&gt;
    if (waitingReaders &amp;gt; 0 )&lt;br /&gt;
        semaphore_V(ok2read);&lt;br /&gt;
    else&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void endread(void) {&lt;br /&gt;
    // &amp;lt;nr--&amp;gt;&lt;br /&gt;
    semaphore_P(mutex);&lt;br /&gt;
    numberOfReaders--;&lt;br /&gt;
    printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, numberOfReaders, numberOfWriters, waitingReaders, waitingWriters);&lt;br /&gt;
    if (numberOfReaders == 0 &amp;amp;&amp;amp; waitingWriters &amp;gt; 0)&lt;br /&gt;
        semaphore_V(ok2write);&lt;br /&gt;
    else&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void startwrite(void) {&lt;br /&gt;
    // &amp;lt;await nw == 0 &amp;amp;&amp;amp; nr == 0 -&amp;gt; nw++&amp;gt;&lt;br /&gt;
    semaphore_P(mutex);&lt;br /&gt;
    if (numberOfWriters &amp;gt; 0 || numberOfReaders &amp;gt; 0) {&lt;br /&gt;
        waitingWriters++;&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
        semaphore_P(ok2write);&lt;br /&gt;
        waitingWriters--;&lt;br /&gt;
    }&lt;br /&gt;
    numberOfWriters++;&lt;br /&gt;
    w_last=1;&lt;br /&gt;
    printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, numberOfReaders, numberOfWriters, waitingReaders, waitingWriters);&lt;br /&gt;
    semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void endwrite(void) {&lt;br /&gt;
    // &amp;lt;nw--&amp;gt;&lt;br /&gt;
    semaphore_P(mutex);&lt;br /&gt;
    numberOfWriters--;&lt;br /&gt;
    printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, numberOfReaders, numberOfWriters, waitingReaders, waitingWriters);&lt;br /&gt;
    if (waitingReaders &amp;gt; 0 &amp;amp;&amp;amp; (waitingWriters==0 || w_last))&lt;br /&gt;
        semaphore_V(ok2read);&lt;br /&gt;
    else if (waitingWriters &amp;gt; 0 &amp;amp;&amp;amp; (waitingReaders==0 || !w_last))&lt;br /&gt;
        semaphore_V(ok2write);&lt;br /&gt;
    else&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void *reader(void *arg) {&lt;br /&gt;
    int i = (uintptr_t)arg;&lt;br /&gt;
    while (1) {&lt;br /&gt;
        //other code&lt;br /&gt;
        usleep(random() % 200000);&lt;br /&gt;
        startread();&lt;br /&gt;
        //read&lt;br /&gt;
        usleep(random() % 200000);&lt;br /&gt;
        endread();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void *writer(void *arg) {&lt;br /&gt;
    int i = (uintptr_t)arg;&lt;br /&gt;
    while (1) {&lt;br /&gt;
        //other code&lt;br /&gt;
        usleep(random() % 200000);&lt;br /&gt;
        startwrite();&lt;br /&gt;
        //write&lt;br /&gt;
        usleep(random() % 200000);&lt;br /&gt;
        endwrite();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char *argv[]) {&lt;br /&gt;
    int i;&lt;br /&gt;
    pthread_t t;&lt;br /&gt;
    srandom(time(NULL));&lt;br /&gt;
    mutex=semaphore_create(1);&lt;br /&gt;
    ok2read=semaphore_create(0);&lt;br /&gt;
    ok2write=semaphore_create(0);&lt;br /&gt;
    for (i=0; i&amp;lt;NUMBER_OF_READERS; i++)&lt;br /&gt;
        pthread_create(&amp;amp;t, NULL, reader, (void *)(uintptr_t) i);&lt;br /&gt;
    for (i=0; i&amp;lt;NUMBER_OF_WRITERS; i++)&lt;br /&gt;
        pthread_create(&amp;amp;t, NULL, writer, (void *)(uintptr_t) i);&lt;br /&gt;
    while(1)&lt;br /&gt;
        pause();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
wlast non serve pi&amp;amp;ugrave;... [[User:Renzo|Renzo]] ([[User talk:Renzo|talk]]) 17:52, 13 November 2016 (CET)&lt;br /&gt;
&lt;br /&gt;
== RW2bis ==&lt;br /&gt;
Nella tua soluzione se i lettori sono &amp;quot;molto veloci&amp;quot; e non vanno mai a 0, lo scrittore non inizierà mai a scrivere.&lt;br /&gt;
&lt;br /&gt;
Cioè: Uno scrittore viene svegliato da ok2write solo se passa la condizione &lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
[..] &lt;br /&gt;
if (numberofReaders == 0 &amp;amp;&amp;amp; waitingWriters &amp;gt;0) &lt;br /&gt;
     semaphore_V(ok2write);&lt;br /&gt;
[..]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; --[[User:GabrieleCalarota|GabrieleCalarota]] ([[User talk:GabrieleCalarota|talk]]) 17:46, 13 November 2016 (CET)&lt;br /&gt;
&lt;br /&gt;
Non direi perche' nella startread se:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
    if (numberOfWriters &amp;gt; 0 || waitingWriters&amp;gt;0) &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
i lettori si bloccano. Quindi se c'e' almeno uno scrittore in attesa i lettori non entrano (e quindi prima o poi terminano e lasciano il posto ad uno scrittore).&lt;br /&gt;
[[User:Renzo|Renzo]] ([[User talk:Renzo|talk]]) 17:57, 13 November 2016 (CET)&lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
Ho pensato al caso limite seguente:&lt;br /&gt;
Supponiamo che ci siano dei lettori che stanno leggendo e ad un certo punto uno scrittore chiede di scrivere.&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;syntaxhighlight lang=C&amp;gt;         &lt;br /&gt;
       void startread(void) {&lt;br /&gt;
    // &amp;lt;await nw == 0 -&amp;gt; nr++&amp;gt;&lt;br /&gt;
    semaphore_P(mutex);&lt;br /&gt;
    if (numberOfWriters &amp;gt; 0 || waitingWriters&amp;gt;0) {&lt;br /&gt;
        waitingReaders++;   //Nuovo scrittore (t1)&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
        semaphore_P(ok2read);&lt;br /&gt;
        waitingReaders--;&lt;br /&gt;
    }&lt;br /&gt;
    numberOfReaders++;&lt;br /&gt;
    w_last=0;&lt;br /&gt;
    printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, numberOfReaders, numberOfWriters, waitingReaders, waitingWriters);&lt;br /&gt;
   if (waitingReaders &amp;gt; 0 )   //Vecchio scrittore(t1)&lt;br /&gt;
        semaphore_V(ok2read);&lt;br /&gt;
    else&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Non appena lo scrittore rilascia il mutex, un nuovo lettore chiede di leggere (e si addormenterà). Un lettore (lento) che era riuscito a entrare nel segmento startofread prima che lo scrittore entrasse in startofwrite, continua a leggere e risveglia uno dei nuovi lettori. Se i lettori continuano a richiedere di leggere continuamente, verranno addormentati e subito risvegliati. &lt;br /&gt;
&lt;br /&gt;
E' da considerarsi possibile? --[[User:GabrieleCalarota|GabrieleCalarota]] ([[User talk:GabrieleCalarota|talk]]) 19:11, 13 November 2016 (CET)&lt;br /&gt;
&lt;br /&gt;
Suppongo che &amp;quot;un nuovo scrittore chiede di leggere&amp;quot; si aun refuso e sia da intendere &amp;quot;un nuovo lettore chiede di leggere&amp;quot; (altrimenti ci sono crisi di identit&amp;amp;agrave;) e che &amp;quot;startofread&amp;quot; significhi &amp;quot;startread&amp;quot; e &amp;quot;startofwrite&amp;quot;  sia &amp;quot;startwrite&amp;quot;.&lt;br /&gt;
La &amp;quot;startread&amp;quot; viene eseguita in mutua esclusione, quindi non ci puo' essere &amp;quot;un lettore lento che sia riuscito ad entrare&amp;quot; nella funione startread. Se ha superato la P(mutex) iniziale o e' bloccato sulla ok2read o e' entrato. [[User:Renzo|Renzo]] ([[User talk:Renzo|talk]]) 19:37, 13 November 2016 (CET)&lt;/div&gt;</summary>
		<author><name>GabrieleCalarota</name></author>
	</entry>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=Zibaldone&amp;diff=1714</id>
		<title>Zibaldone</title>
		<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php?title=Zibaldone&amp;diff=1714"/>
		<updated>2016-12-15T15:53:31Z</updated>

		<summary type="html">&lt;p&gt;GabrieleCalarota: /* Monitor: Ponte a senso Unico */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Monitor: Ponte a senso Unico ==&lt;br /&gt;
Proposta di soluzione: esercizio 1 esame 22/01/2014&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
//&lt;br /&gt;
//  20140122_bridge&lt;br /&gt;
//&lt;br /&gt;
/*   Esercizio c.1:&lt;br /&gt;
 *&lt;br /&gt;
 *   Per colpa delle frane un ponte veicolare e' rimasto danneggiato.&lt;br /&gt;
 *   I veicoli possono ora percorrerlo solo in senso unico alternato e, per non eccedere la portata,&lt;br /&gt;
 *   al piu' ci possono essere sul ponte N veicoli contemporaneamente.&lt;br /&gt;
 *   Scrivere il monitor bridge sapendo che i veicoli chiameranno il monitor prima di entrare nel&lt;br /&gt;
 *   ponte e dopo averlo attraversato.&lt;br /&gt;
 *   I veicoli che entrano dal lato est escono dal lato ovest e viceversa.&lt;br /&gt;
 *   Quindi i (numerosi) veicoli eseguiranno uno dei due frammenti di codice seguenti:&lt;br /&gt;
 *&lt;br /&gt;
 *&lt;br /&gt;
 *   bridge.enter(E)                      bridge.enter(W)&lt;br /&gt;
 *   //cross the bridge                   //cross the bridge&lt;br /&gt;
 *   bridge.exit(W)                       bridge.exit(E)&lt;br /&gt;
 *&lt;br /&gt;
 *&lt;br /&gt;
 *   La soluzione proposta deve evitare deadlock e deve essere efficiente.&lt;br /&gt;
 *   (controesempio: una soluzione che prevedesse l'attraversamento del ponte da parte di un solo veicolo alla volta&lt;br /&gt;
 *   sebbene rispetti tutti i vincoli sarebbe considerata errata poiche' inefficiente).&lt;br /&gt;
 *   Oltre al codice si richiede una descrizione degli accorgimenti adottati per rendere la soluzione efficiente.&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;quot;monitor.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
#define CAPACITY 7 //capacità del bridge&lt;br /&gt;
#define BALANCE 9  &lt;br /&gt;
#define NCAR 15&lt;br /&gt;
&lt;br /&gt;
enum dest{&lt;br /&gt;
    E = 0,&lt;br /&gt;
    W = 1&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
int ncrossing_we = 0; //n car che stanno attraversando il bridge da W-&amp;gt;E&lt;br /&gt;
int ncrossing_ew = 0; //n car che stanno attraversando il bridge da E-&amp;gt;W&lt;br /&gt;
&lt;br /&gt;
int nwaiting_we = 0; //n car che aspettano di attraversare da W-&amp;gt;E&lt;br /&gt;
int nwaiting_ew = 0;  //n car che aspettano di attraversare da E-&amp;gt;W&lt;br /&gt;
&lt;br /&gt;
int priority = BALANCE;&lt;br /&gt;
&lt;br /&gt;
int crossed_we = 0; //n volte che il ponte è stato attraversato da W-&amp;gt;E&lt;br /&gt;
int crossed_ew = 0; //n volte che il ponte è stato attraversato da E-&amp;gt;W&lt;br /&gt;
&lt;br /&gt;
condition ok2goW; // capacity &amp;gt; 0 &amp;amp;&amp;amp; (ncrossing_ew == 0 || priority &amp;gt; 0)&lt;br /&gt;
condition ok2goE; // capacity &amp;gt; 0 &amp;amp;&amp;amp; (ncrossing_we == 0 || prioriti &amp;gt; 0 )&lt;br /&gt;
monitor bridge;&lt;br /&gt;
&lt;br /&gt;
void bridge_create(void){&lt;br /&gt;
    bridge = monitor_create();&lt;br /&gt;
    ok2goW = condition_create(bridge);&lt;br /&gt;
    ok2goE = condition_create(bridge);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void bridge_enter(enum dest d){&lt;br /&gt;
    monitor_enter(bridge);&lt;br /&gt;
    if (d == W) {&lt;br /&gt;
        nwaiting_we++;&lt;br /&gt;
        if (ncrossing_we &amp;gt;= CAPACITY || ncrossing_ew &amp;gt; 0 || (nwaiting_ew &amp;gt; 0 &amp;amp;&amp;amp; priority &amp;lt;= 0)) {&lt;br /&gt;
            condition_wait(ok2goW);&lt;br /&gt;
        }&lt;br /&gt;
        priority--;&lt;br /&gt;
        nwaiting_we--;&lt;br /&gt;
        ncrossing_we++;&lt;br /&gt;
        if (ncrossing_we &amp;lt; CAPACITY &amp;amp;&amp;amp; priority &amp;gt; 0) {&lt;br /&gt;
            condition_signal(ok2goW);&lt;br /&gt;
        }&lt;br /&gt;
    }else if(d == E){&lt;br /&gt;
        nwaiting_ew++;&lt;br /&gt;
        if (ncrossing_ew &amp;gt;= CAPACITY || ncrossing_we &amp;gt; 0 || (nwaiting_we &amp;gt; 0 &amp;amp;&amp;amp; priority &amp;lt;= 0)){&lt;br /&gt;
            condition_wait(ok2goE);&lt;br /&gt;
        }&lt;br /&gt;
        priority--;&lt;br /&gt;
        nwaiting_ew--;&lt;br /&gt;
        ncrossing_ew++;&lt;br /&gt;
        if (ncrossing_ew &amp;lt; CAPACITY &amp;amp;&amp;amp; priority &amp;gt; 0) {&lt;br /&gt;
            condition_signal(ok2goE);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    monitor_exit(bridge);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void bridge_exit(enum dest d){&lt;br /&gt;
    monitor_enter(bridge);&lt;br /&gt;
    if (d == E) {&lt;br /&gt;
        ncrossing_we--;&lt;br /&gt;
        crossed_we++;&lt;br /&gt;
        if (ncrossing_we &amp;lt; CAPACITY &amp;amp;&amp;amp; nwaiting_we &amp;gt; 0 &amp;amp;&amp;amp; (nwaiting_ew == 0 || priority &amp;gt; 0)) {&lt;br /&gt;
            condition_signal(ok2goW);&lt;br /&gt;
        }else if (ncrossing_we == 0 &amp;amp;&amp;amp; nwaiting_ew &amp;gt; 0 ) {&lt;br /&gt;
            priority = BALANCE;&lt;br /&gt;
            condition_signal(ok2goE);&lt;br /&gt;
        }&lt;br /&gt;
    } else if (d == W){&lt;br /&gt;
        ncrossing_ew--;&lt;br /&gt;
        crossed_ew++;&lt;br /&gt;
        if (ncrossing_ew &amp;lt; CAPACITY &amp;amp;&amp;amp; nwaiting_ew &amp;gt; 0 &amp;amp;&amp;amp; (nwaiting_we == 0 || priority &amp;gt; 0)) {&lt;br /&gt;
            condition_signal(ok2goE);&lt;br /&gt;
        }else if (ncrossing_ew == 0 &amp;amp;&amp;amp; nwaiting_we &amp;gt; 0) {&lt;br /&gt;
            priority = BALANCE;&lt;br /&gt;
            condition_signal(ok2goW);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    monitor_exit(bridge);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void *crossEW(void* arg){&lt;br /&gt;
    while (1) {&lt;br /&gt;
        printf(&amp;quot;waitW: %d |-|%d|-&amp;gt;  &amp;lt;-|%d|-| waitE: %d  || crossed W-&amp;gt;E: %d crossed E-&amp;gt;W: %d||\n&amp;quot;, nwaiting_we, ncrossing_we, ncrossing_ew, nwaiting_ew, crossed_we, crossed_ew);&lt;br /&gt;
        usleep(random() % 200000);&lt;br /&gt;
        bridge_enter(E);&lt;br /&gt;
        usleep(random() % 20000);&lt;br /&gt;
        bridge_exit(W);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void *crossWE(void* arg){&lt;br /&gt;
    while (1) {&lt;br /&gt;
        printf(&amp;quot;waitW: %d |-|%d|-&amp;gt;  &amp;lt;-|%d|-| waitE: %d  || crossed W-&amp;gt;E: %d crossed E-&amp;gt;W: %d||\n&amp;quot;, nwaiting_we, ncrossing_we, ncrossing_ew, nwaiting_ew, crossed_we, crossed_ew);&lt;br /&gt;
        usleep(random() % 200000);&lt;br /&gt;
        bridge_enter(W);&lt;br /&gt;
        usleep(random() % 20000);&lt;br /&gt;
        bridge_exit(E);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main(int argc, const char * argv[]) {&lt;br /&gt;
    pthread_t e_w_t[NCAR];&lt;br /&gt;
    pthread_t w_e_t[NCAR];&lt;br /&gt;
    bridge_create();&lt;br /&gt;
&lt;br /&gt;
    srandom(time(NULL));&lt;br /&gt;
    for (int i = 0; i &amp;lt; NCAR; i++) {&lt;br /&gt;
        pthread_create(&amp;amp;e_w_t[i], NULL, crossEW, NULL);&lt;br /&gt;
        pthread_create(&amp;amp;w_e_t[i], NULL, crossWE, NULL);&lt;br /&gt;
&lt;br /&gt;
    }&lt;br /&gt;
    for (int i = 0; i &amp;lt; NCAR; i++) {&lt;br /&gt;
        pthread_join(w_e_t[i], NULL);&lt;br /&gt;
        pthread_join(e_w_t[i], NULL);&lt;br /&gt;
    }&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Dal testo dell'esercizio si evincono le seguenti condizioni basilari per poter attraversare il ponte:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
   (capacità&amp;gt;0 &amp;amp;&amp;amp; ncrossing_OppositeDirection == 0)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Per rendere la soluzione efficiente ho introdotto, così, la variabile priority settata al valore BALANCE ottenendo la seguente condizione:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
priority &amp;gt; 0 || nwaitingOppositeDirection == 0; &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
e.i. fin quando il mio senso (e.g. W-&amp;gt;E) ha ancora priorità di attraversare  O non ci sono macchine nella &lt;br /&gt;
direzione opposta che attendono, continuo a dare il via alle macchine che vanno nella mia stessa direzione.&lt;br /&gt;
Priority viene decrementata ad ogni macchina che attraversa il ponte.&lt;br /&gt;
&lt;br /&gt;
Non appena tale condizione viene interrotta, priority viene restaurata al valore BALANCE e la sua gestione viene ceduta al senso opposto.&lt;br /&gt;
Notare che anche questa soluzione non gestisce il caso in cui &amp;quot;il mio senso ha priorità ma non c'è nessuno che vuole attraversare&amp;quot;, &lt;br /&gt;
sarebbe inutile far attendere e maccchine della direzione opposta.&lt;br /&gt;
Allora il tutto viene gestito come segue:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
   bridge.enter()&lt;br /&gt;
    if (ncrossing_MyDirection &amp;lt;= CAPACITY &amp;amp;&amp;amp; ncrossing_OppositeDirection == 0 &amp;amp;&amp;amp; (mypriority &amp;gt; 0 || nwaitingOppositeDirection == 0)){&lt;br /&gt;
					 attraverso il ponte;&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
    bridge.exit()&lt;br /&gt;
	if (ncrossing_MyDirection &amp;lt; CAPACITY &amp;amp;&amp;amp; nwaiting_MyDirection &amp;gt; 0 &amp;amp;&amp;amp; (nwaiting_OppositeDirection == 0 || mypriority &amp;gt; 0)) {&lt;br /&gt;
            		do il via a chi attende di attraversare nella mia stessa direzione;&lt;br /&gt;
        }else if (ncrossing_MyDirection == 0 &amp;amp;&amp;amp; nwaiting_OppositeDirection &amp;gt; 0 ) {&lt;br /&gt;
            		restauro priority e lascio il comando alle macchine nella direzione opposta;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
L’ultima possibilità è che nessuno vuole attraversare il bridge, in questo caso nn faccio nulla. &lt;br /&gt;
Il comando resta alla direzione che per ultima ha attraversato il bridge&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;monitor.h&amp;gt;&lt;br /&gt;
#include &amp;lt;pthread.h&amp;gt;&lt;br /&gt;
#include &amp;lt;string.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
const int NCAR_E=8;&lt;br /&gt;
const int NCAR_W=8;&lt;br /&gt;
const int MAX_CAR = 7;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
enum dir{E,W,N};&lt;br /&gt;
int n_carcross = 0;&lt;br /&gt;
int waiting[2] = {0,0}; //[0] = [E] ; [1] = [W]&lt;br /&gt;
enum dir curr_dir = N; &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
monitor bridge;&lt;br /&gt;
condition ok2go[2];&lt;br /&gt;
&lt;br /&gt;
void bridge_create(){&lt;br /&gt;
	bridge = monitor_create();&lt;br /&gt;
	ok2go[0] = condition_create(bridge);&lt;br /&gt;
	ok2go[1] = condition_create(bridge);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void print_bridge(){&lt;br /&gt;
	if (curr_dir == E)&lt;br /&gt;
		printf(&amp;quot;%d W &amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;%d&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt; E %d\n&amp;quot;,waiting[1],n_carcross,waiting[0]);&lt;br /&gt;
	else&lt;br /&gt;
		printf(&amp;quot;%d W &amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;%d&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; E %d\n&amp;quot;,waiting[1],n_carcross,waiting[0]);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void bridge_enter(enum dir d){&lt;br /&gt;
	monitor_enter(bridge);&lt;br /&gt;
	int i = (int) d;&lt;br /&gt;
	if (curr_dir == N){&lt;br /&gt;
		curr_dir = d;&lt;br /&gt;
	}&lt;br /&gt;
	if ((curr_dir != d) || (n_carcross &amp;gt;= MAX_CAR) || (waiting[1-i]&amp;gt;0)){&lt;br /&gt;
			waiting[i]++;&lt;br /&gt;
			condition_wait(ok2go[i]);&lt;br /&gt;
			waiting[i]--;&lt;br /&gt;
	}&lt;br /&gt;
	n_carcross++;&lt;br /&gt;
	print_bridge();&lt;br /&gt;
	if (n_carcross &amp;lt; MAX_CAR){&lt;br /&gt;
		if (waiting[i]&amp;gt;0)&lt;br /&gt;
			condition_signal(ok2go[i]);&lt;br /&gt;
	}&lt;br /&gt;
	monitor_exit(bridge);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void bridge_exit(enum dir d){&lt;br /&gt;
 monitor_enter(bridge);&lt;br /&gt;
 int i = (int) d;&lt;br /&gt;
 n_carcross--;&lt;br /&gt;
 print_bridge();&lt;br /&gt;
 if (waiting[i]&amp;gt;0){&lt;br /&gt;
 	if (n_carcross == 0){&lt;br /&gt;
 		curr_dir = (enum dir) (1 - curr_dir);&lt;br /&gt;
 		condition_signal(ok2go[i]);&lt;br /&gt;
 	}&lt;br /&gt;
 }&lt;br /&gt;
 else&lt;br /&gt;
       If (waiting [1-i]&amp;gt;0)&lt;br /&gt;
 	   condition_signal(ok2go[1-i]);&lt;br /&gt;
       Else &lt;br /&gt;
           curr_dir = N; &lt;br /&gt;
 monitor_exit(bridge);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void *cross(void* arg){&lt;br /&gt;
	enum dir d = (enum dir) arg;&lt;br /&gt;
	while (1) {&lt;br /&gt;
	        usleep(random() % 2000000);&lt;br /&gt;
	        bridge_enter(d);&lt;br /&gt;
	        usleep(random() % 2000000);&lt;br /&gt;
	        bridge_exit((enum dir)(1-d));&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main(int argc, const char * argv[]) {&lt;br /&gt;
    pthread_t e_t[NCAR_E];&lt;br /&gt;
    pthread_t w_t[NCAR_W];&lt;br /&gt;
    &lt;br /&gt;
    bridge_create();&lt;br /&gt;
 &lt;br /&gt;
    srandom(time(NULL));&lt;br /&gt;
&lt;br /&gt;
    for (int i = 0; i &amp;lt; NCAR_E; i++) {&lt;br /&gt;
        pthread_create(&amp;amp;e_t[i], NULL, cross,(void*) E); &lt;br /&gt;
    }&lt;br /&gt;
    for (int i = 0; i &amp;lt; NCAR_W; i++) {&lt;br /&gt;
        pthread_create(&amp;amp;w_t[i], NULL, cross, (void*) W);&lt;br /&gt;
    }&lt;br /&gt;
    for (int i = 0; i &amp;lt; NCAR_E; i++) {&lt;br /&gt;
        pthread_join(e_t[i], NULL);&lt;br /&gt;
    }&lt;br /&gt;
    for (int i = 0; i &amp;lt; NCAR_W; i++) {&lt;br /&gt;
        pthread_join(w_t[i], NULL);&lt;br /&gt;
    }&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Questa è la prima soluzione che mi è venuta in mente cercando di rimanere sul più semplice possibile ... ho adottato alcuni accorgimenti per evitare di avere un programma lungo ma con &amp;quot;doppioni&amp;quot; --[[User:GabrieleCalarota|GabrieleCalarota]] ([[User talk:GabrieleCalarota|talk]]) 18:35, 14 December 2016 (CET)&lt;br /&gt;
&lt;br /&gt;
== Monitor: Cospirazione dei filosofi ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;monitor.h&amp;gt;&lt;br /&gt;
#include &amp;lt;pthread.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdint.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
monitor dp;&lt;br /&gt;
condition philo_wait[5]; /* status[np(i,1)] == 'T' &amp;amp;&amp;amp; status[np(i,-1)] == 'T' */&lt;br /&gt;
char status[] = &amp;quot;TTTTT&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
int np(int i, int off) {&lt;br /&gt;
        return (i+5+off) % 5;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void dp_create(void) {&lt;br /&gt;
        int i;&lt;br /&gt;
        dp = monitor_create();&lt;br /&gt;
        for (i=0; i&amp;lt;5; i++)&lt;br /&gt;
                philo_wait[i] = condition_create(dp);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void dp_starteat(int i) {&lt;br /&gt;
        monitor_enter(dp);&lt;br /&gt;
        if (status[np(i,1)] != 'T' || status[np(i,-1)] != 'T')&lt;br /&gt;
                condition_wait(philo_wait[i]);&lt;br /&gt;
        status[i] = 'E';&lt;br /&gt;
        printf(&amp;quot;%s\n&amp;quot;,status);&lt;br /&gt;
        monitor_exit(dp);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void dp_endeat(int i) {&lt;br /&gt;
        monitor_enter(dp);&lt;br /&gt;
        status[i] = 'T';&lt;br /&gt;
        printf(&amp;quot;%s\n&amp;quot;,status);&lt;br /&gt;
        if (status[np(i,2)] == 'T')&lt;br /&gt;
                condition_signal(philo_wait[np(i,1)]);&lt;br /&gt;
        if (status[np(i,-2)] == 'T')&lt;br /&gt;
                condition_signal(philo_wait[np(i,-1)]);&lt;br /&gt;
        monitor_exit(dp);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
monitor cospy;&lt;br /&gt;
condition wait2eat;&lt;br /&gt;
int cospy_count;&lt;br /&gt;
&lt;br /&gt;
void cospy_create(void) {&lt;br /&gt;
        cospy = monitor_create();&lt;br /&gt;
        wait2eat = condition_create(cospy);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void cospy_starteat(void) {&lt;br /&gt;
        monitor_enter(cospy);&lt;br /&gt;
        cospy_count++;&lt;br /&gt;
        condition_signal(wait2eat);&lt;br /&gt;
        monitor_exit(cospy);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void cospy_endeat(void) {&lt;br /&gt;
        monitor_enter(cospy);&lt;br /&gt;
        cospy_count--;&lt;br /&gt;
        if (cospy_count == 0)&lt;br /&gt;
                condition_wait(wait2eat);&lt;br /&gt;
        monitor_exit(cospy);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void *philo(void *arg) {&lt;br /&gt;
        int i = (uintptr_t) arg;&lt;br /&gt;
        while (1) {&lt;br /&gt;
                usleep(random() % 2000000);&lt;br /&gt;
                dp_starteat(i);&lt;br /&gt;
                if (i == 1 || i == 3)&lt;br /&gt;
                        cospy_starteat();&lt;br /&gt;
                usleep(random() % 2000000);&lt;br /&gt;
                if (i == 1 || i == 3)&lt;br /&gt;
                        cospy_endeat();&lt;br /&gt;
                dp_endeat(i);&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char *argv[]) {&lt;br /&gt;
        pthread_t philo_t[5];&lt;br /&gt;
        uintptr_t i;&lt;br /&gt;
        dp_create();&lt;br /&gt;
        cospy_create();&lt;br /&gt;
        srandom(time(NULL));&lt;br /&gt;
        for (i=0; i&amp;lt;5; i++)&lt;br /&gt;
                pthread_create(&amp;amp;philo_t[i], NULL, philo, (void *) i );&lt;br /&gt;
        while(1)&lt;br /&gt;
                pause();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
--[[User:FedericoB|FedericoB]] ([[User talk:FedericoB|talk]]) 11:27, 25 November 2016 (CET)Veniva creata la condizione di cospirazione collegata al monitor dp invece che cospy. Quindi con il signal il processo veniva messo nell'urgent stack sbagliato e chiamando monitor_exit su cospy non si risvegliava il processo nell' urgent stack di dp.&lt;br /&gt;
&lt;br /&gt;
== RW errato ==&lt;br /&gt;
Codice '''ERRATO''' dei lettori scrittori che dovrebbe non soffrire di problemi di starvation...&lt;br /&gt;
Esercizio: trovare gli errori.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
#include&amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include&amp;lt;stdint.h&amp;gt;&lt;br /&gt;
#include&amp;lt;pthread.h&amp;gt;&lt;br /&gt;
#include&amp;lt;semaphore.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define NREADER 3&lt;br /&gt;
#define NWRITER 3&lt;br /&gt;
semaphore mutex;&lt;br /&gt;
semaphore ok2read;&lt;br /&gt;
semaphore ok2write;&lt;br /&gt;
&lt;br /&gt;
int nr=0;&lt;br /&gt;
int nw=0;&lt;br /&gt;
int wr=0;&lt;br /&gt;
int ww=0;&lt;br /&gt;
int w_last;&lt;br /&gt;
&lt;br /&gt;
// (nw == 0 &amp;amp;&amp;amp; nr == 0) || (nr &amp;gt; 0 &amp;amp;&amp;amp; nw == 0) || nw == 1&lt;br /&gt;
// (nw == 0 &amp;amp;&amp;amp; nr &amp;gt;= 0) || nw == 1&lt;br /&gt;
&lt;br /&gt;
// this &amp;quot;baton&amp;quot; function has been left for reference only.&lt;br /&gt;
// code to implement &amp;quot;passing the baton&amp;quot; has been copied at the end of&lt;br /&gt;
// each ({start}|{end})({read}|{write}) function and reduced.&lt;br /&gt;
void baton(void) {&lt;br /&gt;
        if (nw == 0 &amp;amp;&amp;amp; nr == 0 &amp;amp;&amp;amp; ww &amp;gt; 0)&lt;br /&gt;
                semaphore_V(ok2write);&lt;br /&gt;
        else if (nw == 0 &amp;amp;&amp;amp; wr &amp;gt; 0 )&lt;br /&gt;
                semaphore_V(ok2read);&lt;br /&gt;
        else&lt;br /&gt;
                semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void startread(void) {&lt;br /&gt;
// &amp;lt;await nw == 0 -&amp;gt; nr++&amp;gt;&lt;br /&gt;
        semaphore_P(mutex);&lt;br /&gt;
        if (nw &amp;gt; 0 &amp;amp;&amp;amp; ww == 0) {&lt;br /&gt;
                wr++;&lt;br /&gt;
                semaphore_V(mutex);&lt;br /&gt;
                semaphore_P(ok2read);&lt;br /&gt;
                wr--;&lt;br /&gt;
        }&lt;br /&gt;
        nr++;&lt;br /&gt;
        w_last=0;&lt;br /&gt;
        printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, nr, nw, wr, ww);&lt;br /&gt;
        if (wr &amp;gt; 0 )&lt;br /&gt;
                semaphore_V(ok2read);&lt;br /&gt;
        else&lt;br /&gt;
                semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void endread(void) {&lt;br /&gt;
// &amp;lt;nr--&amp;gt;&lt;br /&gt;
        semaphore_P(mutex);&lt;br /&gt;
        nr--;&lt;br /&gt;
        printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, nr, nw, wr, ww);&lt;br /&gt;
        if (nr == 0 &amp;amp;&amp;amp; ww &amp;gt; 0)&lt;br /&gt;
                semaphore_V(ok2write);&lt;br /&gt;
        else&lt;br /&gt;
                semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void startwrite(void) {&lt;br /&gt;
// &amp;lt;await nw == 0 &amp;amp;&amp;amp; nr == 0 -&amp;gt; nw++&amp;gt;&lt;br /&gt;
        semaphore_P(mutex);&lt;br /&gt;
        if (nw &amp;gt; 0 || nr &amp;gt; 0) {&lt;br /&gt;
                ww++;&lt;br /&gt;
                semaphore_V(mutex);&lt;br /&gt;
                semaphore_P(ok2write);&lt;br /&gt;
                ww--;&lt;br /&gt;
        }&lt;br /&gt;
        nw++;&lt;br /&gt;
        w_last=1;&lt;br /&gt;
        printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, nr, nw, wr, ww);&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void endwrite(void) {&lt;br /&gt;
// &amp;lt;nw--&amp;gt;&lt;br /&gt;
        semaphore_P(mutex);&lt;br /&gt;
        nw--;&lt;br /&gt;
        printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, nr, nw, wr, ww);&lt;br /&gt;
        if (wr &amp;gt; 0 &amp;amp;&amp;amp; (ww == 0 || w_last))&lt;br /&gt;
                semaphore_V(ok2read);&lt;br /&gt;
        else if (ww &amp;gt; 0 &amp;amp;&amp;amp; (wr == 0 || !w_last))&lt;br /&gt;
                semaphore_V(ok2write);&lt;br /&gt;
        else&lt;br /&gt;
                semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void *reader(void *arg) {&lt;br /&gt;
        int i = (uintptr_t)arg;&lt;br /&gt;
        while (1) {&lt;br /&gt;
                //other code&lt;br /&gt;
                usleep(random() % 200000);&lt;br /&gt;
                startread();&lt;br /&gt;
                //read&lt;br /&gt;
                usleep(random() % 200000);&lt;br /&gt;
                endread();&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void *writer(void *arg) {&lt;br /&gt;
        int i = (uintptr_t)arg;&lt;br /&gt;
        while (1) {&lt;br /&gt;
                //other code&lt;br /&gt;
                usleep(random() % 200000);&lt;br /&gt;
                startwrite();&lt;br /&gt;
                //write&lt;br /&gt;
                usleep(random() % 200000);&lt;br /&gt;
                endwrite();&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//printf(&amp;quot;philo thinking: %d\n&amp;quot;,i);&lt;br /&gt;
/*while*/&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char *argv[]) {&lt;br /&gt;
        int i;&lt;br /&gt;
        pthread_t t;&lt;br /&gt;
        srandom(time(NULL));&lt;br /&gt;
        mutex=semaphore_create(1);&lt;br /&gt;
        ok2read=semaphore_create(0);&lt;br /&gt;
        ok2write=semaphore_create(0);&lt;br /&gt;
        for (i=0; i&amp;lt;NREADER; i++)&lt;br /&gt;
                pthread_create(&amp;amp;t, NULL, reader, (void *)(uintptr_t) i);&lt;br /&gt;
        for (i=0; i&amp;lt;NWRITER; i++)&lt;br /&gt;
                pthread_create(&amp;amp;t, NULL, writer, (void *)(uintptr_t) i);&lt;br /&gt;
        while(1)&lt;br /&gt;
                pause();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== RW di FedericoB ==&lt;br /&gt;
Propongo la seguente soluzione. Mi sembra che funzioni ma devo ancora capire perchè e documentarla bene. Ho provato prima a cercare il bug ma non ci sono riuscito. Ho quindi modificato il codice secondo ciò che mi sembrava sensato in base alle condizioni del problema. Ne possiamo parlare in aula oggi. --[[User:FedericoB|FedericoB]] ([[User talk:FedericoB|talk]]) 12:48, 11 November 2016 (CET)&lt;br /&gt;
Ho notato che l'errore non si manifesta più eliminando il controllo che ci siano scrittori in attesa quando un lettore vuole iniziare a scrivere. Non capisco come questo possa essere collegato al bug. --[[User:FedericoB|FedericoB]] ([[User talk:FedericoB|talk]]) 15:10, 11 November 2016 (CET)&lt;br /&gt;
&lt;br /&gt;
FedericoB, questa soluzione &amp;amp;egrave; quella con priorit&amp;amp;agrave; ai lettori, no? Se continuano ad arrivare lettori numberOfReaders non sar&amp;amp;agrave; mai zero e quindi gli scrittori non scriveranno mai. [[User:Renzo|Renzo]] ([[User talk:Renzo|talk]]) 10:34, 12 November 2016 (CET)&lt;br /&gt;
&lt;br /&gt;
SFIDA: ho trovato il modo di togliere la starvation aggiungendo 4 token (parole chiave, nomi di variabili, operatori, costanti) a questa soluzione di FedericoB. Chi trova la soluzione? [[User:Renzo|Renzo]] ([[User talk:Renzo|talk]]) 10:43, 12 November 2016 (CET) Ah! ho appena trovato una soluzione che prevede 2 soli token in pi&amp;amp;ugrave;! [[User:Renzo|Renzo]] ([[User talk:Renzo|talk]]) 10:47, 12 November 2016 (CET)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
#include&amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include&amp;lt;stdint.h&amp;gt;&lt;br /&gt;
#include&amp;lt;pthread.h&amp;gt;&lt;br /&gt;
#include&amp;lt;semaphore.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define NUMBER_OF_READERS 3&lt;br /&gt;
#define NUMBER_OF_WRITERS 3&lt;br /&gt;
semaphore mutex;&lt;br /&gt;
semaphore ok2read;&lt;br /&gt;
semaphore ok2write;&lt;br /&gt;
&lt;br /&gt;
int numberOfReaders=0;&lt;br /&gt;
int numberOfWriters=0;&lt;br /&gt;
int waitingReaders=0;&lt;br /&gt;
int waitingWriters=0;&lt;br /&gt;
&lt;br /&gt;
// (nw == 0 &amp;amp;&amp;amp; nr == 0) || (nr &amp;gt; 0 &amp;amp;&amp;amp; nw == 0) || nw == 1&lt;br /&gt;
// (nw == 0 &amp;amp;&amp;amp; nr &amp;gt;= 0) || nw == 1&lt;br /&gt;
&lt;br /&gt;
void startread(void) {&lt;br /&gt;
// &amp;lt;await nw == 0 -&amp;gt; nr++&amp;gt;&lt;br /&gt;
    semaphore_P(mutex);&lt;br /&gt;
    if (numberOfWriters &amp;gt; 0) {&lt;br /&gt;
        waitingReaders++;&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
        semaphore_P(ok2read);&lt;br /&gt;
        waitingReaders--;&lt;br /&gt;
    }&lt;br /&gt;
    numberOfReaders++;&lt;br /&gt;
    printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, numberOfReaders, numberOfWriters, waitingReaders, waitingWriters);&lt;br /&gt;
    if (waitingReaders &amp;gt; 0 )&lt;br /&gt;
        semaphore_V(ok2read);&lt;br /&gt;
    else&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void endread(void) {&lt;br /&gt;
// &amp;lt;nr--&amp;gt;&lt;br /&gt;
    semaphore_P(mutex);&lt;br /&gt;
    numberOfReaders--;&lt;br /&gt;
    printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, numberOfReaders, numberOfWriters, waitingReaders, waitingWriters);&lt;br /&gt;
    if (numberOfReaders == 0 &amp;amp;&amp;amp; waitingWriters &amp;gt; 0)&lt;br /&gt;
        semaphore_V(ok2write);&lt;br /&gt;
    else&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void startwrite(void) {&lt;br /&gt;
// &amp;lt;await nw == 0 &amp;amp;&amp;amp; nr == 0 -&amp;gt; nw++&amp;gt;&lt;br /&gt;
    semaphore_P(mutex);&lt;br /&gt;
    if (numberOfWriters &amp;gt; 0 || numberOfReaders &amp;gt; 0) {&lt;br /&gt;
        waitingWriters++;&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
        semaphore_P(ok2write);&lt;br /&gt;
        waitingWriters--;&lt;br /&gt;
    }&lt;br /&gt;
    numberOfWriters++;&lt;br /&gt;
    printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, numberOfReaders, numberOfWriters, waitingReaders, waitingWriters);&lt;br /&gt;
    semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void endwrite(void) {&lt;br /&gt;
// &amp;lt;nw--&amp;gt;&lt;br /&gt;
    semaphore_P(mutex);&lt;br /&gt;
    numberOfWriters--;&lt;br /&gt;
    printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, numberOfReaders, numberOfWriters, waitingReaders, waitingWriters);&lt;br /&gt;
    if (waitingReaders &amp;gt; 0)&lt;br /&gt;
        semaphore_V(ok2read);&lt;br /&gt;
    else if (waitingWriters &amp;gt; 0)&lt;br /&gt;
        semaphore_V(ok2write);&lt;br /&gt;
    else&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void *reader(void *arg) {&lt;br /&gt;
    int i = (uintptr_t)arg;&lt;br /&gt;
    while (1) {&lt;br /&gt;
        //other code&lt;br /&gt;
        usleep(random() % 200000);&lt;br /&gt;
        startread();&lt;br /&gt;
        //read&lt;br /&gt;
        usleep(random() % 200000);&lt;br /&gt;
        endread();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void *writer(void *arg) {&lt;br /&gt;
    int i = (uintptr_t)arg;&lt;br /&gt;
    while (1) {&lt;br /&gt;
        //other code&lt;br /&gt;
        usleep(random() % 200000);&lt;br /&gt;
        startwrite();&lt;br /&gt;
        //write&lt;br /&gt;
        usleep(random() % 200000);&lt;br /&gt;
        endwrite();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//printf(&amp;quot;philo thinking: %d\n&amp;quot;,i);&lt;br /&gt;
/*while*/&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char *argv[]) {&lt;br /&gt;
    int i;&lt;br /&gt;
    pthread_t t;&lt;br /&gt;
    srandom(time(NULL));&lt;br /&gt;
    mutex=semaphore_create(1);&lt;br /&gt;
    ok2read=semaphore_create(0);&lt;br /&gt;
    ok2write=semaphore_create(0);&lt;br /&gt;
    for (i=0; i&amp;lt;NUMBER_OF_READERS; i++)&lt;br /&gt;
        pthread_create(&amp;amp;t, NULL, reader, (void *)(uintptr_t) i);&lt;br /&gt;
    for (i=0; i&amp;lt;NUMBER_OF_WRITERS; i++)&lt;br /&gt;
        pthread_create(&amp;amp;t, NULL, writer, (void *)(uintptr_t) i);&lt;br /&gt;
    while(1)&lt;br /&gt;
        pause();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== RW2 ==&lt;br /&gt;
Buongiorno, guardando il codice visto a lezione mi sembra che cambiando la condizione del primo if nella startread() da &amp;quot;if (nw &amp;gt; 0 &amp;amp;&amp;amp; ww == 0)&amp;quot; a &amp;quot;if (nw &amp;gt; 0 || ww &amp;gt; 0)&amp;quot; la situazione migliori. In particolare con l'and tra quelle due condizioni si aveva che non veniva fatta la P sull'ok2read anche quando si aveva nw&amp;gt;0 (con ww!=0), cosa che invece dovrebbe fare. Lasciando il resto del codice uguale mi sembra che faccia quello che deve fare.. .&lt;br /&gt;
&lt;br /&gt;
Matteo.pincherle: Perch&amp;amp;eacute; non modifichi in programma di FedericoB, lo provi e pubblichi qui la patch? [[User:Renzo|Renzo]] ([[User talk:Renzo|talk]]) 10:42, 13 November 2016 (CET)&lt;br /&gt;
&lt;br /&gt;
'''Perchè quel AND permetteva di avere 2 scrittori?''' &amp;lt;br&amp;gt;&lt;br /&gt;
Permetteva in primis di avere dei lettori in contemporanea a uno scrittore. In quanto se succedeva che un lettore volesse entrare mentre non c'erano degli scrittori in attesa ma scrittori in scrittura, veniva saltato il blocco che mandava il lettore in attesa e risultava un lettore in contemporanea a uno scrittore. &amp;lt;br&amp;gt;&lt;br /&gt;
Questo lettore poi poteva finire di leggere prima che lo scrittore in contemporanea a lui finisse di scrivere. &amp;lt;br&amp;gt;&lt;br /&gt;
Il lettore in uscita se non c'erano altri lettori con lui e non c'erano scrittori in attesa dava il permesso per far accedere un altro scrittore. &amp;lt;br&amp;gt;&lt;br /&gt;
A questo punto un altro scrittore che avesse voluto entrare poteva entrare, con il risultato di avere 2 scrittori in contemporanea.&lt;br /&gt;
--[[User:FedericoB|FedericoB]] ([[User talk:FedericoB|talk]]) 19:25, 13 November 2016 (CET)&lt;br /&gt;
&lt;br /&gt;
== Patch ==&lt;br /&gt;
Così, se non sbaglio, quando c'è almeno uno scrittore in attesa non lascia entrare altri lettori. Fa esaurire la lettura dei presenti e poi lascia scrivere lo scrittore.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include&amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include&amp;lt;stdint.h&amp;gt;&lt;br /&gt;
#include&amp;lt;pthread.h&amp;gt;&lt;br /&gt;
#include&amp;lt;semaphore.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define NUMBER_OF_READERS 3&lt;br /&gt;
#define NUMBER_OF_WRITERS 3&lt;br /&gt;
semaphore mutex;&lt;br /&gt;
semaphore ok2read;&lt;br /&gt;
semaphore ok2write;&lt;br /&gt;
&lt;br /&gt;
int numberOfReaders=0;&lt;br /&gt;
int numberOfWriters=0;&lt;br /&gt;
int waitingReaders=0;&lt;br /&gt;
int waitingWriters=0;&lt;br /&gt;
int w_last;&lt;br /&gt;
&lt;br /&gt;
// (nw == 0 &amp;amp;&amp;amp; nr == 0) || (nr &amp;gt; 0 &amp;amp;&amp;amp; nw == 0) || nw == 1&lt;br /&gt;
// (nw == 0 &amp;amp;&amp;amp; nr &amp;gt;= 0) || nw == 1&lt;br /&gt;
&lt;br /&gt;
void startread(void) {&lt;br /&gt;
    // &amp;lt;await nw == 0 -&amp;gt; nr++&amp;gt;&lt;br /&gt;
    semaphore_P(mutex);&lt;br /&gt;
    if (numberOfWriters &amp;gt; 0 || waitingWriters&amp;gt;0) {&lt;br /&gt;
        waitingReaders++;&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
        semaphore_P(ok2read);&lt;br /&gt;
        waitingReaders--;&lt;br /&gt;
    }&lt;br /&gt;
    numberOfReaders++;&lt;br /&gt;
    w_last=0;&lt;br /&gt;
    printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, numberOfReaders, numberOfWriters, waitingReaders, waitingWriters);&lt;br /&gt;
    if (waitingReaders &amp;gt; 0 )&lt;br /&gt;
        semaphore_V(ok2read);&lt;br /&gt;
    else&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void endread(void) {&lt;br /&gt;
    // &amp;lt;nr--&amp;gt;&lt;br /&gt;
    semaphore_P(mutex);&lt;br /&gt;
    numberOfReaders--;&lt;br /&gt;
    printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, numberOfReaders, numberOfWriters, waitingReaders, waitingWriters);&lt;br /&gt;
    if (numberOfReaders == 0 &amp;amp;&amp;amp; waitingWriters &amp;gt; 0)&lt;br /&gt;
        semaphore_V(ok2write);&lt;br /&gt;
    else&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void startwrite(void) {&lt;br /&gt;
    // &amp;lt;await nw == 0 &amp;amp;&amp;amp; nr == 0 -&amp;gt; nw++&amp;gt;&lt;br /&gt;
    semaphore_P(mutex);&lt;br /&gt;
    if (numberOfWriters &amp;gt; 0 || numberOfReaders &amp;gt; 0) {&lt;br /&gt;
        waitingWriters++;&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
        semaphore_P(ok2write);&lt;br /&gt;
        waitingWriters--;&lt;br /&gt;
    }&lt;br /&gt;
    numberOfWriters++;&lt;br /&gt;
    w_last=1;&lt;br /&gt;
    printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, numberOfReaders, numberOfWriters, waitingReaders, waitingWriters);&lt;br /&gt;
    semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void endwrite(void) {&lt;br /&gt;
    // &amp;lt;nw--&amp;gt;&lt;br /&gt;
    semaphore_P(mutex);&lt;br /&gt;
    numberOfWriters--;&lt;br /&gt;
    printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, numberOfReaders, numberOfWriters, waitingReaders, waitingWriters);&lt;br /&gt;
    if (waitingReaders &amp;gt; 0 &amp;amp;&amp;amp; (waitingWriters==0 || w_last))&lt;br /&gt;
        semaphore_V(ok2read);&lt;br /&gt;
    else if (waitingWriters &amp;gt; 0 &amp;amp;&amp;amp; (waitingReaders==0 || !w_last))&lt;br /&gt;
        semaphore_V(ok2write);&lt;br /&gt;
    else&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void *reader(void *arg) {&lt;br /&gt;
    int i = (uintptr_t)arg;&lt;br /&gt;
    while (1) {&lt;br /&gt;
        //other code&lt;br /&gt;
        usleep(random() % 200000);&lt;br /&gt;
        startread();&lt;br /&gt;
        //read&lt;br /&gt;
        usleep(random() % 200000);&lt;br /&gt;
        endread();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void *writer(void *arg) {&lt;br /&gt;
    int i = (uintptr_t)arg;&lt;br /&gt;
    while (1) {&lt;br /&gt;
        //other code&lt;br /&gt;
        usleep(random() % 200000);&lt;br /&gt;
        startwrite();&lt;br /&gt;
        //write&lt;br /&gt;
        usleep(random() % 200000);&lt;br /&gt;
        endwrite();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char *argv[]) {&lt;br /&gt;
    int i;&lt;br /&gt;
    pthread_t t;&lt;br /&gt;
    srandom(time(NULL));&lt;br /&gt;
    mutex=semaphore_create(1);&lt;br /&gt;
    ok2read=semaphore_create(0);&lt;br /&gt;
    ok2write=semaphore_create(0);&lt;br /&gt;
    for (i=0; i&amp;lt;NUMBER_OF_READERS; i++)&lt;br /&gt;
        pthread_create(&amp;amp;t, NULL, reader, (void *)(uintptr_t) i);&lt;br /&gt;
    for (i=0; i&amp;lt;NUMBER_OF_WRITERS; i++)&lt;br /&gt;
        pthread_create(&amp;amp;t, NULL, writer, (void *)(uintptr_t) i);&lt;br /&gt;
    while(1)&lt;br /&gt;
        pause();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
wlast non serve pi&amp;amp;ugrave;... [[User:Renzo|Renzo]] ([[User talk:Renzo|talk]]) 17:52, 13 November 2016 (CET)&lt;br /&gt;
&lt;br /&gt;
== RW2bis ==&lt;br /&gt;
Nella tua soluzione se i lettori sono &amp;quot;molto veloci&amp;quot; e non vanno mai a 0, lo scrittore non inizierà mai a scrivere.&lt;br /&gt;
&lt;br /&gt;
Cioè: Uno scrittore viene svegliato da ok2write solo se passa la condizione &lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
[..] &lt;br /&gt;
if (numberofReaders == 0 &amp;amp;&amp;amp; waitingWriters &amp;gt;0) &lt;br /&gt;
     semaphore_V(ok2write);&lt;br /&gt;
[..]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; --[[User:GabrieleCalarota|GabrieleCalarota]] ([[User talk:GabrieleCalarota|talk]]) 17:46, 13 November 2016 (CET)&lt;br /&gt;
&lt;br /&gt;
Non direi perche' nella startread se:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
    if (numberOfWriters &amp;gt; 0 || waitingWriters&amp;gt;0) &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
i lettori si bloccano. Quindi se c'e' almeno uno scrittore in attesa i lettori non entrano (e quindi prima o poi terminano e lasciano il posto ad uno scrittore).&lt;br /&gt;
[[User:Renzo|Renzo]] ([[User talk:Renzo|talk]]) 17:57, 13 November 2016 (CET)&lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
Ho pensato al caso limite seguente:&lt;br /&gt;
Supponiamo che ci siano dei lettori che stanno leggendo e ad un certo punto uno scrittore chiede di scrivere.&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;syntaxhighlight lang=C&amp;gt;         &lt;br /&gt;
       void startread(void) {&lt;br /&gt;
    // &amp;lt;await nw == 0 -&amp;gt; nr++&amp;gt;&lt;br /&gt;
    semaphore_P(mutex);&lt;br /&gt;
    if (numberOfWriters &amp;gt; 0 || waitingWriters&amp;gt;0) {&lt;br /&gt;
        waitingReaders++;   //Nuovo scrittore (t1)&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
        semaphore_P(ok2read);&lt;br /&gt;
        waitingReaders--;&lt;br /&gt;
    }&lt;br /&gt;
    numberOfReaders++;&lt;br /&gt;
    w_last=0;&lt;br /&gt;
    printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, numberOfReaders, numberOfWriters, waitingReaders, waitingWriters);&lt;br /&gt;
   if (waitingReaders &amp;gt; 0 )   //Vecchio scrittore(t1)&lt;br /&gt;
        semaphore_V(ok2read);&lt;br /&gt;
    else&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Non appena lo scrittore rilascia il mutex, un nuovo lettore chiede di leggere (e si addormenterà). Un lettore (lento) che era riuscito a entrare nel segmento startofread prima che lo scrittore entrasse in startofwrite, continua a leggere e risveglia uno dei nuovi lettori. Se i lettori continuano a richiedere di leggere continuamente, verranno addormentati e subito risvegliati. &lt;br /&gt;
&lt;br /&gt;
E' da considerarsi possibile? --[[User:GabrieleCalarota|GabrieleCalarota]] ([[User talk:GabrieleCalarota|talk]]) 19:11, 13 November 2016 (CET)&lt;br /&gt;
&lt;br /&gt;
Suppongo che &amp;quot;un nuovo scrittore chiede di leggere&amp;quot; si aun refuso e sia da intendere &amp;quot;un nuovo lettore chiede di leggere&amp;quot; (altrimenti ci sono crisi di identit&amp;amp;agrave;) e che &amp;quot;startofread&amp;quot; significhi &amp;quot;startread&amp;quot; e &amp;quot;startofwrite&amp;quot;  sia &amp;quot;startwrite&amp;quot;.&lt;br /&gt;
La &amp;quot;startread&amp;quot; viene eseguita in mutua esclusione, quindi non ci puo' essere &amp;quot;un lettore lento che sia riuscito ad entrare&amp;quot; nella funione startread. Se ha superato la P(mutex) iniziale o e' bloccato sulla ok2read o e' entrato. [[User:Renzo|Renzo]] ([[User talk:Renzo|talk]]) 19:37, 13 November 2016 (CET)&lt;/div&gt;</summary>
		<author><name>GabrieleCalarota</name></author>
	</entry>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=Zibaldone&amp;diff=1713</id>
		<title>Zibaldone</title>
		<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php?title=Zibaldone&amp;diff=1713"/>
		<updated>2016-12-15T15:53:02Z</updated>

		<summary type="html">&lt;p&gt;GabrieleCalarota: /* == */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Monitor: Ponte a senso Unico ==&lt;br /&gt;
Proposta di soluzione: esercizio 1 esame 22/01/2014&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
//&lt;br /&gt;
//  20140122_bridge&lt;br /&gt;
//&lt;br /&gt;
/*   Esercizio c.1:&lt;br /&gt;
 *&lt;br /&gt;
 *   Per colpa delle frane un ponte veicolare e' rimasto danneggiato.&lt;br /&gt;
 *   I veicoli possono ora percorrerlo solo in senso unico alternato e, per non eccedere la portata,&lt;br /&gt;
 *   al piu' ci possono essere sul ponte N veicoli contemporaneamente.&lt;br /&gt;
 *   Scrivere il monitor bridge sapendo che i veicoli chiameranno il monitor prima di entrare nel&lt;br /&gt;
 *   ponte e dopo averlo attraversato.&lt;br /&gt;
 *   I veicoli che entrano dal lato est escono dal lato ovest e viceversa.&lt;br /&gt;
 *   Quindi i (numerosi) veicoli eseguiranno uno dei due frammenti di codice seguenti:&lt;br /&gt;
 *&lt;br /&gt;
 *&lt;br /&gt;
 *   bridge.enter(E)                      bridge.enter(W)&lt;br /&gt;
 *   //cross the bridge                   //cross the bridge&lt;br /&gt;
 *   bridge.exit(W)                       bridge.exit(E)&lt;br /&gt;
 *&lt;br /&gt;
 *&lt;br /&gt;
 *   La soluzione proposta deve evitare deadlock e deve essere efficiente.&lt;br /&gt;
 *   (controesempio: una soluzione che prevedesse l'attraversamento del ponte da parte di un solo veicolo alla volta&lt;br /&gt;
 *   sebbene rispetti tutti i vincoli sarebbe considerata errata poiche' inefficiente).&lt;br /&gt;
 *   Oltre al codice si richiede una descrizione degli accorgimenti adottati per rendere la soluzione efficiente.&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;quot;monitor.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
#define CAPACITY 7 //capacità del bridge&lt;br /&gt;
#define BALANCE 9  &lt;br /&gt;
#define NCAR 15&lt;br /&gt;
&lt;br /&gt;
enum dest{&lt;br /&gt;
    E = 0,&lt;br /&gt;
    W = 1&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
int ncrossing_we = 0; //n car che stanno attraversando il bridge da W-&amp;gt;E&lt;br /&gt;
int ncrossing_ew = 0; //n car che stanno attraversando il bridge da E-&amp;gt;W&lt;br /&gt;
&lt;br /&gt;
int nwaiting_we = 0; //n car che aspettano di attraversare da W-&amp;gt;E&lt;br /&gt;
int nwaiting_ew = 0;  //n car che aspettano di attraversare da E-&amp;gt;W&lt;br /&gt;
&lt;br /&gt;
int priority = BALANCE;&lt;br /&gt;
&lt;br /&gt;
int crossed_we = 0; //n volte che il ponte è stato attraversato da W-&amp;gt;E&lt;br /&gt;
int crossed_ew = 0; //n volte che il ponte è stato attraversato da E-&amp;gt;W&lt;br /&gt;
&lt;br /&gt;
condition ok2goW; // capacity &amp;gt; 0 &amp;amp;&amp;amp; (ncrossing_ew == 0 || priority &amp;gt; 0)&lt;br /&gt;
condition ok2goE; // capacity &amp;gt; 0 &amp;amp;&amp;amp; (ncrossing_we == 0 || prioriti &amp;gt; 0 )&lt;br /&gt;
monitor bridge;&lt;br /&gt;
&lt;br /&gt;
void bridge_create(void){&lt;br /&gt;
    bridge = monitor_create();&lt;br /&gt;
    ok2goW = condition_create(bridge);&lt;br /&gt;
    ok2goE = condition_create(bridge);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void bridge_enter(enum dest d){&lt;br /&gt;
    monitor_enter(bridge);&lt;br /&gt;
    if (d == W) {&lt;br /&gt;
        nwaiting_we++;&lt;br /&gt;
        if (ncrossing_we &amp;gt;= CAPACITY || ncrossing_ew &amp;gt; 0 || (nwaiting_ew &amp;gt; 0 &amp;amp;&amp;amp; priority &amp;lt;= 0)) {&lt;br /&gt;
            condition_wait(ok2goW);&lt;br /&gt;
        }&lt;br /&gt;
        priority--;&lt;br /&gt;
        nwaiting_we--;&lt;br /&gt;
        ncrossing_we++;&lt;br /&gt;
        if (ncrossing_we &amp;lt; CAPACITY &amp;amp;&amp;amp; priority &amp;gt; 0) {&lt;br /&gt;
            condition_signal(ok2goW);&lt;br /&gt;
        }&lt;br /&gt;
    }else if(d == E){&lt;br /&gt;
        nwaiting_ew++;&lt;br /&gt;
        if (ncrossing_ew &amp;gt;= CAPACITY || ncrossing_we &amp;gt; 0 || (nwaiting_we &amp;gt; 0 &amp;amp;&amp;amp; priority &amp;lt;= 0)){&lt;br /&gt;
            condition_wait(ok2goE);&lt;br /&gt;
        }&lt;br /&gt;
        priority--;&lt;br /&gt;
        nwaiting_ew--;&lt;br /&gt;
        ncrossing_ew++;&lt;br /&gt;
        if (ncrossing_ew &amp;lt; CAPACITY &amp;amp;&amp;amp; priority &amp;gt; 0) {&lt;br /&gt;
            condition_signal(ok2goE);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    monitor_exit(bridge);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void bridge_exit(enum dest d){&lt;br /&gt;
    monitor_enter(bridge);&lt;br /&gt;
    if (d == E) {&lt;br /&gt;
        ncrossing_we--;&lt;br /&gt;
        crossed_we++;&lt;br /&gt;
        if (ncrossing_we &amp;lt; CAPACITY &amp;amp;&amp;amp; nwaiting_we &amp;gt; 0 &amp;amp;&amp;amp; (nwaiting_ew == 0 || priority &amp;gt; 0)) {&lt;br /&gt;
            condition_signal(ok2goW);&lt;br /&gt;
        }else if (ncrossing_we == 0 &amp;amp;&amp;amp; nwaiting_ew &amp;gt; 0 ) {&lt;br /&gt;
            priority = BALANCE;&lt;br /&gt;
            condition_signal(ok2goE);&lt;br /&gt;
        }&lt;br /&gt;
    } else if (d == W){&lt;br /&gt;
        ncrossing_ew--;&lt;br /&gt;
        crossed_ew++;&lt;br /&gt;
        if (ncrossing_ew &amp;lt; CAPACITY &amp;amp;&amp;amp; nwaiting_ew &amp;gt; 0 &amp;amp;&amp;amp; (nwaiting_we == 0 || priority &amp;gt; 0)) {&lt;br /&gt;
            condition_signal(ok2goE);&lt;br /&gt;
        }else if (ncrossing_ew == 0 &amp;amp;&amp;amp; nwaiting_we &amp;gt; 0) {&lt;br /&gt;
            priority = BALANCE;&lt;br /&gt;
            condition_signal(ok2goW);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    monitor_exit(bridge);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void *crossEW(void* arg){&lt;br /&gt;
    while (1) {&lt;br /&gt;
        printf(&amp;quot;waitW: %d |-|%d|-&amp;gt;  &amp;lt;-|%d|-| waitE: %d  || crossed W-&amp;gt;E: %d crossed E-&amp;gt;W: %d||\n&amp;quot;, nwaiting_we, ncrossing_we, ncrossing_ew, nwaiting_ew, crossed_we, crossed_ew);&lt;br /&gt;
        usleep(random() % 200000);&lt;br /&gt;
        bridge_enter(E);&lt;br /&gt;
        usleep(random() % 20000);&lt;br /&gt;
        bridge_exit(W);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void *crossWE(void* arg){&lt;br /&gt;
    while (1) {&lt;br /&gt;
        printf(&amp;quot;waitW: %d |-|%d|-&amp;gt;  &amp;lt;-|%d|-| waitE: %d  || crossed W-&amp;gt;E: %d crossed E-&amp;gt;W: %d||\n&amp;quot;, nwaiting_we, ncrossing_we, ncrossing_ew, nwaiting_ew, crossed_we, crossed_ew);&lt;br /&gt;
        usleep(random() % 200000);&lt;br /&gt;
        bridge_enter(W);&lt;br /&gt;
        usleep(random() % 20000);&lt;br /&gt;
        bridge_exit(E);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main(int argc, const char * argv[]) {&lt;br /&gt;
    pthread_t e_w_t[NCAR];&lt;br /&gt;
    pthread_t w_e_t[NCAR];&lt;br /&gt;
    bridge_create();&lt;br /&gt;
&lt;br /&gt;
    srandom(time(NULL));&lt;br /&gt;
    for (int i = 0; i &amp;lt; NCAR; i++) {&lt;br /&gt;
        pthread_create(&amp;amp;e_w_t[i], NULL, crossEW, NULL);&lt;br /&gt;
        pthread_create(&amp;amp;w_e_t[i], NULL, crossWE, NULL);&lt;br /&gt;
&lt;br /&gt;
    }&lt;br /&gt;
    for (int i = 0; i &amp;lt; NCAR; i++) {&lt;br /&gt;
        pthread_join(w_e_t[i], NULL);&lt;br /&gt;
        pthread_join(e_w_t[i], NULL);&lt;br /&gt;
    }&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Dal testo dell'esercizio si evincono le seguenti condizioni basilari per poter attraversare il ponte:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
   (capacità&amp;gt;0 &amp;amp;&amp;amp; ncrossing_OppositeDirection == 0)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Per rendere la soluzione efficiente ho introdotto, così, la variabile priority settata al valore BALANCE ottenendo la seguente condizione:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
priority &amp;gt; 0 || nwaitingOppositeDirection == 0; &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
e.i. fin quando il mio senso (e.g. W-&amp;gt;E) ha ancora priorità di attraversare  O non ci sono macchine nella &lt;br /&gt;
direzione opposta che attendono, continuo a dare il via alle macchine che vanno nella mia stessa direzione.&lt;br /&gt;
Priority viene decrementata ad ogni macchina che attraversa il ponte.&lt;br /&gt;
&lt;br /&gt;
Non appena tale condizione viene interrotta, priority viene restaurata al valore BALANCE e la sua gestione viene ceduta al senso opposto.&lt;br /&gt;
Notare che anche questa soluzione non gestisce il caso in cui &amp;quot;il mio senso ha priorità ma non c'è nessuno che vuole attraversare&amp;quot;, &lt;br /&gt;
sarebbe inutile far attendere e maccchine della direzione opposta.&lt;br /&gt;
Allora il tutto viene gestito come segue:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
   bridge.enter()&lt;br /&gt;
    if (ncrossing_MyDirection &amp;lt;= CAPACITY &amp;amp;&amp;amp; ncrossing_OppositeDirection == 0 &amp;amp;&amp;amp; (mypriority &amp;gt; 0 || nwaitingOppositeDirection == 0)){&lt;br /&gt;
					 attraverso il ponte;&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
    bridge.exit()&lt;br /&gt;
	if (ncrossing_MyDirection &amp;lt; CAPACITY &amp;amp;&amp;amp; nwaiting_MyDirection &amp;gt; 0 &amp;amp;&amp;amp; (nwaiting_OppositeDirection == 0 || mypriority &amp;gt; 0)) {&lt;br /&gt;
            		do il via a chi attende di attraversare nella mia stessa direzione;&lt;br /&gt;
        }else if (ncrossing_MyDirection == 0 &amp;amp;&amp;amp; nwaiting_OppositeDirection &amp;gt; 0 ) {&lt;br /&gt;
            		restauro priority e lascio il comando alle macchine nella direzione opposta;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
L’ultima possibilità è che nessuno vuole attraversare il bridge, in questo caso nn faccio nulla. &lt;br /&gt;
Il comando resta alla direzione che per ultima ha attraversato il bridge&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;monitor.h&amp;gt;&lt;br /&gt;
#include &amp;lt;pthread.h&amp;gt;&lt;br /&gt;
#include &amp;lt;string.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
const int NCAR_E=8;&lt;br /&gt;
const int NCAR_W=8;&lt;br /&gt;
const int MAX_CAR = 7;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
enum dir{E,W,N};&lt;br /&gt;
int n_carcross = 0;&lt;br /&gt;
int waiting[2] = {0,0}; //[0] = [E] ; [1] = [W]&lt;br /&gt;
enum dir curr_dir = N; &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
monitor bridge;&lt;br /&gt;
condition ok2go[2];&lt;br /&gt;
&lt;br /&gt;
void bridge_create(){&lt;br /&gt;
	bridge = monitor_create();&lt;br /&gt;
	ok2go[0] = condition_create(bridge);&lt;br /&gt;
	ok2go[1] = condition_create(bridge);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void print_bridge(){&lt;br /&gt;
	if (curr_dir == E)&lt;br /&gt;
		printf(&amp;quot;%d W &amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;%d&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt; E %d\n&amp;quot;,waiting[1],n_carcross,waiting[0]);&lt;br /&gt;
	else&lt;br /&gt;
		printf(&amp;quot;%d W &amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;%d&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; E %d\n&amp;quot;,waiting[1],n_carcross,waiting[0]);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void bridge_enter(enum dir d){&lt;br /&gt;
	monitor_enter(bridge);&lt;br /&gt;
	int i = (int) d;&lt;br /&gt;
	if (curr_dir == N){&lt;br /&gt;
		curr_dir = d;&lt;br /&gt;
	}&lt;br /&gt;
	if ((curr_dir != d) || (n_carcross &amp;gt;= MAX_CAR) || (waiting[1-i]&amp;gt;0)){&lt;br /&gt;
			waiting[i]++;&lt;br /&gt;
			condition_wait(ok2go[i]);&lt;br /&gt;
			waiting[i]--;&lt;br /&gt;
	}&lt;br /&gt;
	n_carcross++;&lt;br /&gt;
	print_bridge();&lt;br /&gt;
	if (n_carcross &amp;lt; MAX_CAR){&lt;br /&gt;
		if (waiting[i]&amp;gt;0)&lt;br /&gt;
			condition_signal(ok2go[i]);&lt;br /&gt;
	}&lt;br /&gt;
	monitor_exit(bridge);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void bridge_exit(enum dir d){&lt;br /&gt;
 monitor_enter(bridge);&lt;br /&gt;
 int i = (int) d;&lt;br /&gt;
 n_carcross--;&lt;br /&gt;
 print_bridge();&lt;br /&gt;
 if (waiting[i]&amp;gt;0){&lt;br /&gt;
 	if (n_carcross == 0){&lt;br /&gt;
 		curr_dir = (enum dir) (1 - curr_dir);&lt;br /&gt;
 		condition_signal(ok2go[i]);&lt;br /&gt;
 	}&lt;br /&gt;
 }&lt;br /&gt;
 else&lt;br /&gt;
       If (waiting [1-i]&amp;gt;0)&lt;br /&gt;
 	   condition_signal(ok2go[1-i]);&lt;br /&gt;
       Else &lt;br /&gt;
           curr_dir = N; &lt;br /&gt;
 monitor_exit(bridge);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void *cross(void* arg){&lt;br /&gt;
	enum dir d = (enum dir) arg;&lt;br /&gt;
	while (1) {&lt;br /&gt;
	        usleep(random() % 2000000);&lt;br /&gt;
	        bridge_enter(d);&lt;br /&gt;
	        usleep(random() % 2000000);&lt;br /&gt;
	        bridge_exit((enum dir)(1-d));&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main(int argc, const char * argv[]) {&lt;br /&gt;
    pthread_t e_t[NCAR_E];&lt;br /&gt;
    pthread_t w_t[NCAR_W];&lt;br /&gt;
    &lt;br /&gt;
    bridge_create();&lt;br /&gt;
 &lt;br /&gt;
    srandom(time(NULL));&lt;br /&gt;
&lt;br /&gt;
    for (int i = 0; i &amp;lt; NCAR_E; i++) {&lt;br /&gt;
        pthread_create(&amp;amp;e_t[i], NULL, cross,(void*) E); &lt;br /&gt;
    }&lt;br /&gt;
    for (int i = 0; i &amp;lt; NCAR_W; i++) {&lt;br /&gt;
        pthread_create(&amp;amp;w_t[i], NULL, cross, (void*) W);&lt;br /&gt;
    }&lt;br /&gt;
    for (int i = 0; i &amp;lt; NCAR_E; i++) {&lt;br /&gt;
        pthread_join(e_t[i], NULL);&lt;br /&gt;
    }&lt;br /&gt;
    for (int i = 0; i &amp;lt; NCAR_W; i++) {&lt;br /&gt;
        pthread_join(w_t[i], NULL);&lt;br /&gt;
    }&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Questa è la prima soluzione che mi è venuta in mente cercando di rimanere sul più semplice possibile ... ho adottato alcuni accorgimenti per evitare di avere un programma lungo ma con &amp;quot;doppioni&amp;quot; --[[User:GabrieleCalarota|GabrieleCalarota]] ([[User talk:GabrieleCalarota|talk]]) 18:35, 14 December 2016 (CET)&lt;br /&gt;
&lt;br /&gt;
== Monitor: Cospirazione dei filosofi ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;monitor.h&amp;gt;&lt;br /&gt;
#include &amp;lt;pthread.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdint.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
monitor dp;&lt;br /&gt;
condition philo_wait[5]; /* status[np(i,1)] == 'T' &amp;amp;&amp;amp; status[np(i,-1)] == 'T' */&lt;br /&gt;
char status[] = &amp;quot;TTTTT&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
int np(int i, int off) {&lt;br /&gt;
        return (i+5+off) % 5;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void dp_create(void) {&lt;br /&gt;
        int i;&lt;br /&gt;
        dp = monitor_create();&lt;br /&gt;
        for (i=0; i&amp;lt;5; i++)&lt;br /&gt;
                philo_wait[i] = condition_create(dp);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void dp_starteat(int i) {&lt;br /&gt;
        monitor_enter(dp);&lt;br /&gt;
        if (status[np(i,1)] != 'T' || status[np(i,-1)] != 'T')&lt;br /&gt;
                condition_wait(philo_wait[i]);&lt;br /&gt;
        status[i] = 'E';&lt;br /&gt;
        printf(&amp;quot;%s\n&amp;quot;,status);&lt;br /&gt;
        monitor_exit(dp);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void dp_endeat(int i) {&lt;br /&gt;
        monitor_enter(dp);&lt;br /&gt;
        status[i] = 'T';&lt;br /&gt;
        printf(&amp;quot;%s\n&amp;quot;,status);&lt;br /&gt;
        if (status[np(i,2)] == 'T')&lt;br /&gt;
                condition_signal(philo_wait[np(i,1)]);&lt;br /&gt;
        if (status[np(i,-2)] == 'T')&lt;br /&gt;
                condition_signal(philo_wait[np(i,-1)]);&lt;br /&gt;
        monitor_exit(dp);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
monitor cospy;&lt;br /&gt;
condition wait2eat;&lt;br /&gt;
int cospy_count;&lt;br /&gt;
&lt;br /&gt;
void cospy_create(void) {&lt;br /&gt;
        cospy = monitor_create();&lt;br /&gt;
        wait2eat = condition_create(cospy);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void cospy_starteat(void) {&lt;br /&gt;
        monitor_enter(cospy);&lt;br /&gt;
        cospy_count++;&lt;br /&gt;
        condition_signal(wait2eat);&lt;br /&gt;
        monitor_exit(cospy);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void cospy_endeat(void) {&lt;br /&gt;
        monitor_enter(cospy);&lt;br /&gt;
        cospy_count--;&lt;br /&gt;
        if (cospy_count == 0)&lt;br /&gt;
                condition_wait(wait2eat);&lt;br /&gt;
        monitor_exit(cospy);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void *philo(void *arg) {&lt;br /&gt;
        int i = (uintptr_t) arg;&lt;br /&gt;
        while (1) {&lt;br /&gt;
                usleep(random() % 2000000);&lt;br /&gt;
                dp_starteat(i);&lt;br /&gt;
                if (i == 1 || i == 3)&lt;br /&gt;
                        cospy_starteat();&lt;br /&gt;
                usleep(random() % 2000000);&lt;br /&gt;
                if (i == 1 || i == 3)&lt;br /&gt;
                        cospy_endeat();&lt;br /&gt;
                dp_endeat(i);&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char *argv[]) {&lt;br /&gt;
        pthread_t philo_t[5];&lt;br /&gt;
        uintptr_t i;&lt;br /&gt;
        dp_create();&lt;br /&gt;
        cospy_create();&lt;br /&gt;
        srandom(time(NULL));&lt;br /&gt;
        for (i=0; i&amp;lt;5; i++)&lt;br /&gt;
                pthread_create(&amp;amp;philo_t[i], NULL, philo, (void *) i );&lt;br /&gt;
        while(1)&lt;br /&gt;
                pause();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
--[[User:FedericoB|FedericoB]] ([[User talk:FedericoB|talk]]) 11:27, 25 November 2016 (CET)Veniva creata la condizione di cospirazione collegata al monitor dp invece che cospy. Quindi con il signal il processo veniva messo nell'urgent stack sbagliato e chiamando monitor_exit su cospy non si risvegliava il processo nell' urgent stack di dp.&lt;br /&gt;
&lt;br /&gt;
== RW errato ==&lt;br /&gt;
Codice '''ERRATO''' dei lettori scrittori che dovrebbe non soffrire di problemi di starvation...&lt;br /&gt;
Esercizio: trovare gli errori.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
#include&amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include&amp;lt;stdint.h&amp;gt;&lt;br /&gt;
#include&amp;lt;pthread.h&amp;gt;&lt;br /&gt;
#include&amp;lt;semaphore.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define NREADER 3&lt;br /&gt;
#define NWRITER 3&lt;br /&gt;
semaphore mutex;&lt;br /&gt;
semaphore ok2read;&lt;br /&gt;
semaphore ok2write;&lt;br /&gt;
&lt;br /&gt;
int nr=0;&lt;br /&gt;
int nw=0;&lt;br /&gt;
int wr=0;&lt;br /&gt;
int ww=0;&lt;br /&gt;
int w_last;&lt;br /&gt;
&lt;br /&gt;
// (nw == 0 &amp;amp;&amp;amp; nr == 0) || (nr &amp;gt; 0 &amp;amp;&amp;amp; nw == 0) || nw == 1&lt;br /&gt;
// (nw == 0 &amp;amp;&amp;amp; nr &amp;gt;= 0) || nw == 1&lt;br /&gt;
&lt;br /&gt;
// this &amp;quot;baton&amp;quot; function has been left for reference only.&lt;br /&gt;
// code to implement &amp;quot;passing the baton&amp;quot; has been copied at the end of&lt;br /&gt;
// each ({start}|{end})({read}|{write}) function and reduced.&lt;br /&gt;
void baton(void) {&lt;br /&gt;
        if (nw == 0 &amp;amp;&amp;amp; nr == 0 &amp;amp;&amp;amp; ww &amp;gt; 0)&lt;br /&gt;
                semaphore_V(ok2write);&lt;br /&gt;
        else if (nw == 0 &amp;amp;&amp;amp; wr &amp;gt; 0 )&lt;br /&gt;
                semaphore_V(ok2read);&lt;br /&gt;
        else&lt;br /&gt;
                semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void startread(void) {&lt;br /&gt;
// &amp;lt;await nw == 0 -&amp;gt; nr++&amp;gt;&lt;br /&gt;
        semaphore_P(mutex);&lt;br /&gt;
        if (nw &amp;gt; 0 &amp;amp;&amp;amp; ww == 0) {&lt;br /&gt;
                wr++;&lt;br /&gt;
                semaphore_V(mutex);&lt;br /&gt;
                semaphore_P(ok2read);&lt;br /&gt;
                wr--;&lt;br /&gt;
        }&lt;br /&gt;
        nr++;&lt;br /&gt;
        w_last=0;&lt;br /&gt;
        printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, nr, nw, wr, ww);&lt;br /&gt;
        if (wr &amp;gt; 0 )&lt;br /&gt;
                semaphore_V(ok2read);&lt;br /&gt;
        else&lt;br /&gt;
                semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void endread(void) {&lt;br /&gt;
// &amp;lt;nr--&amp;gt;&lt;br /&gt;
        semaphore_P(mutex);&lt;br /&gt;
        nr--;&lt;br /&gt;
        printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, nr, nw, wr, ww);&lt;br /&gt;
        if (nr == 0 &amp;amp;&amp;amp; ww &amp;gt; 0)&lt;br /&gt;
                semaphore_V(ok2write);&lt;br /&gt;
        else&lt;br /&gt;
                semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void startwrite(void) {&lt;br /&gt;
// &amp;lt;await nw == 0 &amp;amp;&amp;amp; nr == 0 -&amp;gt; nw++&amp;gt;&lt;br /&gt;
        semaphore_P(mutex);&lt;br /&gt;
        if (nw &amp;gt; 0 || nr &amp;gt; 0) {&lt;br /&gt;
                ww++;&lt;br /&gt;
                semaphore_V(mutex);&lt;br /&gt;
                semaphore_P(ok2write);&lt;br /&gt;
                ww--;&lt;br /&gt;
        }&lt;br /&gt;
        nw++;&lt;br /&gt;
        w_last=1;&lt;br /&gt;
        printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, nr, nw, wr, ww);&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void endwrite(void) {&lt;br /&gt;
// &amp;lt;nw--&amp;gt;&lt;br /&gt;
        semaphore_P(mutex);&lt;br /&gt;
        nw--;&lt;br /&gt;
        printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, nr, nw, wr, ww);&lt;br /&gt;
        if (wr &amp;gt; 0 &amp;amp;&amp;amp; (ww == 0 || w_last))&lt;br /&gt;
                semaphore_V(ok2read);&lt;br /&gt;
        else if (ww &amp;gt; 0 &amp;amp;&amp;amp; (wr == 0 || !w_last))&lt;br /&gt;
                semaphore_V(ok2write);&lt;br /&gt;
        else&lt;br /&gt;
                semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void *reader(void *arg) {&lt;br /&gt;
        int i = (uintptr_t)arg;&lt;br /&gt;
        while (1) {&lt;br /&gt;
                //other code&lt;br /&gt;
                usleep(random() % 200000);&lt;br /&gt;
                startread();&lt;br /&gt;
                //read&lt;br /&gt;
                usleep(random() % 200000);&lt;br /&gt;
                endread();&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void *writer(void *arg) {&lt;br /&gt;
        int i = (uintptr_t)arg;&lt;br /&gt;
        while (1) {&lt;br /&gt;
                //other code&lt;br /&gt;
                usleep(random() % 200000);&lt;br /&gt;
                startwrite();&lt;br /&gt;
                //write&lt;br /&gt;
                usleep(random() % 200000);&lt;br /&gt;
                endwrite();&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//printf(&amp;quot;philo thinking: %d\n&amp;quot;,i);&lt;br /&gt;
/*while*/&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char *argv[]) {&lt;br /&gt;
        int i;&lt;br /&gt;
        pthread_t t;&lt;br /&gt;
        srandom(time(NULL));&lt;br /&gt;
        mutex=semaphore_create(1);&lt;br /&gt;
        ok2read=semaphore_create(0);&lt;br /&gt;
        ok2write=semaphore_create(0);&lt;br /&gt;
        for (i=0; i&amp;lt;NREADER; i++)&lt;br /&gt;
                pthread_create(&amp;amp;t, NULL, reader, (void *)(uintptr_t) i);&lt;br /&gt;
        for (i=0; i&amp;lt;NWRITER; i++)&lt;br /&gt;
                pthread_create(&amp;amp;t, NULL, writer, (void *)(uintptr_t) i);&lt;br /&gt;
        while(1)&lt;br /&gt;
                pause();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== RW di FedericoB ==&lt;br /&gt;
Propongo la seguente soluzione. Mi sembra che funzioni ma devo ancora capire perchè e documentarla bene. Ho provato prima a cercare il bug ma non ci sono riuscito. Ho quindi modificato il codice secondo ciò che mi sembrava sensato in base alle condizioni del problema. Ne possiamo parlare in aula oggi. --[[User:FedericoB|FedericoB]] ([[User talk:FedericoB|talk]]) 12:48, 11 November 2016 (CET)&lt;br /&gt;
Ho notato che l'errore non si manifesta più eliminando il controllo che ci siano scrittori in attesa quando un lettore vuole iniziare a scrivere. Non capisco come questo possa essere collegato al bug. --[[User:FedericoB|FedericoB]] ([[User talk:FedericoB|talk]]) 15:10, 11 November 2016 (CET)&lt;br /&gt;
&lt;br /&gt;
FedericoB, questa soluzione &amp;amp;egrave; quella con priorit&amp;amp;agrave; ai lettori, no? Se continuano ad arrivare lettori numberOfReaders non sar&amp;amp;agrave; mai zero e quindi gli scrittori non scriveranno mai. [[User:Renzo|Renzo]] ([[User talk:Renzo|talk]]) 10:34, 12 November 2016 (CET)&lt;br /&gt;
&lt;br /&gt;
SFIDA: ho trovato il modo di togliere la starvation aggiungendo 4 token (parole chiave, nomi di variabili, operatori, costanti) a questa soluzione di FedericoB. Chi trova la soluzione? [[User:Renzo|Renzo]] ([[User talk:Renzo|talk]]) 10:43, 12 November 2016 (CET) Ah! ho appena trovato una soluzione che prevede 2 soli token in pi&amp;amp;ugrave;! [[User:Renzo|Renzo]] ([[User talk:Renzo|talk]]) 10:47, 12 November 2016 (CET)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
#include&amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include&amp;lt;stdint.h&amp;gt;&lt;br /&gt;
#include&amp;lt;pthread.h&amp;gt;&lt;br /&gt;
#include&amp;lt;semaphore.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define NUMBER_OF_READERS 3&lt;br /&gt;
#define NUMBER_OF_WRITERS 3&lt;br /&gt;
semaphore mutex;&lt;br /&gt;
semaphore ok2read;&lt;br /&gt;
semaphore ok2write;&lt;br /&gt;
&lt;br /&gt;
int numberOfReaders=0;&lt;br /&gt;
int numberOfWriters=0;&lt;br /&gt;
int waitingReaders=0;&lt;br /&gt;
int waitingWriters=0;&lt;br /&gt;
&lt;br /&gt;
// (nw == 0 &amp;amp;&amp;amp; nr == 0) || (nr &amp;gt; 0 &amp;amp;&amp;amp; nw == 0) || nw == 1&lt;br /&gt;
// (nw == 0 &amp;amp;&amp;amp; nr &amp;gt;= 0) || nw == 1&lt;br /&gt;
&lt;br /&gt;
void startread(void) {&lt;br /&gt;
// &amp;lt;await nw == 0 -&amp;gt; nr++&amp;gt;&lt;br /&gt;
    semaphore_P(mutex);&lt;br /&gt;
    if (numberOfWriters &amp;gt; 0) {&lt;br /&gt;
        waitingReaders++;&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
        semaphore_P(ok2read);&lt;br /&gt;
        waitingReaders--;&lt;br /&gt;
    }&lt;br /&gt;
    numberOfReaders++;&lt;br /&gt;
    printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, numberOfReaders, numberOfWriters, waitingReaders, waitingWriters);&lt;br /&gt;
    if (waitingReaders &amp;gt; 0 )&lt;br /&gt;
        semaphore_V(ok2read);&lt;br /&gt;
    else&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void endread(void) {&lt;br /&gt;
// &amp;lt;nr--&amp;gt;&lt;br /&gt;
    semaphore_P(mutex);&lt;br /&gt;
    numberOfReaders--;&lt;br /&gt;
    printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, numberOfReaders, numberOfWriters, waitingReaders, waitingWriters);&lt;br /&gt;
    if (numberOfReaders == 0 &amp;amp;&amp;amp; waitingWriters &amp;gt; 0)&lt;br /&gt;
        semaphore_V(ok2write);&lt;br /&gt;
    else&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void startwrite(void) {&lt;br /&gt;
// &amp;lt;await nw == 0 &amp;amp;&amp;amp; nr == 0 -&amp;gt; nw++&amp;gt;&lt;br /&gt;
    semaphore_P(mutex);&lt;br /&gt;
    if (numberOfWriters &amp;gt; 0 || numberOfReaders &amp;gt; 0) {&lt;br /&gt;
        waitingWriters++;&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
        semaphore_P(ok2write);&lt;br /&gt;
        waitingWriters--;&lt;br /&gt;
    }&lt;br /&gt;
    numberOfWriters++;&lt;br /&gt;
    printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, numberOfReaders, numberOfWriters, waitingReaders, waitingWriters);&lt;br /&gt;
    semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void endwrite(void) {&lt;br /&gt;
// &amp;lt;nw--&amp;gt;&lt;br /&gt;
    semaphore_P(mutex);&lt;br /&gt;
    numberOfWriters--;&lt;br /&gt;
    printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, numberOfReaders, numberOfWriters, waitingReaders, waitingWriters);&lt;br /&gt;
    if (waitingReaders &amp;gt; 0)&lt;br /&gt;
        semaphore_V(ok2read);&lt;br /&gt;
    else if (waitingWriters &amp;gt; 0)&lt;br /&gt;
        semaphore_V(ok2write);&lt;br /&gt;
    else&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void *reader(void *arg) {&lt;br /&gt;
    int i = (uintptr_t)arg;&lt;br /&gt;
    while (1) {&lt;br /&gt;
        //other code&lt;br /&gt;
        usleep(random() % 200000);&lt;br /&gt;
        startread();&lt;br /&gt;
        //read&lt;br /&gt;
        usleep(random() % 200000);&lt;br /&gt;
        endread();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void *writer(void *arg) {&lt;br /&gt;
    int i = (uintptr_t)arg;&lt;br /&gt;
    while (1) {&lt;br /&gt;
        //other code&lt;br /&gt;
        usleep(random() % 200000);&lt;br /&gt;
        startwrite();&lt;br /&gt;
        //write&lt;br /&gt;
        usleep(random() % 200000);&lt;br /&gt;
        endwrite();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//printf(&amp;quot;philo thinking: %d\n&amp;quot;,i);&lt;br /&gt;
/*while*/&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char *argv[]) {&lt;br /&gt;
    int i;&lt;br /&gt;
    pthread_t t;&lt;br /&gt;
    srandom(time(NULL));&lt;br /&gt;
    mutex=semaphore_create(1);&lt;br /&gt;
    ok2read=semaphore_create(0);&lt;br /&gt;
    ok2write=semaphore_create(0);&lt;br /&gt;
    for (i=0; i&amp;lt;NUMBER_OF_READERS; i++)&lt;br /&gt;
        pthread_create(&amp;amp;t, NULL, reader, (void *)(uintptr_t) i);&lt;br /&gt;
    for (i=0; i&amp;lt;NUMBER_OF_WRITERS; i++)&lt;br /&gt;
        pthread_create(&amp;amp;t, NULL, writer, (void *)(uintptr_t) i);&lt;br /&gt;
    while(1)&lt;br /&gt;
        pause();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== RW2 ==&lt;br /&gt;
Buongiorno, guardando il codice visto a lezione mi sembra che cambiando la condizione del primo if nella startread() da &amp;quot;if (nw &amp;gt; 0 &amp;amp;&amp;amp; ww == 0)&amp;quot; a &amp;quot;if (nw &amp;gt; 0 || ww &amp;gt; 0)&amp;quot; la situazione migliori. In particolare con l'and tra quelle due condizioni si aveva che non veniva fatta la P sull'ok2read anche quando si aveva nw&amp;gt;0 (con ww!=0), cosa che invece dovrebbe fare. Lasciando il resto del codice uguale mi sembra che faccia quello che deve fare.. .&lt;br /&gt;
&lt;br /&gt;
Matteo.pincherle: Perch&amp;amp;eacute; non modifichi in programma di FedericoB, lo provi e pubblichi qui la patch? [[User:Renzo|Renzo]] ([[User talk:Renzo|talk]]) 10:42, 13 November 2016 (CET)&lt;br /&gt;
&lt;br /&gt;
'''Perchè quel AND permetteva di avere 2 scrittori?''' &amp;lt;br&amp;gt;&lt;br /&gt;
Permetteva in primis di avere dei lettori in contemporanea a uno scrittore. In quanto se succedeva che un lettore volesse entrare mentre non c'erano degli scrittori in attesa ma scrittori in scrittura, veniva saltato il blocco che mandava il lettore in attesa e risultava un lettore in contemporanea a uno scrittore. &amp;lt;br&amp;gt;&lt;br /&gt;
Questo lettore poi poteva finire di leggere prima che lo scrittore in contemporanea a lui finisse di scrivere. &amp;lt;br&amp;gt;&lt;br /&gt;
Il lettore in uscita se non c'erano altri lettori con lui e non c'erano scrittori in attesa dava il permesso per far accedere un altro scrittore. &amp;lt;br&amp;gt;&lt;br /&gt;
A questo punto un altro scrittore che avesse voluto entrare poteva entrare, con il risultato di avere 2 scrittori in contemporanea.&lt;br /&gt;
--[[User:FedericoB|FedericoB]] ([[User talk:FedericoB|talk]]) 19:25, 13 November 2016 (CET)&lt;br /&gt;
&lt;br /&gt;
== Patch ==&lt;br /&gt;
Così, se non sbaglio, quando c'è almeno uno scrittore in attesa non lascia entrare altri lettori. Fa esaurire la lettura dei presenti e poi lascia scrivere lo scrittore.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include&amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include&amp;lt;stdint.h&amp;gt;&lt;br /&gt;
#include&amp;lt;pthread.h&amp;gt;&lt;br /&gt;
#include&amp;lt;semaphore.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define NUMBER_OF_READERS 3&lt;br /&gt;
#define NUMBER_OF_WRITERS 3&lt;br /&gt;
semaphore mutex;&lt;br /&gt;
semaphore ok2read;&lt;br /&gt;
semaphore ok2write;&lt;br /&gt;
&lt;br /&gt;
int numberOfReaders=0;&lt;br /&gt;
int numberOfWriters=0;&lt;br /&gt;
int waitingReaders=0;&lt;br /&gt;
int waitingWriters=0;&lt;br /&gt;
int w_last;&lt;br /&gt;
&lt;br /&gt;
// (nw == 0 &amp;amp;&amp;amp; nr == 0) || (nr &amp;gt; 0 &amp;amp;&amp;amp; nw == 0) || nw == 1&lt;br /&gt;
// (nw == 0 &amp;amp;&amp;amp; nr &amp;gt;= 0) || nw == 1&lt;br /&gt;
&lt;br /&gt;
void startread(void) {&lt;br /&gt;
    // &amp;lt;await nw == 0 -&amp;gt; nr++&amp;gt;&lt;br /&gt;
    semaphore_P(mutex);&lt;br /&gt;
    if (numberOfWriters &amp;gt; 0 || waitingWriters&amp;gt;0) {&lt;br /&gt;
        waitingReaders++;&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
        semaphore_P(ok2read);&lt;br /&gt;
        waitingReaders--;&lt;br /&gt;
    }&lt;br /&gt;
    numberOfReaders++;&lt;br /&gt;
    w_last=0;&lt;br /&gt;
    printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, numberOfReaders, numberOfWriters, waitingReaders, waitingWriters);&lt;br /&gt;
    if (waitingReaders &amp;gt; 0 )&lt;br /&gt;
        semaphore_V(ok2read);&lt;br /&gt;
    else&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void endread(void) {&lt;br /&gt;
    // &amp;lt;nr--&amp;gt;&lt;br /&gt;
    semaphore_P(mutex);&lt;br /&gt;
    numberOfReaders--;&lt;br /&gt;
    printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, numberOfReaders, numberOfWriters, waitingReaders, waitingWriters);&lt;br /&gt;
    if (numberOfReaders == 0 &amp;amp;&amp;amp; waitingWriters &amp;gt; 0)&lt;br /&gt;
        semaphore_V(ok2write);&lt;br /&gt;
    else&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void startwrite(void) {&lt;br /&gt;
    // &amp;lt;await nw == 0 &amp;amp;&amp;amp; nr == 0 -&amp;gt; nw++&amp;gt;&lt;br /&gt;
    semaphore_P(mutex);&lt;br /&gt;
    if (numberOfWriters &amp;gt; 0 || numberOfReaders &amp;gt; 0) {&lt;br /&gt;
        waitingWriters++;&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
        semaphore_P(ok2write);&lt;br /&gt;
        waitingWriters--;&lt;br /&gt;
    }&lt;br /&gt;
    numberOfWriters++;&lt;br /&gt;
    w_last=1;&lt;br /&gt;
    printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, numberOfReaders, numberOfWriters, waitingReaders, waitingWriters);&lt;br /&gt;
    semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void endwrite(void) {&lt;br /&gt;
    // &amp;lt;nw--&amp;gt;&lt;br /&gt;
    semaphore_P(mutex);&lt;br /&gt;
    numberOfWriters--;&lt;br /&gt;
    printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, numberOfReaders, numberOfWriters, waitingReaders, waitingWriters);&lt;br /&gt;
    if (waitingReaders &amp;gt; 0 &amp;amp;&amp;amp; (waitingWriters==0 || w_last))&lt;br /&gt;
        semaphore_V(ok2read);&lt;br /&gt;
    else if (waitingWriters &amp;gt; 0 &amp;amp;&amp;amp; (waitingReaders==0 || !w_last))&lt;br /&gt;
        semaphore_V(ok2write);&lt;br /&gt;
    else&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void *reader(void *arg) {&lt;br /&gt;
    int i = (uintptr_t)arg;&lt;br /&gt;
    while (1) {&lt;br /&gt;
        //other code&lt;br /&gt;
        usleep(random() % 200000);&lt;br /&gt;
        startread();&lt;br /&gt;
        //read&lt;br /&gt;
        usleep(random() % 200000);&lt;br /&gt;
        endread();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void *writer(void *arg) {&lt;br /&gt;
    int i = (uintptr_t)arg;&lt;br /&gt;
    while (1) {&lt;br /&gt;
        //other code&lt;br /&gt;
        usleep(random() % 200000);&lt;br /&gt;
        startwrite();&lt;br /&gt;
        //write&lt;br /&gt;
        usleep(random() % 200000);&lt;br /&gt;
        endwrite();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char *argv[]) {&lt;br /&gt;
    int i;&lt;br /&gt;
    pthread_t t;&lt;br /&gt;
    srandom(time(NULL));&lt;br /&gt;
    mutex=semaphore_create(1);&lt;br /&gt;
    ok2read=semaphore_create(0);&lt;br /&gt;
    ok2write=semaphore_create(0);&lt;br /&gt;
    for (i=0; i&amp;lt;NUMBER_OF_READERS; i++)&lt;br /&gt;
        pthread_create(&amp;amp;t, NULL, reader, (void *)(uintptr_t) i);&lt;br /&gt;
    for (i=0; i&amp;lt;NUMBER_OF_WRITERS; i++)&lt;br /&gt;
        pthread_create(&amp;amp;t, NULL, writer, (void *)(uintptr_t) i);&lt;br /&gt;
    while(1)&lt;br /&gt;
        pause();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
wlast non serve pi&amp;amp;ugrave;... [[User:Renzo|Renzo]] ([[User talk:Renzo|talk]]) 17:52, 13 November 2016 (CET)&lt;br /&gt;
&lt;br /&gt;
== RW2bis ==&lt;br /&gt;
Nella tua soluzione se i lettori sono &amp;quot;molto veloci&amp;quot; e non vanno mai a 0, lo scrittore non inizierà mai a scrivere.&lt;br /&gt;
&lt;br /&gt;
Cioè: Uno scrittore viene svegliato da ok2write solo se passa la condizione &lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
[..] &lt;br /&gt;
if (numberofReaders == 0 &amp;amp;&amp;amp; waitingWriters &amp;gt;0) &lt;br /&gt;
     semaphore_V(ok2write);&lt;br /&gt;
[..]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; --[[User:GabrieleCalarota|GabrieleCalarota]] ([[User talk:GabrieleCalarota|talk]]) 17:46, 13 November 2016 (CET)&lt;br /&gt;
&lt;br /&gt;
Non direi perche' nella startread se:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
    if (numberOfWriters &amp;gt; 0 || waitingWriters&amp;gt;0) &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
i lettori si bloccano. Quindi se c'e' almeno uno scrittore in attesa i lettori non entrano (e quindi prima o poi terminano e lasciano il posto ad uno scrittore).&lt;br /&gt;
[[User:Renzo|Renzo]] ([[User talk:Renzo|talk]]) 17:57, 13 November 2016 (CET)&lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
Ho pensato al caso limite seguente:&lt;br /&gt;
Supponiamo che ci siano dei lettori che stanno leggendo e ad un certo punto uno scrittore chiede di scrivere.&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;syntaxhighlight lang=C&amp;gt;         &lt;br /&gt;
       void startread(void) {&lt;br /&gt;
    // &amp;lt;await nw == 0 -&amp;gt; nr++&amp;gt;&lt;br /&gt;
    semaphore_P(mutex);&lt;br /&gt;
    if (numberOfWriters &amp;gt; 0 || waitingWriters&amp;gt;0) {&lt;br /&gt;
        waitingReaders++;   //Nuovo scrittore (t1)&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
        semaphore_P(ok2read);&lt;br /&gt;
        waitingReaders--;&lt;br /&gt;
    }&lt;br /&gt;
    numberOfReaders++;&lt;br /&gt;
    w_last=0;&lt;br /&gt;
    printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, numberOfReaders, numberOfWriters, waitingReaders, waitingWriters);&lt;br /&gt;
   if (waitingReaders &amp;gt; 0 )   //Vecchio scrittore(t1)&lt;br /&gt;
        semaphore_V(ok2read);&lt;br /&gt;
    else&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Non appena lo scrittore rilascia il mutex, un nuovo lettore chiede di leggere (e si addormenterà). Un lettore (lento) che era riuscito a entrare nel segmento startofread prima che lo scrittore entrasse in startofwrite, continua a leggere e risveglia uno dei nuovi lettori. Se i lettori continuano a richiedere di leggere continuamente, verranno addormentati e subito risvegliati. &lt;br /&gt;
&lt;br /&gt;
E' da considerarsi possibile? --[[User:GabrieleCalarota|GabrieleCalarota]] ([[User talk:GabrieleCalarota|talk]]) 19:11, 13 November 2016 (CET)&lt;br /&gt;
&lt;br /&gt;
Suppongo che &amp;quot;un nuovo scrittore chiede di leggere&amp;quot; si aun refuso e sia da intendere &amp;quot;un nuovo lettore chiede di leggere&amp;quot; (altrimenti ci sono crisi di identit&amp;amp;agrave;) e che &amp;quot;startofread&amp;quot; significhi &amp;quot;startread&amp;quot; e &amp;quot;startofwrite&amp;quot;  sia &amp;quot;startwrite&amp;quot;.&lt;br /&gt;
La &amp;quot;startread&amp;quot; viene eseguita in mutua esclusione, quindi non ci puo' essere &amp;quot;un lettore lento che sia riuscito ad entrare&amp;quot; nella funione startread. Se ha superato la P(mutex) iniziale o e' bloccato sulla ok2read o e' entrato. [[User:Renzo|Renzo]] ([[User talk:Renzo|talk]]) 19:37, 13 November 2016 (CET)&lt;/div&gt;</summary>
		<author><name>GabrieleCalarota</name></author>
	</entry>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=Zibaldone&amp;diff=1712</id>
		<title>Zibaldone</title>
		<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php?title=Zibaldone&amp;diff=1712"/>
		<updated>2016-12-15T15:27:17Z</updated>

		<summary type="html">&lt;p&gt;GabrieleCalarota: /* Monitor: Ponte a senso Unico */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Monitor: Ponte a senso Unico ==&lt;br /&gt;
Proposta di soluzione: esercizio 1 esame 22/01/2014&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
//&lt;br /&gt;
//  20140122_bridge&lt;br /&gt;
//&lt;br /&gt;
/*   Esercizio c.1:&lt;br /&gt;
 *&lt;br /&gt;
 *   Per colpa delle frane un ponte veicolare e' rimasto danneggiato.&lt;br /&gt;
 *   I veicoli possono ora percorrerlo solo in senso unico alternato e, per non eccedere la portata,&lt;br /&gt;
 *   al piu' ci possono essere sul ponte N veicoli contemporaneamente.&lt;br /&gt;
 *   Scrivere il monitor bridge sapendo che i veicoli chiameranno il monitor prima di entrare nel&lt;br /&gt;
 *   ponte e dopo averlo attraversato.&lt;br /&gt;
 *   I veicoli che entrano dal lato est escono dal lato ovest e viceversa.&lt;br /&gt;
 *   Quindi i (numerosi) veicoli eseguiranno uno dei due frammenti di codice seguenti:&lt;br /&gt;
 *&lt;br /&gt;
 *&lt;br /&gt;
 *   bridge.enter(E)                      bridge.enter(W)&lt;br /&gt;
 *   //cross the bridge                   //cross the bridge&lt;br /&gt;
 *   bridge.exit(W)                       bridge.exit(E)&lt;br /&gt;
 *&lt;br /&gt;
 *&lt;br /&gt;
 *   La soluzione proposta deve evitare deadlock e deve essere efficiente.&lt;br /&gt;
 *   (controesempio: una soluzione che prevedesse l'attraversamento del ponte da parte di un solo veicolo alla volta&lt;br /&gt;
 *   sebbene rispetti tutti i vincoli sarebbe considerata errata poiche' inefficiente).&lt;br /&gt;
 *   Oltre al codice si richiede una descrizione degli accorgimenti adottati per rendere la soluzione efficiente.&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;quot;monitor.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
#define CAPACITY 7 //capacità del bridge&lt;br /&gt;
#define BALANCE 9  &lt;br /&gt;
#define NCAR 15&lt;br /&gt;
&lt;br /&gt;
enum dest{&lt;br /&gt;
    E = 0,&lt;br /&gt;
    W = 1&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
int ncrossing_we = 0; //n car che stanno attraversando il bridge da W-&amp;gt;E&lt;br /&gt;
int ncrossing_ew = 0; //n car che stanno attraversando il bridge da E-&amp;gt;W&lt;br /&gt;
&lt;br /&gt;
int nwaiting_we = 0; //n car che aspettano di attraversare da W-&amp;gt;E&lt;br /&gt;
int nwaiting_ew = 0;  //n car che aspettano di attraversare da E-&amp;gt;W&lt;br /&gt;
&lt;br /&gt;
int priority = BALANCE;&lt;br /&gt;
&lt;br /&gt;
int crossed_we = 0; //n volte che il ponte è stato attraversato da W-&amp;gt;E&lt;br /&gt;
int crossed_ew = 0; //n volte che il ponte è stato attraversato da E-&amp;gt;W&lt;br /&gt;
&lt;br /&gt;
condition ok2goW; // capacity &amp;gt; 0 &amp;amp;&amp;amp; (ncrossing_ew == 0 || priority &amp;gt; 0)&lt;br /&gt;
condition ok2goE; // capacity &amp;gt; 0 &amp;amp;&amp;amp; (ncrossing_we == 0 || prioriti &amp;gt; 0 )&lt;br /&gt;
monitor bridge;&lt;br /&gt;
&lt;br /&gt;
void bridge_create(void){&lt;br /&gt;
    bridge = monitor_create();&lt;br /&gt;
    ok2goW = condition_create(bridge);&lt;br /&gt;
    ok2goE = condition_create(bridge);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void bridge_enter(enum dest d){&lt;br /&gt;
    monitor_enter(bridge);&lt;br /&gt;
    if (d == W) {&lt;br /&gt;
        nwaiting_we++;&lt;br /&gt;
        if (ncrossing_we &amp;gt;= CAPACITY || ncrossing_ew &amp;gt; 0 || (nwaiting_ew &amp;gt; 0 &amp;amp;&amp;amp; priority &amp;lt;= 0)) {&lt;br /&gt;
            condition_wait(ok2goW);&lt;br /&gt;
        }&lt;br /&gt;
        priority--;&lt;br /&gt;
        nwaiting_we--;&lt;br /&gt;
        ncrossing_we++;&lt;br /&gt;
        if (ncrossing_we &amp;lt; CAPACITY &amp;amp;&amp;amp; priority &amp;gt; 0) {&lt;br /&gt;
            condition_signal(ok2goW);&lt;br /&gt;
        }&lt;br /&gt;
    }else if(d == E){&lt;br /&gt;
        nwaiting_ew++;&lt;br /&gt;
        if (ncrossing_ew &amp;gt;= CAPACITY || ncrossing_we &amp;gt; 0 || (nwaiting_we &amp;gt; 0 &amp;amp;&amp;amp; priority &amp;lt;= 0)){&lt;br /&gt;
            condition_wait(ok2goE);&lt;br /&gt;
        }&lt;br /&gt;
        priority--;&lt;br /&gt;
        nwaiting_ew--;&lt;br /&gt;
        ncrossing_ew++;&lt;br /&gt;
        if (ncrossing_ew &amp;lt; CAPACITY &amp;amp;&amp;amp; priority &amp;gt; 0) {&lt;br /&gt;
            condition_signal(ok2goE);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    monitor_exit(bridge);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void bridge_exit(enum dest d){&lt;br /&gt;
    monitor_enter(bridge);&lt;br /&gt;
    if (d == E) {&lt;br /&gt;
        ncrossing_we--;&lt;br /&gt;
        crossed_we++;&lt;br /&gt;
        if (ncrossing_we &amp;lt; CAPACITY &amp;amp;&amp;amp; nwaiting_we &amp;gt; 0 &amp;amp;&amp;amp; (nwaiting_ew == 0 || priority &amp;gt; 0)) {&lt;br /&gt;
            condition_signal(ok2goW);&lt;br /&gt;
        }else if (ncrossing_we == 0 &amp;amp;&amp;amp; nwaiting_ew &amp;gt; 0 ) {&lt;br /&gt;
            priority = BALANCE;&lt;br /&gt;
            condition_signal(ok2goE);&lt;br /&gt;
        }&lt;br /&gt;
    } else if (d == W){&lt;br /&gt;
        ncrossing_ew--;&lt;br /&gt;
        crossed_ew++;&lt;br /&gt;
        if (ncrossing_ew &amp;lt; CAPACITY &amp;amp;&amp;amp; nwaiting_ew &amp;gt; 0 &amp;amp;&amp;amp; (nwaiting_we == 0 || priority &amp;gt; 0)) {&lt;br /&gt;
            condition_signal(ok2goE);&lt;br /&gt;
        }else if (ncrossing_ew == 0 &amp;amp;&amp;amp; nwaiting_we &amp;gt; 0) {&lt;br /&gt;
            priority = BALANCE;&lt;br /&gt;
            condition_signal(ok2goW);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    monitor_exit(bridge);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void *crossEW(void* arg){&lt;br /&gt;
    while (1) {&lt;br /&gt;
        printf(&amp;quot;waitW: %d |-|%d|-&amp;gt;  &amp;lt;-|%d|-| waitE: %d  || crossed W-&amp;gt;E: %d crossed E-&amp;gt;W: %d||\n&amp;quot;, nwaiting_we, ncrossing_we, ncrossing_ew, nwaiting_ew, crossed_we, crossed_ew);&lt;br /&gt;
        usleep(random() % 200000);&lt;br /&gt;
        bridge_enter(E);&lt;br /&gt;
        usleep(random() % 20000);&lt;br /&gt;
        bridge_exit(W);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void *crossWE(void* arg){&lt;br /&gt;
    while (1) {&lt;br /&gt;
        printf(&amp;quot;waitW: %d |-|%d|-&amp;gt;  &amp;lt;-|%d|-| waitE: %d  || crossed W-&amp;gt;E: %d crossed E-&amp;gt;W: %d||\n&amp;quot;, nwaiting_we, ncrossing_we, ncrossing_ew, nwaiting_ew, crossed_we, crossed_ew);&lt;br /&gt;
        usleep(random() % 200000);&lt;br /&gt;
        bridge_enter(W);&lt;br /&gt;
        usleep(random() % 20000);&lt;br /&gt;
        bridge_exit(E);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main(int argc, const char * argv[]) {&lt;br /&gt;
    pthread_t e_w_t[NCAR];&lt;br /&gt;
    pthread_t w_e_t[NCAR];&lt;br /&gt;
    bridge_create();&lt;br /&gt;
&lt;br /&gt;
    srandom(time(NULL));&lt;br /&gt;
    for (int i = 0; i &amp;lt; NCAR; i++) {&lt;br /&gt;
        pthread_create(&amp;amp;e_w_t[i], NULL, crossEW, NULL);&lt;br /&gt;
        pthread_create(&amp;amp;w_e_t[i], NULL, crossWE, NULL);&lt;br /&gt;
&lt;br /&gt;
    }&lt;br /&gt;
    for (int i = 0; i &amp;lt; NCAR; i++) {&lt;br /&gt;
        pthread_join(w_e_t[i], NULL);&lt;br /&gt;
        pthread_join(e_w_t[i], NULL);&lt;br /&gt;
    }&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Dal testo dell'esercizio si evincono le seguenti condizioni basilari per poter attraversare il ponte:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
   (capacità&amp;gt;0 &amp;amp;&amp;amp; ncrossing_OppositeDirection == 0)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Per rendere la soluzione efficiente ho introdotto, così, la variabile priority settata al valore BALANCE ottenendo la seguente condizione:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
priority &amp;gt; 0 || nwaitingOppositeDirection == 0; &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
e.i. fin quando il mio senso (e.g. W-&amp;gt;E) ha ancora priorità di attraversare  O non ci sono macchine nella &lt;br /&gt;
direzione opposta che attendono, continuo a dare il via alle macchine che vanno nella mia stessa direzione.&lt;br /&gt;
Priority viene decrementata ad ogni macchina che attraversa il ponte.&lt;br /&gt;
&lt;br /&gt;
Non appena tale condizione viene interrotta, priority viene restaurata al valore BALANCE e la sua gestione viene ceduta al senso opposto.&lt;br /&gt;
Notare che anche questa soluzione non gestisce il caso in cui &amp;quot;il mio senso ha priorità ma non c'è nessuno che vuole attraversare&amp;quot;, &lt;br /&gt;
sarebbe inutile far attendere e maccchine della direzione opposta.&lt;br /&gt;
Allora il tutto viene gestito come segue:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
   bridge.enter()&lt;br /&gt;
    if (ncrossing_MyDirection &amp;lt;= CAPACITY &amp;amp;&amp;amp; ncrossing_OppositeDirection == 0 &amp;amp;&amp;amp; (mypriority &amp;gt; 0 || nwaitingOppositeDirection == 0)){&lt;br /&gt;
					 attraverso il ponte;&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
    bridge.exit()&lt;br /&gt;
	if (ncrossing_MyDirection &amp;lt; CAPACITY &amp;amp;&amp;amp; nwaiting_MyDirection &amp;gt; 0 &amp;amp;&amp;amp; (nwaiting_OppositeDirection == 0 || mypriority &amp;gt; 0)) {&lt;br /&gt;
            		do il via a chi attende di attraversare nella mia stessa direzione;&lt;br /&gt;
        }else if (ncrossing_MyDirection == 0 &amp;amp;&amp;amp; nwaiting_OppositeDirection &amp;gt; 0 ) {&lt;br /&gt;
            		restauro priority e lascio il comando alle macchine nella direzione opposta;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
L’ultima possibilità è che nessuno vuole attraversare il bridge, in questo caso nn faccio nulla. &lt;br /&gt;
Il comando resta alla direzione che per ultima ha attraversato il bridge&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;monitor.h&amp;gt;&lt;br /&gt;
#include &amp;lt;pthread.h&amp;gt;&lt;br /&gt;
#include &amp;lt;string.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
const int NCAR_E=8;&lt;br /&gt;
const int NCAR_W=8;&lt;br /&gt;
const int MAX_CAR = 7;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
enum dir{E,W,N};&lt;br /&gt;
int n_carcross = 0;&lt;br /&gt;
int waiting[2] = {0,0}; //[0] = [E] ; [1] = [W]&lt;br /&gt;
enum dir curr_dir = N; &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
monitor bridge;&lt;br /&gt;
condition ok2go[2];&lt;br /&gt;
&lt;br /&gt;
void bridge_create(){&lt;br /&gt;
	bridge = monitor_create();&lt;br /&gt;
	ok2go[0] = condition_create(bridge);&lt;br /&gt;
	ok2go[1] = condition_create(bridge);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void print_bridge(){&lt;br /&gt;
	if (curr_dir == E)&lt;br /&gt;
		printf(&amp;quot;%d W &amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;%d&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt; E %d\n&amp;quot;,waiting[1],n_carcross,waiting[0]);&lt;br /&gt;
	else&lt;br /&gt;
		printf(&amp;quot;%d W &amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;%d&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; E %d\n&amp;quot;,waiting[1],n_carcross,waiting[0]);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void bridge_enter(enum dir d){&lt;br /&gt;
	monitor_enter(bridge);&lt;br /&gt;
	int i = (int) d;&lt;br /&gt;
	if (curr_dir == N){&lt;br /&gt;
		curr_dir = d;&lt;br /&gt;
		change_dir(d);&lt;br /&gt;
	}&lt;br /&gt;
	if ((curr_dir != d) || (n_carcross &amp;gt;= MAX_CAR) || (waiting[1-i]&amp;gt;0)){&lt;br /&gt;
			waiting[i]++;&lt;br /&gt;
			condition_wait(ok2go[i]);&lt;br /&gt;
			waiting[i]--;&lt;br /&gt;
	}&lt;br /&gt;
	n_carcross++;&lt;br /&gt;
	print_bridge();&lt;br /&gt;
	if (n_carcross &amp;lt; MAX_CAR){&lt;br /&gt;
		if (waiting[i]&amp;gt;0)&lt;br /&gt;
			condition_signal(ok2go[i]);&lt;br /&gt;
	}&lt;br /&gt;
	monitor_exit(bridge);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void bridge_exit(enum dir d){&lt;br /&gt;
 monitor_enter(bridge);&lt;br /&gt;
 int i = (int) d;&lt;br /&gt;
 n_carcross--;&lt;br /&gt;
 print_bridge();&lt;br /&gt;
 if (waiting[i]&amp;gt;0){&lt;br /&gt;
 	if (n_carcross == 0){&lt;br /&gt;
 		change_dir(d);&lt;br /&gt;
 		curr_dir = (enum dir) (1 - curr_dir);&lt;br /&gt;
 		condition_signal(ok2go[i]);&lt;br /&gt;
 	}&lt;br /&gt;
 }&lt;br /&gt;
 else&lt;br /&gt;
       If (waiting [1-i]&amp;gt;0)&lt;br /&gt;
 	   condition_signal(ok2go[1-i]);&lt;br /&gt;
       Else &lt;br /&gt;
           curr_dir = N; &lt;br /&gt;
 monitor_exit(bridge);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void *cross(void* arg){&lt;br /&gt;
	enum dir d = (enum dir) arg;&lt;br /&gt;
	while (1) {&lt;br /&gt;
	        usleep(random() % 2000000);&lt;br /&gt;
	        bridge_enter(d);&lt;br /&gt;
	        usleep(random() % 2000000);&lt;br /&gt;
	        bridge_exit((enum dir)(1-d));&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main(int argc, const char * argv[]) {&lt;br /&gt;
    pthread_t e_t[NCAR_E];&lt;br /&gt;
    pthread_t w_t[NCAR_W];&lt;br /&gt;
    &lt;br /&gt;
    bridge_create();&lt;br /&gt;
 &lt;br /&gt;
    srandom(time(NULL));&lt;br /&gt;
&lt;br /&gt;
    for (int i = 0; i &amp;lt; NCAR_E; i++) {&lt;br /&gt;
        pthread_create(&amp;amp;e_t[i], NULL, cross,(void*) E); &lt;br /&gt;
    }&lt;br /&gt;
    for (int i = 0; i &amp;lt; NCAR_W; i++) {&lt;br /&gt;
        pthread_create(&amp;amp;w_t[i], NULL, cross, (void*) W);&lt;br /&gt;
    }&lt;br /&gt;
    for (int i = 0; i &amp;lt; NCAR_E; i++) {&lt;br /&gt;
        pthread_join(e_t[i], NULL);&lt;br /&gt;
    }&lt;br /&gt;
    for (int i = 0; i &amp;lt; NCAR_W; i++) {&lt;br /&gt;
        pthread_join(w_t[i], NULL);&lt;br /&gt;
    }&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Questa è la prima soluzione che mi è venuta in mente cercando di rimanere sul più semplice possibile ... ho adottato alcuni accorgimenti per evitare di avere un programma lungo ma con &amp;quot;doppioni&amp;quot; --[[User:GabrieleCalarota|GabrieleCalarota]] ([[User talk:GabrieleCalarota|talk]]) 18:35, 14 December 2016 (CET)&lt;br /&gt;
&lt;br /&gt;
== Monitor: Cospirazione dei filosofi ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;monitor.h&amp;gt;&lt;br /&gt;
#include &amp;lt;pthread.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdint.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
monitor dp;&lt;br /&gt;
condition philo_wait[5]; /* status[np(i,1)] == 'T' &amp;amp;&amp;amp; status[np(i,-1)] == 'T' */&lt;br /&gt;
char status[] = &amp;quot;TTTTT&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
int np(int i, int off) {&lt;br /&gt;
        return (i+5+off) % 5;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void dp_create(void) {&lt;br /&gt;
        int i;&lt;br /&gt;
        dp = monitor_create();&lt;br /&gt;
        for (i=0; i&amp;lt;5; i++)&lt;br /&gt;
                philo_wait[i] = condition_create(dp);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void dp_starteat(int i) {&lt;br /&gt;
        monitor_enter(dp);&lt;br /&gt;
        if (status[np(i,1)] != 'T' || status[np(i,-1)] != 'T')&lt;br /&gt;
                condition_wait(philo_wait[i]);&lt;br /&gt;
        status[i] = 'E';&lt;br /&gt;
        printf(&amp;quot;%s\n&amp;quot;,status);&lt;br /&gt;
        monitor_exit(dp);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void dp_endeat(int i) {&lt;br /&gt;
        monitor_enter(dp);&lt;br /&gt;
        status[i] = 'T';&lt;br /&gt;
        printf(&amp;quot;%s\n&amp;quot;,status);&lt;br /&gt;
        if (status[np(i,2)] == 'T')&lt;br /&gt;
                condition_signal(philo_wait[np(i,1)]);&lt;br /&gt;
        if (status[np(i,-2)] == 'T')&lt;br /&gt;
                condition_signal(philo_wait[np(i,-1)]);&lt;br /&gt;
        monitor_exit(dp);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
monitor cospy;&lt;br /&gt;
condition wait2eat;&lt;br /&gt;
int cospy_count;&lt;br /&gt;
&lt;br /&gt;
void cospy_create(void) {&lt;br /&gt;
        cospy = monitor_create();&lt;br /&gt;
        wait2eat = condition_create(cospy);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void cospy_starteat(void) {&lt;br /&gt;
        monitor_enter(cospy);&lt;br /&gt;
        cospy_count++;&lt;br /&gt;
        condition_signal(wait2eat);&lt;br /&gt;
        monitor_exit(cospy);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void cospy_endeat(void) {&lt;br /&gt;
        monitor_enter(cospy);&lt;br /&gt;
        cospy_count--;&lt;br /&gt;
        if (cospy_count == 0)&lt;br /&gt;
                condition_wait(wait2eat);&lt;br /&gt;
        monitor_exit(cospy);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void *philo(void *arg) {&lt;br /&gt;
        int i = (uintptr_t) arg;&lt;br /&gt;
        while (1) {&lt;br /&gt;
                usleep(random() % 2000000);&lt;br /&gt;
                dp_starteat(i);&lt;br /&gt;
                if (i == 1 || i == 3)&lt;br /&gt;
                        cospy_starteat();&lt;br /&gt;
                usleep(random() % 2000000);&lt;br /&gt;
                if (i == 1 || i == 3)&lt;br /&gt;
                        cospy_endeat();&lt;br /&gt;
                dp_endeat(i);&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char *argv[]) {&lt;br /&gt;
        pthread_t philo_t[5];&lt;br /&gt;
        uintptr_t i;&lt;br /&gt;
        dp_create();&lt;br /&gt;
        cospy_create();&lt;br /&gt;
        srandom(time(NULL));&lt;br /&gt;
        for (i=0; i&amp;lt;5; i++)&lt;br /&gt;
                pthread_create(&amp;amp;philo_t[i], NULL, philo, (void *) i );&lt;br /&gt;
        while(1)&lt;br /&gt;
                pause();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
--[[User:FedericoB|FedericoB]] ([[User talk:FedericoB|talk]]) 11:27, 25 November 2016 (CET)Veniva creata la condizione di cospirazione collegata al monitor dp invece che cospy. Quindi con il signal il processo veniva messo nell'urgent stack sbagliato e chiamando monitor_exit su cospy non si risvegliava il processo nell' urgent stack di dp.&lt;br /&gt;
&lt;br /&gt;
== RW errato ==&lt;br /&gt;
Codice '''ERRATO''' dei lettori scrittori che dovrebbe non soffrire di problemi di starvation...&lt;br /&gt;
Esercizio: trovare gli errori.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
#include&amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include&amp;lt;stdint.h&amp;gt;&lt;br /&gt;
#include&amp;lt;pthread.h&amp;gt;&lt;br /&gt;
#include&amp;lt;semaphore.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define NREADER 3&lt;br /&gt;
#define NWRITER 3&lt;br /&gt;
semaphore mutex;&lt;br /&gt;
semaphore ok2read;&lt;br /&gt;
semaphore ok2write;&lt;br /&gt;
&lt;br /&gt;
int nr=0;&lt;br /&gt;
int nw=0;&lt;br /&gt;
int wr=0;&lt;br /&gt;
int ww=0;&lt;br /&gt;
int w_last;&lt;br /&gt;
&lt;br /&gt;
// (nw == 0 &amp;amp;&amp;amp; nr == 0) || (nr &amp;gt; 0 &amp;amp;&amp;amp; nw == 0) || nw == 1&lt;br /&gt;
// (nw == 0 &amp;amp;&amp;amp; nr &amp;gt;= 0) || nw == 1&lt;br /&gt;
&lt;br /&gt;
// this &amp;quot;baton&amp;quot; function has been left for reference only.&lt;br /&gt;
// code to implement &amp;quot;passing the baton&amp;quot; has been copied at the end of&lt;br /&gt;
// each ({start}|{end})({read}|{write}) function and reduced.&lt;br /&gt;
void baton(void) {&lt;br /&gt;
        if (nw == 0 &amp;amp;&amp;amp; nr == 0 &amp;amp;&amp;amp; ww &amp;gt; 0)&lt;br /&gt;
                semaphore_V(ok2write);&lt;br /&gt;
        else if (nw == 0 &amp;amp;&amp;amp; wr &amp;gt; 0 )&lt;br /&gt;
                semaphore_V(ok2read);&lt;br /&gt;
        else&lt;br /&gt;
                semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void startread(void) {&lt;br /&gt;
// &amp;lt;await nw == 0 -&amp;gt; nr++&amp;gt;&lt;br /&gt;
        semaphore_P(mutex);&lt;br /&gt;
        if (nw &amp;gt; 0 &amp;amp;&amp;amp; ww == 0) {&lt;br /&gt;
                wr++;&lt;br /&gt;
                semaphore_V(mutex);&lt;br /&gt;
                semaphore_P(ok2read);&lt;br /&gt;
                wr--;&lt;br /&gt;
        }&lt;br /&gt;
        nr++;&lt;br /&gt;
        w_last=0;&lt;br /&gt;
        printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, nr, nw, wr, ww);&lt;br /&gt;
        if (wr &amp;gt; 0 )&lt;br /&gt;
                semaphore_V(ok2read);&lt;br /&gt;
        else&lt;br /&gt;
                semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void endread(void) {&lt;br /&gt;
// &amp;lt;nr--&amp;gt;&lt;br /&gt;
        semaphore_P(mutex);&lt;br /&gt;
        nr--;&lt;br /&gt;
        printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, nr, nw, wr, ww);&lt;br /&gt;
        if (nr == 0 &amp;amp;&amp;amp; ww &amp;gt; 0)&lt;br /&gt;
                semaphore_V(ok2write);&lt;br /&gt;
        else&lt;br /&gt;
                semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void startwrite(void) {&lt;br /&gt;
// &amp;lt;await nw == 0 &amp;amp;&amp;amp; nr == 0 -&amp;gt; nw++&amp;gt;&lt;br /&gt;
        semaphore_P(mutex);&lt;br /&gt;
        if (nw &amp;gt; 0 || nr &amp;gt; 0) {&lt;br /&gt;
                ww++;&lt;br /&gt;
                semaphore_V(mutex);&lt;br /&gt;
                semaphore_P(ok2write);&lt;br /&gt;
                ww--;&lt;br /&gt;
        }&lt;br /&gt;
        nw++;&lt;br /&gt;
        w_last=1;&lt;br /&gt;
        printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, nr, nw, wr, ww);&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void endwrite(void) {&lt;br /&gt;
// &amp;lt;nw--&amp;gt;&lt;br /&gt;
        semaphore_P(mutex);&lt;br /&gt;
        nw--;&lt;br /&gt;
        printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, nr, nw, wr, ww);&lt;br /&gt;
        if (wr &amp;gt; 0 &amp;amp;&amp;amp; (ww == 0 || w_last))&lt;br /&gt;
                semaphore_V(ok2read);&lt;br /&gt;
        else if (ww &amp;gt; 0 &amp;amp;&amp;amp; (wr == 0 || !w_last))&lt;br /&gt;
                semaphore_V(ok2write);&lt;br /&gt;
        else&lt;br /&gt;
                semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void *reader(void *arg) {&lt;br /&gt;
        int i = (uintptr_t)arg;&lt;br /&gt;
        while (1) {&lt;br /&gt;
                //other code&lt;br /&gt;
                usleep(random() % 200000);&lt;br /&gt;
                startread();&lt;br /&gt;
                //read&lt;br /&gt;
                usleep(random() % 200000);&lt;br /&gt;
                endread();&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void *writer(void *arg) {&lt;br /&gt;
        int i = (uintptr_t)arg;&lt;br /&gt;
        while (1) {&lt;br /&gt;
                //other code&lt;br /&gt;
                usleep(random() % 200000);&lt;br /&gt;
                startwrite();&lt;br /&gt;
                //write&lt;br /&gt;
                usleep(random() % 200000);&lt;br /&gt;
                endwrite();&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//printf(&amp;quot;philo thinking: %d\n&amp;quot;,i);&lt;br /&gt;
/*while*/&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char *argv[]) {&lt;br /&gt;
        int i;&lt;br /&gt;
        pthread_t t;&lt;br /&gt;
        srandom(time(NULL));&lt;br /&gt;
        mutex=semaphore_create(1);&lt;br /&gt;
        ok2read=semaphore_create(0);&lt;br /&gt;
        ok2write=semaphore_create(0);&lt;br /&gt;
        for (i=0; i&amp;lt;NREADER; i++)&lt;br /&gt;
                pthread_create(&amp;amp;t, NULL, reader, (void *)(uintptr_t) i);&lt;br /&gt;
        for (i=0; i&amp;lt;NWRITER; i++)&lt;br /&gt;
                pthread_create(&amp;amp;t, NULL, writer, (void *)(uintptr_t) i);&lt;br /&gt;
        while(1)&lt;br /&gt;
                pause();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== RW di FedericoB ==&lt;br /&gt;
Propongo la seguente soluzione. Mi sembra che funzioni ma devo ancora capire perchè e documentarla bene. Ho provato prima a cercare il bug ma non ci sono riuscito. Ho quindi modificato il codice secondo ciò che mi sembrava sensato in base alle condizioni del problema. Ne possiamo parlare in aula oggi. --[[User:FedericoB|FedericoB]] ([[User talk:FedericoB|talk]]) 12:48, 11 November 2016 (CET)&lt;br /&gt;
Ho notato che l'errore non si manifesta più eliminando il controllo che ci siano scrittori in attesa quando un lettore vuole iniziare a scrivere. Non capisco come questo possa essere collegato al bug. --[[User:FedericoB|FedericoB]] ([[User talk:FedericoB|talk]]) 15:10, 11 November 2016 (CET)&lt;br /&gt;
&lt;br /&gt;
FedericoB, questa soluzione &amp;amp;egrave; quella con priorit&amp;amp;agrave; ai lettori, no? Se continuano ad arrivare lettori numberOfReaders non sar&amp;amp;agrave; mai zero e quindi gli scrittori non scriveranno mai. [[User:Renzo|Renzo]] ([[User talk:Renzo|talk]]) 10:34, 12 November 2016 (CET)&lt;br /&gt;
&lt;br /&gt;
SFIDA: ho trovato il modo di togliere la starvation aggiungendo 4 token (parole chiave, nomi di variabili, operatori, costanti) a questa soluzione di FedericoB. Chi trova la soluzione? [[User:Renzo|Renzo]] ([[User talk:Renzo|talk]]) 10:43, 12 November 2016 (CET) Ah! ho appena trovato una soluzione che prevede 2 soli token in pi&amp;amp;ugrave;! [[User:Renzo|Renzo]] ([[User talk:Renzo|talk]]) 10:47, 12 November 2016 (CET)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
#include&amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include&amp;lt;stdint.h&amp;gt;&lt;br /&gt;
#include&amp;lt;pthread.h&amp;gt;&lt;br /&gt;
#include&amp;lt;semaphore.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define NUMBER_OF_READERS 3&lt;br /&gt;
#define NUMBER_OF_WRITERS 3&lt;br /&gt;
semaphore mutex;&lt;br /&gt;
semaphore ok2read;&lt;br /&gt;
semaphore ok2write;&lt;br /&gt;
&lt;br /&gt;
int numberOfReaders=0;&lt;br /&gt;
int numberOfWriters=0;&lt;br /&gt;
int waitingReaders=0;&lt;br /&gt;
int waitingWriters=0;&lt;br /&gt;
&lt;br /&gt;
// (nw == 0 &amp;amp;&amp;amp; nr == 0) || (nr &amp;gt; 0 &amp;amp;&amp;amp; nw == 0) || nw == 1&lt;br /&gt;
// (nw == 0 &amp;amp;&amp;amp; nr &amp;gt;= 0) || nw == 1&lt;br /&gt;
&lt;br /&gt;
void startread(void) {&lt;br /&gt;
// &amp;lt;await nw == 0 -&amp;gt; nr++&amp;gt;&lt;br /&gt;
    semaphore_P(mutex);&lt;br /&gt;
    if (numberOfWriters &amp;gt; 0) {&lt;br /&gt;
        waitingReaders++;&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
        semaphore_P(ok2read);&lt;br /&gt;
        waitingReaders--;&lt;br /&gt;
    }&lt;br /&gt;
    numberOfReaders++;&lt;br /&gt;
    printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, numberOfReaders, numberOfWriters, waitingReaders, waitingWriters);&lt;br /&gt;
    if (waitingReaders &amp;gt; 0 )&lt;br /&gt;
        semaphore_V(ok2read);&lt;br /&gt;
    else&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void endread(void) {&lt;br /&gt;
// &amp;lt;nr--&amp;gt;&lt;br /&gt;
    semaphore_P(mutex);&lt;br /&gt;
    numberOfReaders--;&lt;br /&gt;
    printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, numberOfReaders, numberOfWriters, waitingReaders, waitingWriters);&lt;br /&gt;
    if (numberOfReaders == 0 &amp;amp;&amp;amp; waitingWriters &amp;gt; 0)&lt;br /&gt;
        semaphore_V(ok2write);&lt;br /&gt;
    else&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void startwrite(void) {&lt;br /&gt;
// &amp;lt;await nw == 0 &amp;amp;&amp;amp; nr == 0 -&amp;gt; nw++&amp;gt;&lt;br /&gt;
    semaphore_P(mutex);&lt;br /&gt;
    if (numberOfWriters &amp;gt; 0 || numberOfReaders &amp;gt; 0) {&lt;br /&gt;
        waitingWriters++;&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
        semaphore_P(ok2write);&lt;br /&gt;
        waitingWriters--;&lt;br /&gt;
    }&lt;br /&gt;
    numberOfWriters++;&lt;br /&gt;
    printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, numberOfReaders, numberOfWriters, waitingReaders, waitingWriters);&lt;br /&gt;
    semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void endwrite(void) {&lt;br /&gt;
// &amp;lt;nw--&amp;gt;&lt;br /&gt;
    semaphore_P(mutex);&lt;br /&gt;
    numberOfWriters--;&lt;br /&gt;
    printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, numberOfReaders, numberOfWriters, waitingReaders, waitingWriters);&lt;br /&gt;
    if (waitingReaders &amp;gt; 0)&lt;br /&gt;
        semaphore_V(ok2read);&lt;br /&gt;
    else if (waitingWriters &amp;gt; 0)&lt;br /&gt;
        semaphore_V(ok2write);&lt;br /&gt;
    else&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void *reader(void *arg) {&lt;br /&gt;
    int i = (uintptr_t)arg;&lt;br /&gt;
    while (1) {&lt;br /&gt;
        //other code&lt;br /&gt;
        usleep(random() % 200000);&lt;br /&gt;
        startread();&lt;br /&gt;
        //read&lt;br /&gt;
        usleep(random() % 200000);&lt;br /&gt;
        endread();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void *writer(void *arg) {&lt;br /&gt;
    int i = (uintptr_t)arg;&lt;br /&gt;
    while (1) {&lt;br /&gt;
        //other code&lt;br /&gt;
        usleep(random() % 200000);&lt;br /&gt;
        startwrite();&lt;br /&gt;
        //write&lt;br /&gt;
        usleep(random() % 200000);&lt;br /&gt;
        endwrite();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//printf(&amp;quot;philo thinking: %d\n&amp;quot;,i);&lt;br /&gt;
/*while*/&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char *argv[]) {&lt;br /&gt;
    int i;&lt;br /&gt;
    pthread_t t;&lt;br /&gt;
    srandom(time(NULL));&lt;br /&gt;
    mutex=semaphore_create(1);&lt;br /&gt;
    ok2read=semaphore_create(0);&lt;br /&gt;
    ok2write=semaphore_create(0);&lt;br /&gt;
    for (i=0; i&amp;lt;NUMBER_OF_READERS; i++)&lt;br /&gt;
        pthread_create(&amp;amp;t, NULL, reader, (void *)(uintptr_t) i);&lt;br /&gt;
    for (i=0; i&amp;lt;NUMBER_OF_WRITERS; i++)&lt;br /&gt;
        pthread_create(&amp;amp;t, NULL, writer, (void *)(uintptr_t) i);&lt;br /&gt;
    while(1)&lt;br /&gt;
        pause();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== RW2 ==&lt;br /&gt;
Buongiorno, guardando il codice visto a lezione mi sembra che cambiando la condizione del primo if nella startread() da &amp;quot;if (nw &amp;gt; 0 &amp;amp;&amp;amp; ww == 0)&amp;quot; a &amp;quot;if (nw &amp;gt; 0 || ww &amp;gt; 0)&amp;quot; la situazione migliori. In particolare con l'and tra quelle due condizioni si aveva che non veniva fatta la P sull'ok2read anche quando si aveva nw&amp;gt;0 (con ww!=0), cosa che invece dovrebbe fare. Lasciando il resto del codice uguale mi sembra che faccia quello che deve fare.. .&lt;br /&gt;
&lt;br /&gt;
Matteo.pincherle: Perch&amp;amp;eacute; non modifichi in programma di FedericoB, lo provi e pubblichi qui la patch? [[User:Renzo|Renzo]] ([[User talk:Renzo|talk]]) 10:42, 13 November 2016 (CET)&lt;br /&gt;
&lt;br /&gt;
'''Perchè quel AND permetteva di avere 2 scrittori?''' &amp;lt;br&amp;gt;&lt;br /&gt;
Permetteva in primis di avere dei lettori in contemporanea a uno scrittore. In quanto se succedeva che un lettore volesse entrare mentre non c'erano degli scrittori in attesa ma scrittori in scrittura, veniva saltato il blocco che mandava il lettore in attesa e risultava un lettore in contemporanea a uno scrittore. &amp;lt;br&amp;gt;&lt;br /&gt;
Questo lettore poi poteva finire di leggere prima che lo scrittore in contemporanea a lui finisse di scrivere. &amp;lt;br&amp;gt;&lt;br /&gt;
Il lettore in uscita se non c'erano altri lettori con lui e non c'erano scrittori in attesa dava il permesso per far accedere un altro scrittore. &amp;lt;br&amp;gt;&lt;br /&gt;
A questo punto un altro scrittore che avesse voluto entrare poteva entrare, con il risultato di avere 2 scrittori in contemporanea.&lt;br /&gt;
--[[User:FedericoB|FedericoB]] ([[User talk:FedericoB|talk]]) 19:25, 13 November 2016 (CET)&lt;br /&gt;
&lt;br /&gt;
== Patch ==&lt;br /&gt;
Così, se non sbaglio, quando c'è almeno uno scrittore in attesa non lascia entrare altri lettori. Fa esaurire la lettura dei presenti e poi lascia scrivere lo scrittore.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include&amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include&amp;lt;stdint.h&amp;gt;&lt;br /&gt;
#include&amp;lt;pthread.h&amp;gt;&lt;br /&gt;
#include&amp;lt;semaphore.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define NUMBER_OF_READERS 3&lt;br /&gt;
#define NUMBER_OF_WRITERS 3&lt;br /&gt;
semaphore mutex;&lt;br /&gt;
semaphore ok2read;&lt;br /&gt;
semaphore ok2write;&lt;br /&gt;
&lt;br /&gt;
int numberOfReaders=0;&lt;br /&gt;
int numberOfWriters=0;&lt;br /&gt;
int waitingReaders=0;&lt;br /&gt;
int waitingWriters=0;&lt;br /&gt;
int w_last;&lt;br /&gt;
&lt;br /&gt;
// (nw == 0 &amp;amp;&amp;amp; nr == 0) || (nr &amp;gt; 0 &amp;amp;&amp;amp; nw == 0) || nw == 1&lt;br /&gt;
// (nw == 0 &amp;amp;&amp;amp; nr &amp;gt;= 0) || nw == 1&lt;br /&gt;
&lt;br /&gt;
void startread(void) {&lt;br /&gt;
    // &amp;lt;await nw == 0 -&amp;gt; nr++&amp;gt;&lt;br /&gt;
    semaphore_P(mutex);&lt;br /&gt;
    if (numberOfWriters &amp;gt; 0 || waitingWriters&amp;gt;0) {&lt;br /&gt;
        waitingReaders++;&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
        semaphore_P(ok2read);&lt;br /&gt;
        waitingReaders--;&lt;br /&gt;
    }&lt;br /&gt;
    numberOfReaders++;&lt;br /&gt;
    w_last=0;&lt;br /&gt;
    printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, numberOfReaders, numberOfWriters, waitingReaders, waitingWriters);&lt;br /&gt;
    if (waitingReaders &amp;gt; 0 )&lt;br /&gt;
        semaphore_V(ok2read);&lt;br /&gt;
    else&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void endread(void) {&lt;br /&gt;
    // &amp;lt;nr--&amp;gt;&lt;br /&gt;
    semaphore_P(mutex);&lt;br /&gt;
    numberOfReaders--;&lt;br /&gt;
    printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, numberOfReaders, numberOfWriters, waitingReaders, waitingWriters);&lt;br /&gt;
    if (numberOfReaders == 0 &amp;amp;&amp;amp; waitingWriters &amp;gt; 0)&lt;br /&gt;
        semaphore_V(ok2write);&lt;br /&gt;
    else&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void startwrite(void) {&lt;br /&gt;
    // &amp;lt;await nw == 0 &amp;amp;&amp;amp; nr == 0 -&amp;gt; nw++&amp;gt;&lt;br /&gt;
    semaphore_P(mutex);&lt;br /&gt;
    if (numberOfWriters &amp;gt; 0 || numberOfReaders &amp;gt; 0) {&lt;br /&gt;
        waitingWriters++;&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
        semaphore_P(ok2write);&lt;br /&gt;
        waitingWriters--;&lt;br /&gt;
    }&lt;br /&gt;
    numberOfWriters++;&lt;br /&gt;
    w_last=1;&lt;br /&gt;
    printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, numberOfReaders, numberOfWriters, waitingReaders, waitingWriters);&lt;br /&gt;
    semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void endwrite(void) {&lt;br /&gt;
    // &amp;lt;nw--&amp;gt;&lt;br /&gt;
    semaphore_P(mutex);&lt;br /&gt;
    numberOfWriters--;&lt;br /&gt;
    printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, numberOfReaders, numberOfWriters, waitingReaders, waitingWriters);&lt;br /&gt;
    if (waitingReaders &amp;gt; 0 &amp;amp;&amp;amp; (waitingWriters==0 || w_last))&lt;br /&gt;
        semaphore_V(ok2read);&lt;br /&gt;
    else if (waitingWriters &amp;gt; 0 &amp;amp;&amp;amp; (waitingReaders==0 || !w_last))&lt;br /&gt;
        semaphore_V(ok2write);&lt;br /&gt;
    else&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void *reader(void *arg) {&lt;br /&gt;
    int i = (uintptr_t)arg;&lt;br /&gt;
    while (1) {&lt;br /&gt;
        //other code&lt;br /&gt;
        usleep(random() % 200000);&lt;br /&gt;
        startread();&lt;br /&gt;
        //read&lt;br /&gt;
        usleep(random() % 200000);&lt;br /&gt;
        endread();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void *writer(void *arg) {&lt;br /&gt;
    int i = (uintptr_t)arg;&lt;br /&gt;
    while (1) {&lt;br /&gt;
        //other code&lt;br /&gt;
        usleep(random() % 200000);&lt;br /&gt;
        startwrite();&lt;br /&gt;
        //write&lt;br /&gt;
        usleep(random() % 200000);&lt;br /&gt;
        endwrite();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char *argv[]) {&lt;br /&gt;
    int i;&lt;br /&gt;
    pthread_t t;&lt;br /&gt;
    srandom(time(NULL));&lt;br /&gt;
    mutex=semaphore_create(1);&lt;br /&gt;
    ok2read=semaphore_create(0);&lt;br /&gt;
    ok2write=semaphore_create(0);&lt;br /&gt;
    for (i=0; i&amp;lt;NUMBER_OF_READERS; i++)&lt;br /&gt;
        pthread_create(&amp;amp;t, NULL, reader, (void *)(uintptr_t) i);&lt;br /&gt;
    for (i=0; i&amp;lt;NUMBER_OF_WRITERS; i++)&lt;br /&gt;
        pthread_create(&amp;amp;t, NULL, writer, (void *)(uintptr_t) i);&lt;br /&gt;
    while(1)&lt;br /&gt;
        pause();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
wlast non serve pi&amp;amp;ugrave;... [[User:Renzo|Renzo]] ([[User talk:Renzo|talk]]) 17:52, 13 November 2016 (CET)&lt;br /&gt;
&lt;br /&gt;
== RW2bis ==&lt;br /&gt;
Nella tua soluzione se i lettori sono &amp;quot;molto veloci&amp;quot; e non vanno mai a 0, lo scrittore non inizierà mai a scrivere.&lt;br /&gt;
&lt;br /&gt;
Cioè: Uno scrittore viene svegliato da ok2write solo se passa la condizione &lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
[..] &lt;br /&gt;
if (numberofReaders == 0 &amp;amp;&amp;amp; waitingWriters &amp;gt;0) &lt;br /&gt;
     semaphore_V(ok2write);&lt;br /&gt;
[..]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; --[[User:GabrieleCalarota|GabrieleCalarota]] ([[User talk:GabrieleCalarota|talk]]) 17:46, 13 November 2016 (CET)&lt;br /&gt;
&lt;br /&gt;
Non direi perche' nella startread se:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
    if (numberOfWriters &amp;gt; 0 || waitingWriters&amp;gt;0) &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
i lettori si bloccano. Quindi se c'e' almeno uno scrittore in attesa i lettori non entrano (e quindi prima o poi terminano e lasciano il posto ad uno scrittore).&lt;br /&gt;
[[User:Renzo|Renzo]] ([[User talk:Renzo|talk]]) 17:57, 13 November 2016 (CET)&lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
Ho pensato al caso limite seguente:&lt;br /&gt;
Supponiamo che ci siano dei lettori che stanno leggendo e ad un certo punto uno scrittore chiede di scrivere.&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;syntaxhighlight lang=C&amp;gt;         &lt;br /&gt;
       void startread(void) {&lt;br /&gt;
    // &amp;lt;await nw == 0 -&amp;gt; nr++&amp;gt;&lt;br /&gt;
    semaphore_P(mutex);&lt;br /&gt;
    if (numberOfWriters &amp;gt; 0 || waitingWriters&amp;gt;0) {&lt;br /&gt;
        waitingReaders++;   //Nuovo scrittore (t1)&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
        semaphore_P(ok2read);&lt;br /&gt;
        waitingReaders--;&lt;br /&gt;
    }&lt;br /&gt;
    numberOfReaders++;&lt;br /&gt;
    w_last=0;&lt;br /&gt;
    printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, numberOfReaders, numberOfWriters, waitingReaders, waitingWriters);&lt;br /&gt;
   if (waitingReaders &amp;gt; 0 )   //Vecchio scrittore(t1)&lt;br /&gt;
        semaphore_V(ok2read);&lt;br /&gt;
    else&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Non appena lo scrittore rilascia il mutex, un nuovo lettore chiede di leggere (e si addormenterà). Un lettore (lento) che era riuscito a entrare nel segmento startofread prima che lo scrittore entrasse in startofwrite, continua a leggere e risveglia uno dei nuovi lettori. Se i lettori continuano a richiedere di leggere continuamente, verranno addormentati e subito risvegliati. &lt;br /&gt;
&lt;br /&gt;
E' da considerarsi possibile? --[[User:GabrieleCalarota|GabrieleCalarota]] ([[User talk:GabrieleCalarota|talk]]) 19:11, 13 November 2016 (CET)&lt;br /&gt;
&lt;br /&gt;
Suppongo che &amp;quot;un nuovo scrittore chiede di leggere&amp;quot; si aun refuso e sia da intendere &amp;quot;un nuovo lettore chiede di leggere&amp;quot; (altrimenti ci sono crisi di identit&amp;amp;agrave;) e che &amp;quot;startofread&amp;quot; significhi &amp;quot;startread&amp;quot; e &amp;quot;startofwrite&amp;quot;  sia &amp;quot;startwrite&amp;quot;.&lt;br /&gt;
La &amp;quot;startread&amp;quot; viene eseguita in mutua esclusione, quindi non ci puo' essere &amp;quot;un lettore lento che sia riuscito ad entrare&amp;quot; nella funione startread. Se ha superato la P(mutex) iniziale o e' bloccato sulla ok2read o e' entrato. [[User:Renzo|Renzo]] ([[User talk:Renzo|talk]]) 19:37, 13 November 2016 (CET)&lt;/div&gt;</summary>
		<author><name>GabrieleCalarota</name></author>
	</entry>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=Zibaldone&amp;diff=1711</id>
		<title>Zibaldone</title>
		<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php?title=Zibaldone&amp;diff=1711"/>
		<updated>2016-12-14T17:35:11Z</updated>

		<summary type="html">&lt;p&gt;GabrieleCalarota: /* Monitor: Ponte a senso Unico */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Monitor: Ponte a senso Unico ==&lt;br /&gt;
Proposta di soluzione: esercizio 1 esame 22/01/2014&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
//&lt;br /&gt;
//  20140122_bridge&lt;br /&gt;
//&lt;br /&gt;
/*   Esercizio c.1:&lt;br /&gt;
 *&lt;br /&gt;
 *   Per colpa delle frane un ponte veicolare e' rimasto danneggiato.&lt;br /&gt;
 *   I veicoli possono ora percorrerlo solo in senso unico alternato e, per non eccedere la portata,&lt;br /&gt;
 *   al piu' ci possono essere sul ponte N veicoli contemporaneamente.&lt;br /&gt;
 *   Scrivere il monitor bridge sapendo che i veicoli chiameranno il monitor prima di entrare nel&lt;br /&gt;
 *   ponte e dopo averlo attraversato.&lt;br /&gt;
 *   I veicoli che entrano dal lato est escono dal lato ovest e viceversa.&lt;br /&gt;
 *   Quindi i (numerosi) veicoli eseguiranno uno dei due frammenti di codice seguenti:&lt;br /&gt;
 *&lt;br /&gt;
 *&lt;br /&gt;
 *   bridge.enter(E)                      bridge.enter(W)&lt;br /&gt;
 *   //cross the bridge                   //cross the bridge&lt;br /&gt;
 *   bridge.exit(W)                       bridge.exit(E)&lt;br /&gt;
 *&lt;br /&gt;
 *&lt;br /&gt;
 *   La soluzione proposta deve evitare deadlock e deve essere efficiente.&lt;br /&gt;
 *   (controesempio: una soluzione che prevedesse l'attraversamento del ponte da parte di un solo veicolo alla volta&lt;br /&gt;
 *   sebbene rispetti tutti i vincoli sarebbe considerata errata poiche' inefficiente).&lt;br /&gt;
 *   Oltre al codice si richiede una descrizione degli accorgimenti adottati per rendere la soluzione efficiente.&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;quot;monitor.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
#define CAPACITY 7 //capacità del bridge&lt;br /&gt;
#define BALANCE 9  &lt;br /&gt;
#define NCAR 15&lt;br /&gt;
&lt;br /&gt;
enum dest{&lt;br /&gt;
    E = 0,&lt;br /&gt;
    W = 1&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
int ncrossing_we = 0; //n car che stanno attraversando il bridge da W-&amp;gt;E&lt;br /&gt;
int ncrossing_ew = 0; //n car che stanno attraversando il bridge da E-&amp;gt;W&lt;br /&gt;
&lt;br /&gt;
int nwaiting_we = 0; //n car che aspettano di attraversare da W-&amp;gt;E&lt;br /&gt;
int nwaiting_ew = 0;  //n car che aspettano di attraversare da E-&amp;gt;W&lt;br /&gt;
&lt;br /&gt;
int priority = BALANCE;&lt;br /&gt;
&lt;br /&gt;
int crossed_we = 0; //n volte che il ponte è stato attraversato da W-&amp;gt;E&lt;br /&gt;
int crossed_ew = 0; //n volte che il ponte è stato attraversato da E-&amp;gt;W&lt;br /&gt;
&lt;br /&gt;
condition ok2goW; // capacity &amp;gt; 0 &amp;amp;&amp;amp; (ncrossing_ew == 0 || priority &amp;gt; 0)&lt;br /&gt;
condition ok2goE; // capacity &amp;gt; 0 &amp;amp;&amp;amp; (ncrossing_we == 0 || prioriti &amp;gt; 0 )&lt;br /&gt;
monitor bridge;&lt;br /&gt;
&lt;br /&gt;
void bridge_create(void){&lt;br /&gt;
    bridge = monitor_create();&lt;br /&gt;
    ok2goW = condition_create(bridge);&lt;br /&gt;
    ok2goE = condition_create(bridge);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void bridge_enter(enum dest d){&lt;br /&gt;
    monitor_enter(bridge);&lt;br /&gt;
    if (d == W) {&lt;br /&gt;
        nwaiting_we++;&lt;br /&gt;
        if (ncrossing_we &amp;gt;= CAPACITY || ncrossing_ew &amp;gt; 0 || (nwaiting_ew &amp;gt; 0 &amp;amp;&amp;amp; priority &amp;lt;= 0)) {&lt;br /&gt;
            condition_wait(ok2goW);&lt;br /&gt;
        }&lt;br /&gt;
        priority--;&lt;br /&gt;
        nwaiting_we--;&lt;br /&gt;
        ncrossing_we++;&lt;br /&gt;
        if (ncrossing_we &amp;lt; CAPACITY &amp;amp;&amp;amp; priority &amp;gt; 0) {&lt;br /&gt;
            condition_signal(ok2goW);&lt;br /&gt;
        }&lt;br /&gt;
    }else if(d == E){&lt;br /&gt;
        nwaiting_ew++;&lt;br /&gt;
        if (ncrossing_ew &amp;gt;= CAPACITY || ncrossing_we &amp;gt; 0 || (nwaiting_we &amp;gt; 0 &amp;amp;&amp;amp; priority &amp;lt;= 0)){&lt;br /&gt;
            condition_wait(ok2goE);&lt;br /&gt;
        }&lt;br /&gt;
        priority--;&lt;br /&gt;
        nwaiting_ew--;&lt;br /&gt;
        ncrossing_ew++;&lt;br /&gt;
        if (ncrossing_ew &amp;lt; CAPACITY &amp;amp;&amp;amp; priority &amp;gt; 0) {&lt;br /&gt;
            condition_signal(ok2goE);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    monitor_exit(bridge);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void bridge_exit(enum dest d){&lt;br /&gt;
    monitor_enter(bridge);&lt;br /&gt;
    if (d == E) {&lt;br /&gt;
        ncrossing_we--;&lt;br /&gt;
        crossed_we++;&lt;br /&gt;
        if (ncrossing_we &amp;lt; CAPACITY &amp;amp;&amp;amp; nwaiting_we &amp;gt; 0 &amp;amp;&amp;amp; (nwaiting_ew == 0 || priority &amp;gt; 0)) {&lt;br /&gt;
            condition_signal(ok2goW);&lt;br /&gt;
        }else if (ncrossing_we == 0 &amp;amp;&amp;amp; nwaiting_ew &amp;gt; 0 ) {&lt;br /&gt;
            priority = BALANCE;&lt;br /&gt;
            condition_signal(ok2goE);&lt;br /&gt;
        }&lt;br /&gt;
    } else if (d == W){&lt;br /&gt;
        ncrossing_ew--;&lt;br /&gt;
        crossed_ew++;&lt;br /&gt;
        if (ncrossing_ew &amp;lt; CAPACITY &amp;amp;&amp;amp; nwaiting_ew &amp;gt; 0 &amp;amp;&amp;amp; (nwaiting_we == 0 || priority &amp;gt; 0)) {&lt;br /&gt;
            condition_signal(ok2goE);&lt;br /&gt;
        }else if (ncrossing_ew == 0 &amp;amp;&amp;amp; nwaiting_we &amp;gt; 0) {&lt;br /&gt;
            priority = BALANCE;&lt;br /&gt;
            condition_signal(ok2goW);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    monitor_exit(bridge);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void *crossEW(void* arg){&lt;br /&gt;
    while (1) {&lt;br /&gt;
        printf(&amp;quot;waitW: %d |-|%d|-&amp;gt;  &amp;lt;-|%d|-| waitE: %d  || crossed W-&amp;gt;E: %d crossed E-&amp;gt;W: %d||\n&amp;quot;, nwaiting_we, ncrossing_we, ncrossing_ew, nwaiting_ew, crossed_we, crossed_ew);&lt;br /&gt;
        usleep(random() % 200000);&lt;br /&gt;
        bridge_enter(E);&lt;br /&gt;
        usleep(random() % 20000);&lt;br /&gt;
        bridge_exit(W);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void *crossWE(void* arg){&lt;br /&gt;
    while (1) {&lt;br /&gt;
        printf(&amp;quot;waitW: %d |-|%d|-&amp;gt;  &amp;lt;-|%d|-| waitE: %d  || crossed W-&amp;gt;E: %d crossed E-&amp;gt;W: %d||\n&amp;quot;, nwaiting_we, ncrossing_we, ncrossing_ew, nwaiting_ew, crossed_we, crossed_ew);&lt;br /&gt;
        usleep(random() % 200000);&lt;br /&gt;
        bridge_enter(W);&lt;br /&gt;
        usleep(random() % 20000);&lt;br /&gt;
        bridge_exit(E);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main(int argc, const char * argv[]) {&lt;br /&gt;
    pthread_t e_w_t[NCAR];&lt;br /&gt;
    pthread_t w_e_t[NCAR];&lt;br /&gt;
    bridge_create();&lt;br /&gt;
&lt;br /&gt;
    srandom(time(NULL));&lt;br /&gt;
    for (int i = 0; i &amp;lt; NCAR; i++) {&lt;br /&gt;
        pthread_create(&amp;amp;e_w_t[i], NULL, crossEW, NULL);&lt;br /&gt;
        pthread_create(&amp;amp;w_e_t[i], NULL, crossWE, NULL);&lt;br /&gt;
&lt;br /&gt;
    }&lt;br /&gt;
    for (int i = 0; i &amp;lt; NCAR; i++) {&lt;br /&gt;
        pthread_join(w_e_t[i], NULL);&lt;br /&gt;
        pthread_join(e_w_t[i], NULL);&lt;br /&gt;
    }&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Dal testo dell'esercizio si evincono le seguenti condizioni basilari per poter attraversare il ponte:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
   (capacità&amp;gt;0 &amp;amp;&amp;amp; ncrossing_OppositeDirection == 0)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Per rendere la soluzione efficiente ho introdotto, così, la variabile priority settata al valore BALANCE ottenendo la seguente condizione:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
priority &amp;gt; 0 || nwaitingOppositeDirection == 0; &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
e.i. fin quando il mio senso (e.g. W-&amp;gt;E) ha ancora priorità di attraversare  O non ci sono macchine nella &lt;br /&gt;
direzione opposta che attendono, continuo a dare il via alle macchine che vanno nella mia stessa direzione.&lt;br /&gt;
Priority viene decrementata ad ogni macchina che attraversa il ponte.&lt;br /&gt;
&lt;br /&gt;
Non appena tale condizione viene interrotta, priority viene restaurata al valore BALANCE e la sua gestione viene ceduta al senso opposto.&lt;br /&gt;
Notare che anche questa soluzione non gestisce il caso in cui &amp;quot;il mio senso ha priorità ma non c'è nessuno che vuole attraversare&amp;quot;, &lt;br /&gt;
sarebbe inutile far attendere e maccchine della direzione opposta.&lt;br /&gt;
Allora il tutto viene gestito come segue:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
   bridge.enter()&lt;br /&gt;
    if (ncrossing_MyDirection &amp;lt;= CAPACITY &amp;amp;&amp;amp; ncrossing_OppositeDirection == 0 &amp;amp;&amp;amp; (mypriority &amp;gt; 0 || nwaitingOppositeDirection == 0)){&lt;br /&gt;
					 attraverso il ponte;&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
    bridge.exit()&lt;br /&gt;
	if (ncrossing_MyDirection &amp;lt; CAPACITY &amp;amp;&amp;amp; nwaiting_MyDirection &amp;gt; 0 &amp;amp;&amp;amp; (nwaiting_OppositeDirection == 0 || mypriority &amp;gt; 0)) {&lt;br /&gt;
            		do il via a chi attende di attraversare nella mia stessa direzione;&lt;br /&gt;
        }else if (ncrossing_MyDirection == 0 &amp;amp;&amp;amp; nwaiting_OppositeDirection &amp;gt; 0 ) {&lt;br /&gt;
            		restauro priority e lascio il comando alle macchine nella direzione opposta;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
L’ultima possibilità è che nessuno vuole attraversare il bridge, in questo caso nn faccio nulla. &lt;br /&gt;
Il comando resta alla direzione che per ultima ha attraversato il bridge&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;monitor.h&amp;gt;&lt;br /&gt;
#include &amp;lt;pthread.h&amp;gt;&lt;br /&gt;
#include &amp;lt;string.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
const int NCAR_E=8;&lt;br /&gt;
const int NCAR_W=8;&lt;br /&gt;
const int MAX_CAR = 7;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
enum dir{E,W,N};&lt;br /&gt;
int n_carcross = 0;&lt;br /&gt;
int waiting[2] = {0,0}; //[0] = [E] ; [1] = [W]&lt;br /&gt;
enum dir curr_dir = N; &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
monitor bridge;&lt;br /&gt;
condition ok2go[2];&lt;br /&gt;
&lt;br /&gt;
void bridge_create(){&lt;br /&gt;
	bridge = monitor_create();&lt;br /&gt;
	ok2go[0] = condition_create(bridge);&lt;br /&gt;
	ok2go[1] = condition_create(bridge);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void print_bridge(){&lt;br /&gt;
	if (curr_dir == E)&lt;br /&gt;
		printf(&amp;quot;%d W &amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;%d&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt; E %d\n&amp;quot;,waiting[1],n_carcross,waiting[0]);&lt;br /&gt;
	else&lt;br /&gt;
		printf(&amp;quot;%d W &amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;%d&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; E %d\n&amp;quot;,waiting[1],n_carcross,waiting[0]);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void bridge_enter(enum dir d){&lt;br /&gt;
	monitor_enter(bridge);&lt;br /&gt;
	int i = (int) d;&lt;br /&gt;
	if (curr_dir == N){&lt;br /&gt;
		curr_dir = d;&lt;br /&gt;
		change_dir(d);&lt;br /&gt;
		//printf(&amp;quot;Direction is %s\n&amp;quot;,dir);&lt;br /&gt;
	}&lt;br /&gt;
	if ((curr_dir != d) || (n_carcross &amp;gt;= MAX_CAR) || (waiting[1-i]&amp;gt;0)){&lt;br /&gt;
			waiting[i]++;&lt;br /&gt;
			condition_wait(ok2go[i]);&lt;br /&gt;
			waiting[i]--;&lt;br /&gt;
	}&lt;br /&gt;
	n_carcross++;&lt;br /&gt;
	print_bridge();&lt;br /&gt;
	if (n_carcross &amp;lt; MAX_CAR){&lt;br /&gt;
		if (waiting[i]&amp;gt;0)&lt;br /&gt;
			condition_signal(ok2go[i]);&lt;br /&gt;
	}&lt;br /&gt;
	monitor_exit(bridge);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void bridge_exit(enum dir d){&lt;br /&gt;
 monitor_enter(bridge);&lt;br /&gt;
 int i = (int) d;&lt;br /&gt;
 n_carcross--;&lt;br /&gt;
 print_bridge();&lt;br /&gt;
 if (waiting[i]&amp;gt;0){&lt;br /&gt;
 	if (n_carcross == 0){&lt;br /&gt;
 		//printf(&amp;quot;Direction changed from %s &amp;quot;,dir);&lt;br /&gt;
 		change_dir(d);&lt;br /&gt;
 		//printf(&amp;quot;to %s\n&amp;quot;,dir);&lt;br /&gt;
 		curr_dir = (enum dir) (1 - curr_dir);&lt;br /&gt;
 		condition_signal(ok2go[i]);&lt;br /&gt;
 	}&lt;br /&gt;
 }&lt;br /&gt;
 else&lt;br /&gt;
 	condition_signal(ok2go[1-i]);&lt;br /&gt;
 monitor_exit(bridge);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void *cross(void* arg){&lt;br /&gt;
	enum dir d = (enum dir) arg;&lt;br /&gt;
	while (1) {&lt;br /&gt;
	        usleep(random() % 2000000);&lt;br /&gt;
	        bridge_enter(d);&lt;br /&gt;
	        usleep(random() % 2000000);&lt;br /&gt;
	        bridge_exit((enum dir)(1-d));&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main(int argc, const char * argv[]) {&lt;br /&gt;
    pthread_t e_t[NCAR_E];&lt;br /&gt;
    pthread_t w_t[NCAR_W];&lt;br /&gt;
    &lt;br /&gt;
    bridge_create();&lt;br /&gt;
 &lt;br /&gt;
    srandom(time(NULL));&lt;br /&gt;
&lt;br /&gt;
    for (int i = 0; i &amp;lt; NCAR_E; i++) {&lt;br /&gt;
        pthread_create(&amp;amp;e_t[i], NULL, cross,(void*) E); &lt;br /&gt;
    }&lt;br /&gt;
    for (int i = 0; i &amp;lt; NCAR_W; i++) {&lt;br /&gt;
        pthread_create(&amp;amp;w_t[i], NULL, cross, (void*) W);&lt;br /&gt;
    }&lt;br /&gt;
    for (int i = 0; i &amp;lt; NCAR_E; i++) {&lt;br /&gt;
        pthread_join(e_t[i], NULL);&lt;br /&gt;
    }&lt;br /&gt;
    for (int i = 0; i &amp;lt; NCAR_W; i++) {&lt;br /&gt;
        pthread_join(w_t[i], NULL);&lt;br /&gt;
    }&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Questa è la prima soluzione che mi è venuta in mente cercando di rimanere sul più semplice possibile ... ho adottato alcuni accorgimenti per evitare di avere un programma lungo ma con &amp;quot;doppioni&amp;quot; --[[User:GabrieleCalarota|GabrieleCalarota]] ([[User talk:GabrieleCalarota|talk]]) 18:35, 14 December 2016 (CET)&lt;br /&gt;
&lt;br /&gt;
== Monitor: Cospirazione dei filosofi ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;monitor.h&amp;gt;&lt;br /&gt;
#include &amp;lt;pthread.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdint.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
monitor dp;&lt;br /&gt;
condition philo_wait[5]; /* status[np(i,1)] == 'T' &amp;amp;&amp;amp; status[np(i,-1)] == 'T' */&lt;br /&gt;
char status[] = &amp;quot;TTTTT&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
int np(int i, int off) {&lt;br /&gt;
        return (i+5+off) % 5;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void dp_create(void) {&lt;br /&gt;
        int i;&lt;br /&gt;
        dp = monitor_create();&lt;br /&gt;
        for (i=0; i&amp;lt;5; i++)&lt;br /&gt;
                philo_wait[i] = condition_create(dp);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void dp_starteat(int i) {&lt;br /&gt;
        monitor_enter(dp);&lt;br /&gt;
        if (status[np(i,1)] != 'T' || status[np(i,-1)] != 'T')&lt;br /&gt;
                condition_wait(philo_wait[i]);&lt;br /&gt;
        status[i] = 'E';&lt;br /&gt;
        printf(&amp;quot;%s\n&amp;quot;,status);&lt;br /&gt;
        monitor_exit(dp);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void dp_endeat(int i) {&lt;br /&gt;
        monitor_enter(dp);&lt;br /&gt;
        status[i] = 'T';&lt;br /&gt;
        printf(&amp;quot;%s\n&amp;quot;,status);&lt;br /&gt;
        if (status[np(i,2)] == 'T')&lt;br /&gt;
                condition_signal(philo_wait[np(i,1)]);&lt;br /&gt;
        if (status[np(i,-2)] == 'T')&lt;br /&gt;
                condition_signal(philo_wait[np(i,-1)]);&lt;br /&gt;
        monitor_exit(dp);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
monitor cospy;&lt;br /&gt;
condition wait2eat;&lt;br /&gt;
int cospy_count;&lt;br /&gt;
&lt;br /&gt;
void cospy_create(void) {&lt;br /&gt;
        cospy = monitor_create();&lt;br /&gt;
        wait2eat = condition_create(cospy);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void cospy_starteat(void) {&lt;br /&gt;
        monitor_enter(cospy);&lt;br /&gt;
        cospy_count++;&lt;br /&gt;
        condition_signal(wait2eat);&lt;br /&gt;
        monitor_exit(cospy);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void cospy_endeat(void) {&lt;br /&gt;
        monitor_enter(cospy);&lt;br /&gt;
        cospy_count--;&lt;br /&gt;
        if (cospy_count == 0)&lt;br /&gt;
                condition_wait(wait2eat);&lt;br /&gt;
        monitor_exit(cospy);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void *philo(void *arg) {&lt;br /&gt;
        int i = (uintptr_t) arg;&lt;br /&gt;
        while (1) {&lt;br /&gt;
                usleep(random() % 2000000);&lt;br /&gt;
                dp_starteat(i);&lt;br /&gt;
                if (i == 1 || i == 3)&lt;br /&gt;
                        cospy_starteat();&lt;br /&gt;
                usleep(random() % 2000000);&lt;br /&gt;
                if (i == 1 || i == 3)&lt;br /&gt;
                        cospy_endeat();&lt;br /&gt;
                dp_endeat(i);&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char *argv[]) {&lt;br /&gt;
        pthread_t philo_t[5];&lt;br /&gt;
        uintptr_t i;&lt;br /&gt;
        dp_create();&lt;br /&gt;
        cospy_create();&lt;br /&gt;
        srandom(time(NULL));&lt;br /&gt;
        for (i=0; i&amp;lt;5; i++)&lt;br /&gt;
                pthread_create(&amp;amp;philo_t[i], NULL, philo, (void *) i );&lt;br /&gt;
        while(1)&lt;br /&gt;
                pause();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
--[[User:FedericoB|FedericoB]] ([[User talk:FedericoB|talk]]) 11:27, 25 November 2016 (CET)Veniva creata la condizione di cospirazione collegata al monitor dp invece che cospy. Quindi con il signal il processo veniva messo nell'urgent stack sbagliato e chiamando monitor_exit su cospy non si risvegliava il processo nell' urgent stack di dp.&lt;br /&gt;
&lt;br /&gt;
== RW errato ==&lt;br /&gt;
Codice '''ERRATO''' dei lettori scrittori che dovrebbe non soffrire di problemi di starvation...&lt;br /&gt;
Esercizio: trovare gli errori.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
#include&amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include&amp;lt;stdint.h&amp;gt;&lt;br /&gt;
#include&amp;lt;pthread.h&amp;gt;&lt;br /&gt;
#include&amp;lt;semaphore.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define NREADER 3&lt;br /&gt;
#define NWRITER 3&lt;br /&gt;
semaphore mutex;&lt;br /&gt;
semaphore ok2read;&lt;br /&gt;
semaphore ok2write;&lt;br /&gt;
&lt;br /&gt;
int nr=0;&lt;br /&gt;
int nw=0;&lt;br /&gt;
int wr=0;&lt;br /&gt;
int ww=0;&lt;br /&gt;
int w_last;&lt;br /&gt;
&lt;br /&gt;
// (nw == 0 &amp;amp;&amp;amp; nr == 0) || (nr &amp;gt; 0 &amp;amp;&amp;amp; nw == 0) || nw == 1&lt;br /&gt;
// (nw == 0 &amp;amp;&amp;amp; nr &amp;gt;= 0) || nw == 1&lt;br /&gt;
&lt;br /&gt;
// this &amp;quot;baton&amp;quot; function has been left for reference only.&lt;br /&gt;
// code to implement &amp;quot;passing the baton&amp;quot; has been copied at the end of&lt;br /&gt;
// each ({start}|{end})({read}|{write}) function and reduced.&lt;br /&gt;
void baton(void) {&lt;br /&gt;
        if (nw == 0 &amp;amp;&amp;amp; nr == 0 &amp;amp;&amp;amp; ww &amp;gt; 0)&lt;br /&gt;
                semaphore_V(ok2write);&lt;br /&gt;
        else if (nw == 0 &amp;amp;&amp;amp; wr &amp;gt; 0 )&lt;br /&gt;
                semaphore_V(ok2read);&lt;br /&gt;
        else&lt;br /&gt;
                semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void startread(void) {&lt;br /&gt;
// &amp;lt;await nw == 0 -&amp;gt; nr++&amp;gt;&lt;br /&gt;
        semaphore_P(mutex);&lt;br /&gt;
        if (nw &amp;gt; 0 &amp;amp;&amp;amp; ww == 0) {&lt;br /&gt;
                wr++;&lt;br /&gt;
                semaphore_V(mutex);&lt;br /&gt;
                semaphore_P(ok2read);&lt;br /&gt;
                wr--;&lt;br /&gt;
        }&lt;br /&gt;
        nr++;&lt;br /&gt;
        w_last=0;&lt;br /&gt;
        printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, nr, nw, wr, ww);&lt;br /&gt;
        if (wr &amp;gt; 0 )&lt;br /&gt;
                semaphore_V(ok2read);&lt;br /&gt;
        else&lt;br /&gt;
                semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void endread(void) {&lt;br /&gt;
// &amp;lt;nr--&amp;gt;&lt;br /&gt;
        semaphore_P(mutex);&lt;br /&gt;
        nr--;&lt;br /&gt;
        printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, nr, nw, wr, ww);&lt;br /&gt;
        if (nr == 0 &amp;amp;&amp;amp; ww &amp;gt; 0)&lt;br /&gt;
                semaphore_V(ok2write);&lt;br /&gt;
        else&lt;br /&gt;
                semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void startwrite(void) {&lt;br /&gt;
// &amp;lt;await nw == 0 &amp;amp;&amp;amp; nr == 0 -&amp;gt; nw++&amp;gt;&lt;br /&gt;
        semaphore_P(mutex);&lt;br /&gt;
        if (nw &amp;gt; 0 || nr &amp;gt; 0) {&lt;br /&gt;
                ww++;&lt;br /&gt;
                semaphore_V(mutex);&lt;br /&gt;
                semaphore_P(ok2write);&lt;br /&gt;
                ww--;&lt;br /&gt;
        }&lt;br /&gt;
        nw++;&lt;br /&gt;
        w_last=1;&lt;br /&gt;
        printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, nr, nw, wr, ww);&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void endwrite(void) {&lt;br /&gt;
// &amp;lt;nw--&amp;gt;&lt;br /&gt;
        semaphore_P(mutex);&lt;br /&gt;
        nw--;&lt;br /&gt;
        printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, nr, nw, wr, ww);&lt;br /&gt;
        if (wr &amp;gt; 0 &amp;amp;&amp;amp; (ww == 0 || w_last))&lt;br /&gt;
                semaphore_V(ok2read);&lt;br /&gt;
        else if (ww &amp;gt; 0 &amp;amp;&amp;amp; (wr == 0 || !w_last))&lt;br /&gt;
                semaphore_V(ok2write);&lt;br /&gt;
        else&lt;br /&gt;
                semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void *reader(void *arg) {&lt;br /&gt;
        int i = (uintptr_t)arg;&lt;br /&gt;
        while (1) {&lt;br /&gt;
                //other code&lt;br /&gt;
                usleep(random() % 200000);&lt;br /&gt;
                startread();&lt;br /&gt;
                //read&lt;br /&gt;
                usleep(random() % 200000);&lt;br /&gt;
                endread();&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void *writer(void *arg) {&lt;br /&gt;
        int i = (uintptr_t)arg;&lt;br /&gt;
        while (1) {&lt;br /&gt;
                //other code&lt;br /&gt;
                usleep(random() % 200000);&lt;br /&gt;
                startwrite();&lt;br /&gt;
                //write&lt;br /&gt;
                usleep(random() % 200000);&lt;br /&gt;
                endwrite();&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//printf(&amp;quot;philo thinking: %d\n&amp;quot;,i);&lt;br /&gt;
/*while*/&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char *argv[]) {&lt;br /&gt;
        int i;&lt;br /&gt;
        pthread_t t;&lt;br /&gt;
        srandom(time(NULL));&lt;br /&gt;
        mutex=semaphore_create(1);&lt;br /&gt;
        ok2read=semaphore_create(0);&lt;br /&gt;
        ok2write=semaphore_create(0);&lt;br /&gt;
        for (i=0; i&amp;lt;NREADER; i++)&lt;br /&gt;
                pthread_create(&amp;amp;t, NULL, reader, (void *)(uintptr_t) i);&lt;br /&gt;
        for (i=0; i&amp;lt;NWRITER; i++)&lt;br /&gt;
                pthread_create(&amp;amp;t, NULL, writer, (void *)(uintptr_t) i);&lt;br /&gt;
        while(1)&lt;br /&gt;
                pause();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== RW di FedericoB ==&lt;br /&gt;
Propongo la seguente soluzione. Mi sembra che funzioni ma devo ancora capire perchè e documentarla bene. Ho provato prima a cercare il bug ma non ci sono riuscito. Ho quindi modificato il codice secondo ciò che mi sembrava sensato in base alle condizioni del problema. Ne possiamo parlare in aula oggi. --[[User:FedericoB|FedericoB]] ([[User talk:FedericoB|talk]]) 12:48, 11 November 2016 (CET)&lt;br /&gt;
Ho notato che l'errore non si manifesta più eliminando il controllo che ci siano scrittori in attesa quando un lettore vuole iniziare a scrivere. Non capisco come questo possa essere collegato al bug. --[[User:FedericoB|FedericoB]] ([[User talk:FedericoB|talk]]) 15:10, 11 November 2016 (CET)&lt;br /&gt;
&lt;br /&gt;
FedericoB, questa soluzione &amp;amp;egrave; quella con priorit&amp;amp;agrave; ai lettori, no? Se continuano ad arrivare lettori numberOfReaders non sar&amp;amp;agrave; mai zero e quindi gli scrittori non scriveranno mai. [[User:Renzo|Renzo]] ([[User talk:Renzo|talk]]) 10:34, 12 November 2016 (CET)&lt;br /&gt;
&lt;br /&gt;
SFIDA: ho trovato il modo di togliere la starvation aggiungendo 4 token (parole chiave, nomi di variabili, operatori, costanti) a questa soluzione di FedericoB. Chi trova la soluzione? [[User:Renzo|Renzo]] ([[User talk:Renzo|talk]]) 10:43, 12 November 2016 (CET) Ah! ho appena trovato una soluzione che prevede 2 soli token in pi&amp;amp;ugrave;! [[User:Renzo|Renzo]] ([[User talk:Renzo|talk]]) 10:47, 12 November 2016 (CET)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
#include&amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include&amp;lt;stdint.h&amp;gt;&lt;br /&gt;
#include&amp;lt;pthread.h&amp;gt;&lt;br /&gt;
#include&amp;lt;semaphore.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define NUMBER_OF_READERS 3&lt;br /&gt;
#define NUMBER_OF_WRITERS 3&lt;br /&gt;
semaphore mutex;&lt;br /&gt;
semaphore ok2read;&lt;br /&gt;
semaphore ok2write;&lt;br /&gt;
&lt;br /&gt;
int numberOfReaders=0;&lt;br /&gt;
int numberOfWriters=0;&lt;br /&gt;
int waitingReaders=0;&lt;br /&gt;
int waitingWriters=0;&lt;br /&gt;
&lt;br /&gt;
// (nw == 0 &amp;amp;&amp;amp; nr == 0) || (nr &amp;gt; 0 &amp;amp;&amp;amp; nw == 0) || nw == 1&lt;br /&gt;
// (nw == 0 &amp;amp;&amp;amp; nr &amp;gt;= 0) || nw == 1&lt;br /&gt;
&lt;br /&gt;
void startread(void) {&lt;br /&gt;
// &amp;lt;await nw == 0 -&amp;gt; nr++&amp;gt;&lt;br /&gt;
    semaphore_P(mutex);&lt;br /&gt;
    if (numberOfWriters &amp;gt; 0) {&lt;br /&gt;
        waitingReaders++;&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
        semaphore_P(ok2read);&lt;br /&gt;
        waitingReaders--;&lt;br /&gt;
    }&lt;br /&gt;
    numberOfReaders++;&lt;br /&gt;
    printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, numberOfReaders, numberOfWriters, waitingReaders, waitingWriters);&lt;br /&gt;
    if (waitingReaders &amp;gt; 0 )&lt;br /&gt;
        semaphore_V(ok2read);&lt;br /&gt;
    else&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void endread(void) {&lt;br /&gt;
// &amp;lt;nr--&amp;gt;&lt;br /&gt;
    semaphore_P(mutex);&lt;br /&gt;
    numberOfReaders--;&lt;br /&gt;
    printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, numberOfReaders, numberOfWriters, waitingReaders, waitingWriters);&lt;br /&gt;
    if (numberOfReaders == 0 &amp;amp;&amp;amp; waitingWriters &amp;gt; 0)&lt;br /&gt;
        semaphore_V(ok2write);&lt;br /&gt;
    else&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void startwrite(void) {&lt;br /&gt;
// &amp;lt;await nw == 0 &amp;amp;&amp;amp; nr == 0 -&amp;gt; nw++&amp;gt;&lt;br /&gt;
    semaphore_P(mutex);&lt;br /&gt;
    if (numberOfWriters &amp;gt; 0 || numberOfReaders &amp;gt; 0) {&lt;br /&gt;
        waitingWriters++;&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
        semaphore_P(ok2write);&lt;br /&gt;
        waitingWriters--;&lt;br /&gt;
    }&lt;br /&gt;
    numberOfWriters++;&lt;br /&gt;
    printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, numberOfReaders, numberOfWriters, waitingReaders, waitingWriters);&lt;br /&gt;
    semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void endwrite(void) {&lt;br /&gt;
// &amp;lt;nw--&amp;gt;&lt;br /&gt;
    semaphore_P(mutex);&lt;br /&gt;
    numberOfWriters--;&lt;br /&gt;
    printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, numberOfReaders, numberOfWriters, waitingReaders, waitingWriters);&lt;br /&gt;
    if (waitingReaders &amp;gt; 0)&lt;br /&gt;
        semaphore_V(ok2read);&lt;br /&gt;
    else if (waitingWriters &amp;gt; 0)&lt;br /&gt;
        semaphore_V(ok2write);&lt;br /&gt;
    else&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void *reader(void *arg) {&lt;br /&gt;
    int i = (uintptr_t)arg;&lt;br /&gt;
    while (1) {&lt;br /&gt;
        //other code&lt;br /&gt;
        usleep(random() % 200000);&lt;br /&gt;
        startread();&lt;br /&gt;
        //read&lt;br /&gt;
        usleep(random() % 200000);&lt;br /&gt;
        endread();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void *writer(void *arg) {&lt;br /&gt;
    int i = (uintptr_t)arg;&lt;br /&gt;
    while (1) {&lt;br /&gt;
        //other code&lt;br /&gt;
        usleep(random() % 200000);&lt;br /&gt;
        startwrite();&lt;br /&gt;
        //write&lt;br /&gt;
        usleep(random() % 200000);&lt;br /&gt;
        endwrite();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//printf(&amp;quot;philo thinking: %d\n&amp;quot;,i);&lt;br /&gt;
/*while*/&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char *argv[]) {&lt;br /&gt;
    int i;&lt;br /&gt;
    pthread_t t;&lt;br /&gt;
    srandom(time(NULL));&lt;br /&gt;
    mutex=semaphore_create(1);&lt;br /&gt;
    ok2read=semaphore_create(0);&lt;br /&gt;
    ok2write=semaphore_create(0);&lt;br /&gt;
    for (i=0; i&amp;lt;NUMBER_OF_READERS; i++)&lt;br /&gt;
        pthread_create(&amp;amp;t, NULL, reader, (void *)(uintptr_t) i);&lt;br /&gt;
    for (i=0; i&amp;lt;NUMBER_OF_WRITERS; i++)&lt;br /&gt;
        pthread_create(&amp;amp;t, NULL, writer, (void *)(uintptr_t) i);&lt;br /&gt;
    while(1)&lt;br /&gt;
        pause();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== RW2 ==&lt;br /&gt;
Buongiorno, guardando il codice visto a lezione mi sembra che cambiando la condizione del primo if nella startread() da &amp;quot;if (nw &amp;gt; 0 &amp;amp;&amp;amp; ww == 0)&amp;quot; a &amp;quot;if (nw &amp;gt; 0 || ww &amp;gt; 0)&amp;quot; la situazione migliori. In particolare con l'and tra quelle due condizioni si aveva che non veniva fatta la P sull'ok2read anche quando si aveva nw&amp;gt;0 (con ww!=0), cosa che invece dovrebbe fare. Lasciando il resto del codice uguale mi sembra che faccia quello che deve fare.. .&lt;br /&gt;
&lt;br /&gt;
Matteo.pincherle: Perch&amp;amp;eacute; non modifichi in programma di FedericoB, lo provi e pubblichi qui la patch? [[User:Renzo|Renzo]] ([[User talk:Renzo|talk]]) 10:42, 13 November 2016 (CET)&lt;br /&gt;
&lt;br /&gt;
'''Perchè quel AND permetteva di avere 2 scrittori?''' &amp;lt;br&amp;gt;&lt;br /&gt;
Permetteva in primis di avere dei lettori in contemporanea a uno scrittore. In quanto se succedeva che un lettore volesse entrare mentre non c'erano degli scrittori in attesa ma scrittori in scrittura, veniva saltato il blocco che mandava il lettore in attesa e risultava un lettore in contemporanea a uno scrittore. &amp;lt;br&amp;gt;&lt;br /&gt;
Questo lettore poi poteva finire di leggere prima che lo scrittore in contemporanea a lui finisse di scrivere. &amp;lt;br&amp;gt;&lt;br /&gt;
Il lettore in uscita se non c'erano altri lettori con lui e non c'erano scrittori in attesa dava il permesso per far accedere un altro scrittore. &amp;lt;br&amp;gt;&lt;br /&gt;
A questo punto un altro scrittore che avesse voluto entrare poteva entrare, con il risultato di avere 2 scrittori in contemporanea.&lt;br /&gt;
--[[User:FedericoB|FedericoB]] ([[User talk:FedericoB|talk]]) 19:25, 13 November 2016 (CET)&lt;br /&gt;
&lt;br /&gt;
== Patch ==&lt;br /&gt;
Così, se non sbaglio, quando c'è almeno uno scrittore in attesa non lascia entrare altri lettori. Fa esaurire la lettura dei presenti e poi lascia scrivere lo scrittore.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include&amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include&amp;lt;stdint.h&amp;gt;&lt;br /&gt;
#include&amp;lt;pthread.h&amp;gt;&lt;br /&gt;
#include&amp;lt;semaphore.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define NUMBER_OF_READERS 3&lt;br /&gt;
#define NUMBER_OF_WRITERS 3&lt;br /&gt;
semaphore mutex;&lt;br /&gt;
semaphore ok2read;&lt;br /&gt;
semaphore ok2write;&lt;br /&gt;
&lt;br /&gt;
int numberOfReaders=0;&lt;br /&gt;
int numberOfWriters=0;&lt;br /&gt;
int waitingReaders=0;&lt;br /&gt;
int waitingWriters=0;&lt;br /&gt;
int w_last;&lt;br /&gt;
&lt;br /&gt;
// (nw == 0 &amp;amp;&amp;amp; nr == 0) || (nr &amp;gt; 0 &amp;amp;&amp;amp; nw == 0) || nw == 1&lt;br /&gt;
// (nw == 0 &amp;amp;&amp;amp; nr &amp;gt;= 0) || nw == 1&lt;br /&gt;
&lt;br /&gt;
void startread(void) {&lt;br /&gt;
    // &amp;lt;await nw == 0 -&amp;gt; nr++&amp;gt;&lt;br /&gt;
    semaphore_P(mutex);&lt;br /&gt;
    if (numberOfWriters &amp;gt; 0 || waitingWriters&amp;gt;0) {&lt;br /&gt;
        waitingReaders++;&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
        semaphore_P(ok2read);&lt;br /&gt;
        waitingReaders--;&lt;br /&gt;
    }&lt;br /&gt;
    numberOfReaders++;&lt;br /&gt;
    w_last=0;&lt;br /&gt;
    printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, numberOfReaders, numberOfWriters, waitingReaders, waitingWriters);&lt;br /&gt;
    if (waitingReaders &amp;gt; 0 )&lt;br /&gt;
        semaphore_V(ok2read);&lt;br /&gt;
    else&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void endread(void) {&lt;br /&gt;
    // &amp;lt;nr--&amp;gt;&lt;br /&gt;
    semaphore_P(mutex);&lt;br /&gt;
    numberOfReaders--;&lt;br /&gt;
    printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, numberOfReaders, numberOfWriters, waitingReaders, waitingWriters);&lt;br /&gt;
    if (numberOfReaders == 0 &amp;amp;&amp;amp; waitingWriters &amp;gt; 0)&lt;br /&gt;
        semaphore_V(ok2write);&lt;br /&gt;
    else&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void startwrite(void) {&lt;br /&gt;
    // &amp;lt;await nw == 0 &amp;amp;&amp;amp; nr == 0 -&amp;gt; nw++&amp;gt;&lt;br /&gt;
    semaphore_P(mutex);&lt;br /&gt;
    if (numberOfWriters &amp;gt; 0 || numberOfReaders &amp;gt; 0) {&lt;br /&gt;
        waitingWriters++;&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
        semaphore_P(ok2write);&lt;br /&gt;
        waitingWriters--;&lt;br /&gt;
    }&lt;br /&gt;
    numberOfWriters++;&lt;br /&gt;
    w_last=1;&lt;br /&gt;
    printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, numberOfReaders, numberOfWriters, waitingReaders, waitingWriters);&lt;br /&gt;
    semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void endwrite(void) {&lt;br /&gt;
    // &amp;lt;nw--&amp;gt;&lt;br /&gt;
    semaphore_P(mutex);&lt;br /&gt;
    numberOfWriters--;&lt;br /&gt;
    printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, numberOfReaders, numberOfWriters, waitingReaders, waitingWriters);&lt;br /&gt;
    if (waitingReaders &amp;gt; 0 &amp;amp;&amp;amp; (waitingWriters==0 || w_last))&lt;br /&gt;
        semaphore_V(ok2read);&lt;br /&gt;
    else if (waitingWriters &amp;gt; 0 &amp;amp;&amp;amp; (waitingReaders==0 || !w_last))&lt;br /&gt;
        semaphore_V(ok2write);&lt;br /&gt;
    else&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void *reader(void *arg) {&lt;br /&gt;
    int i = (uintptr_t)arg;&lt;br /&gt;
    while (1) {&lt;br /&gt;
        //other code&lt;br /&gt;
        usleep(random() % 200000);&lt;br /&gt;
        startread();&lt;br /&gt;
        //read&lt;br /&gt;
        usleep(random() % 200000);&lt;br /&gt;
        endread();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void *writer(void *arg) {&lt;br /&gt;
    int i = (uintptr_t)arg;&lt;br /&gt;
    while (1) {&lt;br /&gt;
        //other code&lt;br /&gt;
        usleep(random() % 200000);&lt;br /&gt;
        startwrite();&lt;br /&gt;
        //write&lt;br /&gt;
        usleep(random() % 200000);&lt;br /&gt;
        endwrite();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char *argv[]) {&lt;br /&gt;
    int i;&lt;br /&gt;
    pthread_t t;&lt;br /&gt;
    srandom(time(NULL));&lt;br /&gt;
    mutex=semaphore_create(1);&lt;br /&gt;
    ok2read=semaphore_create(0);&lt;br /&gt;
    ok2write=semaphore_create(0);&lt;br /&gt;
    for (i=0; i&amp;lt;NUMBER_OF_READERS; i++)&lt;br /&gt;
        pthread_create(&amp;amp;t, NULL, reader, (void *)(uintptr_t) i);&lt;br /&gt;
    for (i=0; i&amp;lt;NUMBER_OF_WRITERS; i++)&lt;br /&gt;
        pthread_create(&amp;amp;t, NULL, writer, (void *)(uintptr_t) i);&lt;br /&gt;
    while(1)&lt;br /&gt;
        pause();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
wlast non serve pi&amp;amp;ugrave;... [[User:Renzo|Renzo]] ([[User talk:Renzo|talk]]) 17:52, 13 November 2016 (CET)&lt;br /&gt;
&lt;br /&gt;
== RW2bis ==&lt;br /&gt;
Nella tua soluzione se i lettori sono &amp;quot;molto veloci&amp;quot; e non vanno mai a 0, lo scrittore non inizierà mai a scrivere.&lt;br /&gt;
&lt;br /&gt;
Cioè: Uno scrittore viene svegliato da ok2write solo se passa la condizione &lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
[..] &lt;br /&gt;
if (numberofReaders == 0 &amp;amp;&amp;amp; waitingWriters &amp;gt;0) &lt;br /&gt;
     semaphore_V(ok2write);&lt;br /&gt;
[..]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; --[[User:GabrieleCalarota|GabrieleCalarota]] ([[User talk:GabrieleCalarota|talk]]) 17:46, 13 November 2016 (CET)&lt;br /&gt;
&lt;br /&gt;
Non direi perche' nella startread se:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
    if (numberOfWriters &amp;gt; 0 || waitingWriters&amp;gt;0) &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
i lettori si bloccano. Quindi se c'e' almeno uno scrittore in attesa i lettori non entrano (e quindi prima o poi terminano e lasciano il posto ad uno scrittore).&lt;br /&gt;
[[User:Renzo|Renzo]] ([[User talk:Renzo|talk]]) 17:57, 13 November 2016 (CET)&lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
Ho pensato al caso limite seguente:&lt;br /&gt;
Supponiamo che ci siano dei lettori che stanno leggendo e ad un certo punto uno scrittore chiede di scrivere.&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;syntaxhighlight lang=C&amp;gt;         &lt;br /&gt;
       void startread(void) {&lt;br /&gt;
    // &amp;lt;await nw == 0 -&amp;gt; nr++&amp;gt;&lt;br /&gt;
    semaphore_P(mutex);&lt;br /&gt;
    if (numberOfWriters &amp;gt; 0 || waitingWriters&amp;gt;0) {&lt;br /&gt;
        waitingReaders++;   //Nuovo scrittore (t1)&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
        semaphore_P(ok2read);&lt;br /&gt;
        waitingReaders--;&lt;br /&gt;
    }&lt;br /&gt;
    numberOfReaders++;&lt;br /&gt;
    w_last=0;&lt;br /&gt;
    printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, numberOfReaders, numberOfWriters, waitingReaders, waitingWriters);&lt;br /&gt;
   if (waitingReaders &amp;gt; 0 )   //Vecchio scrittore(t1)&lt;br /&gt;
        semaphore_V(ok2read);&lt;br /&gt;
    else&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Non appena lo scrittore rilascia il mutex, un nuovo lettore chiede di leggere (e si addormenterà). Un lettore (lento) che era riuscito a entrare nel segmento startofread prima che lo scrittore entrasse in startofwrite, continua a leggere e risveglia uno dei nuovi lettori. Se i lettori continuano a richiedere di leggere continuamente, verranno addormentati e subito risvegliati. &lt;br /&gt;
&lt;br /&gt;
E' da considerarsi possibile? --[[User:GabrieleCalarota|GabrieleCalarota]] ([[User talk:GabrieleCalarota|talk]]) 19:11, 13 November 2016 (CET)&lt;br /&gt;
&lt;br /&gt;
Suppongo che &amp;quot;un nuovo scrittore chiede di leggere&amp;quot; si aun refuso e sia da intendere &amp;quot;un nuovo lettore chiede di leggere&amp;quot; (altrimenti ci sono crisi di identit&amp;amp;agrave;) e che &amp;quot;startofread&amp;quot; significhi &amp;quot;startread&amp;quot; e &amp;quot;startofwrite&amp;quot;  sia &amp;quot;startwrite&amp;quot;.&lt;br /&gt;
La &amp;quot;startread&amp;quot; viene eseguita in mutua esclusione, quindi non ci puo' essere &amp;quot;un lettore lento che sia riuscito ad entrare&amp;quot; nella funione startread. Se ha superato la P(mutex) iniziale o e' bloccato sulla ok2read o e' entrato. [[User:Renzo|Renzo]] ([[User talk:Renzo|talk]]) 19:37, 13 November 2016 (CET)&lt;/div&gt;</summary>
		<author><name>GabrieleCalarota</name></author>
	</entry>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=Esperimenti_con_semafori_e_monitor_in_C&amp;diff=1617</id>
		<title>Esperimenti con semafori e monitor in C</title>
		<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php?title=Esperimenti_con_semafori_e_monitor_in_C&amp;diff=1617"/>
		<updated>2016-11-18T19:30:32Z</updated>

		<summary type="html">&lt;p&gt;GabrieleCalarota: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Ho messo a vostra disposizione alcuni sorgenti che implementano in C le astrazioni di semaforo e monitor come le abbiamo viste (o vedremo presto) a lezione.&lt;br /&gt;
&lt;br /&gt;
Ho messo il materiale in [http://www.cs.unibo.it/~renzo/so/tools/sm.tgz questo file].&lt;br /&gt;
&lt;br /&gt;
La directory comprende:&lt;br /&gt;
* un Makefile&lt;br /&gt;
* tlist.[ch] un modulo di implementazione di liste circolari di thread_id (usate per gestire i processi bloccati). Le liste possono essere usate come code o stack.&lt;br /&gt;
* suspend.[ch] &amp;amp;egrave; il modulo che implementa la sospensione e riattivazione dei pthread (usando il segnale SIGUSR1).&lt;br /&gt;
* semaphore.[ch] implementazione dei semafori '''fair'''&lt;br /&gt;
* monitor.[ch] implementazione dei monitor (con semantica '''signal urgent''' per le variabili di condizione).&lt;br /&gt;
* prod_cons.c esempio: produttore consumatore con i semafori&lt;br /&gt;
* bounded_buf.c esempio: bounded_buffer con i semafori&lt;br /&gt;
* bounded_buf_mon.c esempio: bounded buffer con i monitor&lt;br /&gt;
* philo.c: cena dei filosofi (la soluzione &amp;amp;egrave; volutamente errata e pu&amp;amp;ograve; generare deadlock)&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
--[[User:FedericoB|FedericoB]] ([[User talk:FedericoB|talk]]) 20:51, 14 November 2016 (CET) &amp;lt;br&amp;gt;&lt;br /&gt;
Ho aggiunto in [http://federico.bertani.web.cs.unibo.it/sm.tar.gz questo file].&lt;br /&gt;
* binsemaphore.[ch] semafori binari implementati senza semafori normali&lt;br /&gt;
* dirtybinsemaphore.c semafori binari implementati con semafori normali&lt;br /&gt;
* prod_consBin.c problema del produttore-consumatore risolto con solo un semaforo(binario). (warning contiene useless wait)&lt;br /&gt;
* dirtysemaphore.c semafori ordinari implementati con semafori binari&lt;br /&gt;
* readerWriters.c soluzione del problema lettori-scrittori che abbiamo discusso [[Zibaldone | qui]]&lt;br /&gt;
Nel makefile ho aggiunto: &lt;br /&gt;
* il target prod_consBin e dirtyprod_consBin in cui cambia solo il tipo di semaforo binario linkato.&lt;br /&gt;
* il target readerWriters e dirtyreaders_writers in cui cambia solo il tipo di semaforo ordinario linkato.&lt;br /&gt;
----&lt;br /&gt;
[[User:Renzo|Renzo]] ([[User talk:Renzo|talk]]) 09:01, 15 November 2016 (CET)&amp;lt;br&amp;gt;&lt;br /&gt;
attenzione: l'implementazione di FedericoB e' un ottimo punto di partenza per la discussione ma non e' corretta,&lt;br /&gt;
Infatti non rispetta l'invariante dei semafori binari 0 &amp;lt;= nV + Init - nP &amp;lt;= 1.&lt;br /&gt;
Poniamo infatti Init = 0, e sottoponiamo l'implementazione di Federico alla sequenza V V P V.&lt;br /&gt;
La prima V porta il semaforo al valore 1, la seconda blocca il chiamante, la P successiva trova il semaforo a 1 quindi non e' bloccante e quindi (codice alla mano) decrementa il semaforo (s-&amp;gt;value--) e risveglia il processo bloccato per la seconda V. Il semaforo ora vale zero. L'ultima V non e' quindi bloccante.&lt;br /&gt;
quindi Init=0, nV=3, nP=1. (Nv + Init - Np) vale quindi 0 + 3 - 1 cioe' '''2'''. Ahi! Dov'e' l'errore?&lt;br /&gt;
----&lt;br /&gt;
--[[User:FedericoB|FedericoB]] ([[User talk:FedericoB|talk]]) 10:54, 15 November 2016 (CET) &amp;lt;br&amp;gt;&lt;br /&gt;
Ho sistemato creando prima i semafori binari implementati con i semafori normali. &amp;lt;br&amp;gt;&lt;br /&gt;
Dopo sono riuscito a sistemare anche i semafori binari senza semafori normali. L'unico difetto è che usano 2 value invece che 1.&lt;br /&gt;
----&lt;br /&gt;
[[User:Renzo|Renzo]] ([[User talk:Renzo|talk]]) 12:03, 15 November 2016 (CET)&amp;lt;br&amp;gt;&lt;br /&gt;
Ancora ottimi spunti di discussione, ma non ancora perfetti.... Prendiamo l'implementazione dei semafori binari con i semafori ordinari e il caso Init 1, V V P P.&lt;br /&gt;
Per effetto dell'Init sem0 vale 1 e sem 1 vale 0.&lt;br /&gt;
Il primo V porta sem0 a 2 e il chiamante si ferma su sem1. Il secondo V porta sem0 a 3 e ferma anch'esso il chiamante su sem1. La prima P supera la P su sem0 (che viene portato a 2) fa la V su sem1 (che ora vale 1) ed esce. La seconda P porta sem0 a 1, sem1 a 2 ed esce. Abbiamo lasciato I due processi fermi sulla P(sem1).&lt;br /&gt;
Prima o poi si sbloccheranno.... ma in questo momento nP (il numero di processi che hanno superato la P) vale 2, nV (il numero di processi che hanno superato la V) e' zero, Init era 1. quindi nV + Init - nP = 0 + 1 - 2 = -1. Ahime'! Come si risolve?&lt;br /&gt;
----&lt;br /&gt;
--[[User:FedericoB|FedericoB]] ([[User talk:FedericoB|talk]]) 10:52, 18 November 2016 (CET) &amp;lt;br&amp;gt;&lt;br /&gt;
Ho sistemato i semafori binari e ho aggiunto i semafori ordinari implementati con i binari. &amp;lt;br&amp;gt;&lt;br /&gt;
Ho tenuto il problema del produttore consumatore con il solo semaforo binario. Funziona ma abbiamo visto che può far aspettare inutilmente il consumatore.&lt;br /&gt;
----&lt;br /&gt;
[[User:S.G|S.G]] ([[User talk:S.G|talk]]) 10:36, 18 November 2016 (CET)&amp;lt;br&amp;gt;&lt;br /&gt;
Ho dei dubbi riguardo la seguente parte &amp;quot;La prima P supera la P su sem0 (che viene portato a 2) fa la V su sem1 (che ora vale 1) ed esce&amp;quot;. La prima P viene superata, mentre la V su sem1 (verifica che la coda sia vuota, se lo è incrementa di uno il semaforo, altrimenti risveglia un processo) ha in coda alcuni processi, e quindi non dovrebbe incrementare sem1.&lt;br /&gt;
----&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
#include&amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include&amp;lt;pthread.h&amp;gt;&lt;br /&gt;
#include &amp;quot;binsemaphore.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
binsemaphore binSemaphore;&lt;br /&gt;
volatile int buffer;&lt;br /&gt;
&lt;br /&gt;
void *producer(void *arg) {&lt;br /&gt;
    short int firstTime = 1;&lt;br /&gt;
	while (1) {&lt;br /&gt;
		int value;&lt;br /&gt;
		usleep(random() % 200000);&lt;br /&gt;
		value = random() % 32768;&lt;br /&gt;
		printf(&amp;quot;produced: %d\n&amp;quot;,value);&lt;br /&gt;
		if (!firstTime) binsemaphore_V(binSemaphore);&lt;br /&gt;
        buffer = value;&lt;br /&gt;
		printf(&amp;quot;sent: %d\n&amp;quot;,value);&lt;br /&gt;
        binsemaphore_V(binSemaphore);&lt;br /&gt;
        firstTime=0;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void *consumer(void *arg) {&lt;br /&gt;
	while (1) {&lt;br /&gt;
		int value;&lt;br /&gt;
		printf(&amp;quot;\t\tconsumer ready\n&amp;quot;);&lt;br /&gt;
        binsemaphore_P(binSemaphore);&lt;br /&gt;
		value = buffer;&lt;br /&gt;
		printf(&amp;quot;\t\tconsume %d\n&amp;quot;, value);&lt;br /&gt;
        binsemaphore_P(binSemaphore);&lt;br /&gt;
		usleep(random() % 200000);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char *argv[]) {&lt;br /&gt;
	pthread_t prod_t;&lt;br /&gt;
	pthread_t cons_t;&lt;br /&gt;
    binSemaphore=binsemaphore_create(0);&lt;br /&gt;
	srandom(time(NULL));&lt;br /&gt;
	pthread_create(&amp;amp;prod_t, NULL, producer, NULL);&lt;br /&gt;
	pthread_create(&amp;amp;cons_t, NULL, consumer, NULL);&lt;br /&gt;
	pthread_join(prod_t, NULL);&lt;br /&gt;
	pthread_join(cons_t, NULL);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In questa soluzione del prod_cons con un solo semaforo binario è presente race condition su buffer in quanto non c'è alcuna sicurezza di mutua esclusione nel producer e quindi sia producer che consumer possono accedere al buffer contemporaneamente... Si riesce a patchare oppure non è possibile risolverlo con un solo semaforo 0/1?&lt;br /&gt;
&lt;br /&gt;
== uso dei semafori ==&lt;br /&gt;
&lt;br /&gt;
Se volete fare altri esperimenti con i semafori dovete includere il file semaphore.h nei vostri sorgenti C.&lt;br /&gt;
&lt;br /&gt;
Un semaforo ha tipo ''semaphore'' e viene creato in questo modo&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
semaphore mutex;&lt;br /&gt;
mutex = mutex_create(1);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
(ovviamente le variabili semaphore devono essere condivise e 1 &amp;amp;egrave; solo l'esempio di valore iniziale per un semaforo mutex)&lt;br /&gt;
&lt;br /&gt;
Le operazioni P e V su mutex si scrivono cos&amp;amp;igrave;:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
semaphore_P(mutex);&lt;br /&gt;
semaphore_V(mutex);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== produttore e consumatore ==&lt;br /&gt;
&lt;br /&gt;
Il file ''prod_cons.c'' implementa una soluzione del problema del produttore/consumatore.&lt;br /&gt;
&lt;br /&gt;
Il buffer e i semafori sono definiti come variabili condivise.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
semaphore full;&lt;br /&gt;
semaphore empty;&lt;br /&gt;
volatile int buffer;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Il main inizializza i semafori e crea i thread.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
int main(int argc, char *argv[]) {&lt;br /&gt;
  pthread_t prod_t;&lt;br /&gt;
  pthread_t cons_t;&lt;br /&gt;
  full=semaphore_create(0);&lt;br /&gt;
  empty=semaphore_create(1);&lt;br /&gt;
&lt;br /&gt;
  pthread_create(&amp;amp;prod_t, NULL, producer, NULL);&lt;br /&gt;
  pthread_create(&amp;amp;cons_t, NULL, consumer, NULL);&lt;br /&gt;
  pthread_join(prod_t, NULL);&lt;br /&gt;
  pthread_join(cons_t, NULL);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
La sincronizzazione fra produttore e il consumatore viene realizzata come segue:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
void *producer(void *arg) {&lt;br /&gt;
  while (1) {&lt;br /&gt;
    int value;&lt;br /&gt;
    // produce value&lt;br /&gt;
    semaphore_P(empty);&lt;br /&gt;
    buffer = value;&lt;br /&gt;
    semaphore_V(full);&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void *consumer(void *arg) {&lt;br /&gt;
  while (1) {&lt;br /&gt;
    int value;&lt;br /&gt;
    semaphore_P(full);&lt;br /&gt;
    value = buffer;&lt;br /&gt;
    semaphore_V(empty);&lt;br /&gt;
    // consume value&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Uso dei monitor ==&lt;br /&gt;
&lt;br /&gt;
Un monitor viene creato con la funzione:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
monitor mymon;&lt;br /&gt;
mymon = monitor_create()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Le variabili di condizione vengono create nel seguente modo:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
condition oktoproceed;&lt;br /&gt;
oktoproceed = condition_create(mymon);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
(NB: le variabili di condizione sono '''sempre''' riferite ad uno specifico monitor).&lt;br /&gt;
&lt;br /&gt;
Le procedure entry sono normali funzioni C ma occorre mettere all'entrata e all'uscita le chiamate&lt;br /&gt;
''monitor_{enter,exit}':&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
int mymon_dosomething(/* params */) {&lt;br /&gt;
  rval int;&lt;br /&gt;
  monitor_enter(mymon);&lt;br /&gt;
  ....&lt;br /&gt;
  monitor_exit(mymon);&lt;br /&gt;
  return rval;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Le operazioni wait e signal sulle variabili di condizione si scrivono cos&amp;amp;igrave;:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
condition_wait(oktoproceed);&lt;br /&gt;
condition_signal(oktoproceed);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Bounded buffer con i monitor ==&lt;br /&gt;
Vengono definite come variabili condivise il monitor e le variabili di condizione&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
monitor bb;&lt;br /&gt;
condition ok2write;&lt;br /&gt;
condition ok2read;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
oltre al buffer e alle variabili per la gestione delle strutture dati, fra le quali il contatore ''buflen''.&lt;br /&gt;
&lt;br /&gt;
Il monitor viene creato da questa funzione:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
void bb_create(void) {&lt;br /&gt;
  bb = monitor_create();&lt;br /&gt;
  ok2write = condition_create(bb);&lt;br /&gt;
  ok2read = condition_create(bb);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
che viene richiamata dal main prima di far partire i thread:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
int main(int argc, char *argv[]) {&lt;br /&gt;
  pthread_t prod_t;&lt;br /&gt;
  pthread_t cons_t;&lt;br /&gt;
  bb_create();&lt;br /&gt;
&lt;br /&gt;
  pthread_create(&amp;amp;prod_t, NULL, producer, NULL);&lt;br /&gt;
  pthread_create(&amp;amp;cons_t, NULL, consumer, NULL);&lt;br /&gt;
  pthread_join(prod_t, NULL);&lt;br /&gt;
  pthread_join(cons_t, NULL);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Il monitor implementa due procedure entry put e get:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
void bb_put(int value) {&lt;br /&gt;
  monitor_enter(bb);&lt;br /&gt;
  if (buflen &amp;gt;= SIZE)&lt;br /&gt;
    condition_wait(ok2write);&lt;br /&gt;
  // enqueue value in the buffer&lt;br /&gt;
  buflen++;&lt;br /&gt;
  condition_signal(ok2read);&lt;br /&gt;
  monitor_exit(bb);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int bb_get(void) {&lt;br /&gt;
  int rval;&lt;br /&gt;
  monitor_enter(bb);&lt;br /&gt;
  if (buflen &amp;lt;= 0)&lt;br /&gt;
    condition_wait(ok2read);&lt;br /&gt;
  // dequeue rval from the buffer&lt;br /&gt;
  buflen--;&lt;br /&gt;
  condition_signal(ok2write);&lt;br /&gt;
  monitor_exit(bb);&lt;br /&gt;
  return rval;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Il codice dei processi produttore e del consumatore usa le procedure entry del monitor bb in questo modo:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
void *producer(void *arg) {&lt;br /&gt;
  while (1) {&lt;br /&gt;
    int value;&lt;br /&gt;
    // produce value&lt;br /&gt;
    bb_put(value);&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void *consumer(void *arg) {&lt;br /&gt;
  while (1) {&lt;br /&gt;
    int value;&lt;br /&gt;
    value = bb_get();&lt;br /&gt;
    // consume value&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>GabrieleCalarota</name></author>
	</entry>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=Zibaldone&amp;diff=1600</id>
		<title>Zibaldone</title>
		<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php?title=Zibaldone&amp;diff=1600"/>
		<updated>2016-11-13T18:42:05Z</updated>

		<summary type="html">&lt;p&gt;GabrieleCalarota: /* RW2bis */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== RW errato ==&lt;br /&gt;
Codice '''ERRATO''' dei lettori scrittori che dovrebbe non soffrire di problemi di starvation...&lt;br /&gt;
Esercizio: trovare gli errori.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
#include&amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include&amp;lt;stdint.h&amp;gt;&lt;br /&gt;
#include&amp;lt;pthread.h&amp;gt;&lt;br /&gt;
#include&amp;lt;semaphore.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define NREADER 3&lt;br /&gt;
#define NWRITER 3&lt;br /&gt;
semaphore mutex;&lt;br /&gt;
semaphore ok2read;&lt;br /&gt;
semaphore ok2write;&lt;br /&gt;
&lt;br /&gt;
int nr=0;&lt;br /&gt;
int nw=0;&lt;br /&gt;
int wr=0;&lt;br /&gt;
int ww=0;&lt;br /&gt;
int w_last;&lt;br /&gt;
&lt;br /&gt;
// (nw == 0 &amp;amp;&amp;amp; nr == 0) || (nr &amp;gt; 0 &amp;amp;&amp;amp; nw == 0) || nw == 1&lt;br /&gt;
// (nw == 0 &amp;amp;&amp;amp; nr &amp;gt;= 0) || nw == 1&lt;br /&gt;
&lt;br /&gt;
// this &amp;quot;baton&amp;quot; function has been left for reference only.&lt;br /&gt;
// code to implement &amp;quot;passing the baton&amp;quot; has been copied at the end of&lt;br /&gt;
// each ({start}|{end})({read}|{write}) function and reduced.&lt;br /&gt;
void baton(void) {&lt;br /&gt;
        if (nw == 0 &amp;amp;&amp;amp; nr == 0 &amp;amp;&amp;amp; ww &amp;gt; 0)&lt;br /&gt;
                semaphore_V(ok2write);&lt;br /&gt;
        else if (nw == 0 &amp;amp;&amp;amp; wr &amp;gt; 0 )&lt;br /&gt;
                semaphore_V(ok2read);&lt;br /&gt;
        else&lt;br /&gt;
                semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void startread(void) {&lt;br /&gt;
// &amp;lt;await nw == 0 -&amp;gt; nr++&amp;gt;&lt;br /&gt;
        semaphore_P(mutex);&lt;br /&gt;
        if (nw &amp;gt; 0 &amp;amp;&amp;amp; ww == 0) {&lt;br /&gt;
                wr++;&lt;br /&gt;
                semaphore_V(mutex);&lt;br /&gt;
                semaphore_P(ok2read);&lt;br /&gt;
                wr--;&lt;br /&gt;
        }&lt;br /&gt;
        nr++;&lt;br /&gt;
        w_last=0;&lt;br /&gt;
        printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, nr, nw, wr, ww);&lt;br /&gt;
        if (wr &amp;gt; 0 )&lt;br /&gt;
                semaphore_V(ok2read);&lt;br /&gt;
        else&lt;br /&gt;
                semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void endread(void) {&lt;br /&gt;
// &amp;lt;nr--&amp;gt;&lt;br /&gt;
        semaphore_P(mutex);&lt;br /&gt;
        nr--;&lt;br /&gt;
        printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, nr, nw, wr, ww);&lt;br /&gt;
        if (nr == 0 &amp;amp;&amp;amp; ww &amp;gt; 0)&lt;br /&gt;
                semaphore_V(ok2write);&lt;br /&gt;
        else&lt;br /&gt;
                semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void startwrite(void) {&lt;br /&gt;
// &amp;lt;await nw == 0 &amp;amp;&amp;amp; nr == 0 -&amp;gt; nw++&amp;gt;&lt;br /&gt;
        semaphore_P(mutex);&lt;br /&gt;
        if (nw &amp;gt; 0 || nr &amp;gt; 0) {&lt;br /&gt;
                ww++;&lt;br /&gt;
                semaphore_V(mutex);&lt;br /&gt;
                semaphore_P(ok2write);&lt;br /&gt;
                ww--;&lt;br /&gt;
        }&lt;br /&gt;
        nw++;&lt;br /&gt;
        w_last=1;&lt;br /&gt;
        printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, nr, nw, wr, ww);&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void endwrite(void) {&lt;br /&gt;
// &amp;lt;nw--&amp;gt;&lt;br /&gt;
        semaphore_P(mutex);&lt;br /&gt;
        nw--;&lt;br /&gt;
        printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, nr, nw, wr, ww);&lt;br /&gt;
        if (wr &amp;gt; 0 &amp;amp;&amp;amp; (ww == 0 || w_last))&lt;br /&gt;
                semaphore_V(ok2read);&lt;br /&gt;
        else if (ww &amp;gt; 0 &amp;amp;&amp;amp; (wr == 0 || !w_last))&lt;br /&gt;
                semaphore_V(ok2write);&lt;br /&gt;
        else&lt;br /&gt;
                semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void *reader(void *arg) {&lt;br /&gt;
        int i = (uintptr_t)arg;&lt;br /&gt;
        while (1) {&lt;br /&gt;
                //other code&lt;br /&gt;
                usleep(random() % 200000);&lt;br /&gt;
                startread();&lt;br /&gt;
                //read&lt;br /&gt;
                usleep(random() % 200000);&lt;br /&gt;
                endread();&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void *writer(void *arg) {&lt;br /&gt;
        int i = (uintptr_t)arg;&lt;br /&gt;
        while (1) {&lt;br /&gt;
                //other code&lt;br /&gt;
                usleep(random() % 200000);&lt;br /&gt;
                startwrite();&lt;br /&gt;
                //write&lt;br /&gt;
                usleep(random() % 200000);&lt;br /&gt;
                endwrite();&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//printf(&amp;quot;philo thinking: %d\n&amp;quot;,i);&lt;br /&gt;
/*while*/&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char *argv[]) {&lt;br /&gt;
        int i;&lt;br /&gt;
        pthread_t t;&lt;br /&gt;
        srandom(time(NULL));&lt;br /&gt;
        mutex=semaphore_create(1);&lt;br /&gt;
        ok2read=semaphore_create(0);&lt;br /&gt;
        ok2write=semaphore_create(0);&lt;br /&gt;
        for (i=0; i&amp;lt;NREADER; i++)&lt;br /&gt;
                pthread_create(&amp;amp;t, NULL, reader, (void *)(uintptr_t) i);&lt;br /&gt;
        for (i=0; i&amp;lt;NWRITER; i++)&lt;br /&gt;
                pthread_create(&amp;amp;t, NULL, writer, (void *)(uintptr_t) i);&lt;br /&gt;
        while(1)&lt;br /&gt;
                pause();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== RW di FedericoB ==&lt;br /&gt;
Propongo la seguente soluzione. Mi sembra che funzioni ma devo ancora capire perchè e documentarla bene. Ho provato prima a cercare il bug ma non ci sono riuscito. Ho quindi modificato il codice secondo ciò che mi sembrava sensato in base alle condizioni del problema. Ne possiamo parlare in aula oggi. --[[User:FedericoB|FedericoB]] ([[User talk:FedericoB|talk]]) 12:48, 11 November 2016 (CET)&lt;br /&gt;
Ho notato che l'errore non si manifesta più eliminando il controllo che ci siano scrittori in attesa quando un lettore vuole iniziare a scrivere. Non capisco come questo possa essere collegato al bug. --[[User:FedericoB|FedericoB]] ([[User talk:FedericoB|talk]]) 15:10, 11 November 2016 (CET)&lt;br /&gt;
&lt;br /&gt;
FedericoB, questa soluzione &amp;amp;egrave; quella con priorit&amp;amp;agrave; ai lettori, no? Se continuano ad arrivare lettori numberOfReaders non sar&amp;amp;agrave; mai zero e quindi gli scrittori non scriveranno mai. [[User:Renzo|Renzo]] ([[User talk:Renzo|talk]]) 10:34, 12 November 2016 (CET)&lt;br /&gt;
&lt;br /&gt;
SFIDA: ho trovato il modo di togliere la starvation aggiungendo 4 token (parole chiave, nomi di variabili, operatori, costanti) a questa soluzione di FedericoB. Chi trova la soluzione? [[User:Renzo|Renzo]] ([[User talk:Renzo|talk]]) 10:43, 12 November 2016 (CET) Ah! ho appena trovato una soluzione che prevede 2 soli token in pi&amp;amp;ugrave;! [[User:Renzo|Renzo]] ([[User talk:Renzo|talk]]) 10:47, 12 November 2016 (CET)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
#include&amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include&amp;lt;stdint.h&amp;gt;&lt;br /&gt;
#include&amp;lt;pthread.h&amp;gt;&lt;br /&gt;
#include&amp;lt;semaphore.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define NUMBER_OF_READERS 3&lt;br /&gt;
#define NUMBER_OF_WRITERS 3&lt;br /&gt;
semaphore mutex;&lt;br /&gt;
semaphore ok2read;&lt;br /&gt;
semaphore ok2write;&lt;br /&gt;
&lt;br /&gt;
int numberOfReaders=0;&lt;br /&gt;
int numberOfWriters=0;&lt;br /&gt;
int waitingReaders=0;&lt;br /&gt;
int waitingWriters=0;&lt;br /&gt;
&lt;br /&gt;
// (nw == 0 &amp;amp;&amp;amp; nr == 0) || (nr &amp;gt; 0 &amp;amp;&amp;amp; nw == 0) || nw == 1&lt;br /&gt;
// (nw == 0 &amp;amp;&amp;amp; nr &amp;gt;= 0) || nw == 1&lt;br /&gt;
&lt;br /&gt;
void startread(void) {&lt;br /&gt;
// &amp;lt;await nw == 0 -&amp;gt; nr++&amp;gt;&lt;br /&gt;
    semaphore_P(mutex);&lt;br /&gt;
    if (numberOfWriters &amp;gt; 0) {&lt;br /&gt;
        waitingReaders++;&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
        semaphore_P(ok2read);&lt;br /&gt;
        waitingReaders--;&lt;br /&gt;
    }&lt;br /&gt;
    numberOfReaders++;&lt;br /&gt;
    printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, numberOfReaders, numberOfWriters, waitingReaders, waitingWriters);&lt;br /&gt;
    if (waitingReaders &amp;gt; 0 )&lt;br /&gt;
        semaphore_V(ok2read);&lt;br /&gt;
    else&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void endread(void) {&lt;br /&gt;
// &amp;lt;nr--&amp;gt;&lt;br /&gt;
    semaphore_P(mutex);&lt;br /&gt;
    numberOfReaders--;&lt;br /&gt;
    printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, numberOfReaders, numberOfWriters, waitingReaders, waitingWriters);&lt;br /&gt;
    if (numberOfReaders == 0 &amp;amp;&amp;amp; waitingWriters &amp;gt; 0)&lt;br /&gt;
        semaphore_V(ok2write);&lt;br /&gt;
    else&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void startwrite(void) {&lt;br /&gt;
// &amp;lt;await nw == 0 &amp;amp;&amp;amp; nr == 0 -&amp;gt; nw++&amp;gt;&lt;br /&gt;
    semaphore_P(mutex);&lt;br /&gt;
    if (numberOfWriters &amp;gt; 0 || numberOfReaders &amp;gt; 0) {&lt;br /&gt;
        waitingWriters++;&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
        semaphore_P(ok2write);&lt;br /&gt;
        waitingWriters--;&lt;br /&gt;
    }&lt;br /&gt;
    numberOfWriters++;&lt;br /&gt;
    printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, numberOfReaders, numberOfWriters, waitingReaders, waitingWriters);&lt;br /&gt;
    semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void endwrite(void) {&lt;br /&gt;
// &amp;lt;nw--&amp;gt;&lt;br /&gt;
    semaphore_P(mutex);&lt;br /&gt;
    numberOfWriters--;&lt;br /&gt;
    printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, numberOfReaders, numberOfWriters, waitingReaders, waitingWriters);&lt;br /&gt;
    if (waitingReaders &amp;gt; 0)&lt;br /&gt;
        semaphore_V(ok2read);&lt;br /&gt;
    else if (waitingWriters &amp;gt; 0)&lt;br /&gt;
        semaphore_V(ok2write);&lt;br /&gt;
    else&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void *reader(void *arg) {&lt;br /&gt;
    int i = (uintptr_t)arg;&lt;br /&gt;
    while (1) {&lt;br /&gt;
        //other code&lt;br /&gt;
        usleep(random() % 200000);&lt;br /&gt;
        startread();&lt;br /&gt;
        //read&lt;br /&gt;
        usleep(random() % 200000);&lt;br /&gt;
        endread();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void *writer(void *arg) {&lt;br /&gt;
    int i = (uintptr_t)arg;&lt;br /&gt;
    while (1) {&lt;br /&gt;
        //other code&lt;br /&gt;
        usleep(random() % 200000);&lt;br /&gt;
        startwrite();&lt;br /&gt;
        //write&lt;br /&gt;
        usleep(random() % 200000);&lt;br /&gt;
        endwrite();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//printf(&amp;quot;philo thinking: %d\n&amp;quot;,i);&lt;br /&gt;
/*while*/&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char *argv[]) {&lt;br /&gt;
    int i;&lt;br /&gt;
    pthread_t t;&lt;br /&gt;
    srandom(time(NULL));&lt;br /&gt;
    mutex=semaphore_create(1);&lt;br /&gt;
    ok2read=semaphore_create(0);&lt;br /&gt;
    ok2write=semaphore_create(0);&lt;br /&gt;
    for (i=0; i&amp;lt;NUMBER_OF_READERS; i++)&lt;br /&gt;
        pthread_create(&amp;amp;t, NULL, reader, (void *)(uintptr_t) i);&lt;br /&gt;
    for (i=0; i&amp;lt;NUMBER_OF_WRITERS; i++)&lt;br /&gt;
        pthread_create(&amp;amp;t, NULL, writer, (void *)(uintptr_t) i);&lt;br /&gt;
    while(1)&lt;br /&gt;
        pause();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== RW2 ==&lt;br /&gt;
Buongiorno, guardando il codice visto a lezione mi sembra che cambiando la condizione del primo if nella startread() da &amp;quot;if (nw &amp;gt; 0 &amp;amp;&amp;amp; ww == 0)&amp;quot; a &amp;quot;if (nw &amp;gt; 0 || ww &amp;gt; 0)&amp;quot; la situazione migliori. In particolare con l'and tra quelle due condizioni si aveva che non veniva fatta la P sull'ok2read anche quando si aveva nw&amp;gt;0 (con ww!=0), cosa che invece dovrebbe fare. Lasciando il resto del codice uguale mi sembra che faccia quello che deve fare.. .&lt;br /&gt;
&lt;br /&gt;
Matteo.pincherle: Perch&amp;amp;eacute; non modifichi in programma di FedericoB, lo provi e pubblichi qui la patch? [[User:Renzo|Renzo]] ([[User talk:Renzo|talk]]) 10:42, 13 November 2016 (CET)&lt;br /&gt;
&lt;br /&gt;
'''Perchè quel AND permetteva di avere 2 scrittori?''' &amp;lt;br&amp;gt;&lt;br /&gt;
Permetteva in primis di avere dei lettori in contemporanea a uno scrittore. In quanto se succedeva che un lettore volesse entrare mentre non c'erano degli scrittori in attesa ma scrittori in scrittura, veniva saltato il blocco che mandava il lettore in attesa e risultava un lettore in contemporanea a uno scrittore. &amp;lt;br&amp;gt;&lt;br /&gt;
Questo lettore poi poteva finire di leggere prima che lo scrittore in contemporanea a lui finisse di scrivere. &amp;lt;br&amp;gt;&lt;br /&gt;
Il lettore in uscita se non c'erano altri lettori con lui e non c'erano scrittori in attesa dava il permesso per far accedere un altro scrittore. &amp;lt;br&amp;gt;&lt;br /&gt;
A questo punto un altro scrittore che avesse voluto entrare poteva entrare, con il risultato di avere 2 scrittori in contemporanea.&lt;br /&gt;
--[[User:FedericoB|FedericoB]] ([[User talk:FedericoB|talk]]) 19:25, 13 November 2016 (CET)&lt;br /&gt;
&lt;br /&gt;
== Patch ==&lt;br /&gt;
Così, se non sbaglio, quando c'è almeno uno scrittore in attesa non lascia entrare altri lettori. Fa esaurire la lettura dei presenti e poi lascia scrivere lo scrittore.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include&amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include&amp;lt;stdint.h&amp;gt;&lt;br /&gt;
#include&amp;lt;pthread.h&amp;gt;&lt;br /&gt;
#include&amp;lt;semaphore.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define NUMBER_OF_READERS 3&lt;br /&gt;
#define NUMBER_OF_WRITERS 3&lt;br /&gt;
semaphore mutex;&lt;br /&gt;
semaphore ok2read;&lt;br /&gt;
semaphore ok2write;&lt;br /&gt;
&lt;br /&gt;
int numberOfReaders=0;&lt;br /&gt;
int numberOfWriters=0;&lt;br /&gt;
int waitingReaders=0;&lt;br /&gt;
int waitingWriters=0;&lt;br /&gt;
int w_last;&lt;br /&gt;
&lt;br /&gt;
// (nw == 0 &amp;amp;&amp;amp; nr == 0) || (nr &amp;gt; 0 &amp;amp;&amp;amp; nw == 0) || nw == 1&lt;br /&gt;
// (nw == 0 &amp;amp;&amp;amp; nr &amp;gt;= 0) || nw == 1&lt;br /&gt;
&lt;br /&gt;
void startread(void) {&lt;br /&gt;
    // &amp;lt;await nw == 0 -&amp;gt; nr++&amp;gt;&lt;br /&gt;
    semaphore_P(mutex);&lt;br /&gt;
    if (numberOfWriters &amp;gt; 0 || waitingWriters&amp;gt;0) {&lt;br /&gt;
        waitingReaders++;&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
        semaphore_P(ok2read);&lt;br /&gt;
        waitingReaders--;&lt;br /&gt;
    }&lt;br /&gt;
    numberOfReaders++;&lt;br /&gt;
    w_last=0;&lt;br /&gt;
    printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, numberOfReaders, numberOfWriters, waitingReaders, waitingWriters);&lt;br /&gt;
    if (waitingReaders &amp;gt; 0 )&lt;br /&gt;
        semaphore_V(ok2read);&lt;br /&gt;
    else&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void endread(void) {&lt;br /&gt;
    // &amp;lt;nr--&amp;gt;&lt;br /&gt;
    semaphore_P(mutex);&lt;br /&gt;
    numberOfReaders--;&lt;br /&gt;
    printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, numberOfReaders, numberOfWriters, waitingReaders, waitingWriters);&lt;br /&gt;
    if (numberOfReaders == 0 &amp;amp;&amp;amp; waitingWriters &amp;gt; 0)&lt;br /&gt;
        semaphore_V(ok2write);&lt;br /&gt;
    else&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void startwrite(void) {&lt;br /&gt;
    // &amp;lt;await nw == 0 &amp;amp;&amp;amp; nr == 0 -&amp;gt; nw++&amp;gt;&lt;br /&gt;
    semaphore_P(mutex);&lt;br /&gt;
    if (numberOfWriters &amp;gt; 0 || numberOfReaders &amp;gt; 0) {&lt;br /&gt;
        waitingWriters++;&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
        semaphore_P(ok2write);&lt;br /&gt;
        waitingWriters--;&lt;br /&gt;
    }&lt;br /&gt;
    numberOfWriters++;&lt;br /&gt;
    w_last=1;&lt;br /&gt;
    printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, numberOfReaders, numberOfWriters, waitingReaders, waitingWriters);&lt;br /&gt;
    semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void endwrite(void) {&lt;br /&gt;
    // &amp;lt;nw--&amp;gt;&lt;br /&gt;
    semaphore_P(mutex);&lt;br /&gt;
    numberOfWriters--;&lt;br /&gt;
    printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, numberOfReaders, numberOfWriters, waitingReaders, waitingWriters);&lt;br /&gt;
    if (waitingReaders &amp;gt; 0 &amp;amp;&amp;amp; (waitingWriters==0 || w_last))&lt;br /&gt;
        semaphore_V(ok2read);&lt;br /&gt;
    else if (waitingWriters &amp;gt; 0 &amp;amp;&amp;amp; (waitingReaders==0 || !w_last))&lt;br /&gt;
        semaphore_V(ok2write);&lt;br /&gt;
    else&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void *reader(void *arg) {&lt;br /&gt;
    int i = (uintptr_t)arg;&lt;br /&gt;
    while (1) {&lt;br /&gt;
        //other code&lt;br /&gt;
        usleep(random() % 200000);&lt;br /&gt;
        startread();&lt;br /&gt;
        //read&lt;br /&gt;
        usleep(random() % 200000);&lt;br /&gt;
        endread();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void *writer(void *arg) {&lt;br /&gt;
    int i = (uintptr_t)arg;&lt;br /&gt;
    while (1) {&lt;br /&gt;
        //other code&lt;br /&gt;
        usleep(random() % 200000);&lt;br /&gt;
        startwrite();&lt;br /&gt;
        //write&lt;br /&gt;
        usleep(random() % 200000);&lt;br /&gt;
        endwrite();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char *argv[]) {&lt;br /&gt;
    int i;&lt;br /&gt;
    pthread_t t;&lt;br /&gt;
    srandom(time(NULL));&lt;br /&gt;
    mutex=semaphore_create(1);&lt;br /&gt;
    ok2read=semaphore_create(0);&lt;br /&gt;
    ok2write=semaphore_create(0);&lt;br /&gt;
    for (i=0; i&amp;lt;NUMBER_OF_READERS; i++)&lt;br /&gt;
        pthread_create(&amp;amp;t, NULL, reader, (void *)(uintptr_t) i);&lt;br /&gt;
    for (i=0; i&amp;lt;NUMBER_OF_WRITERS; i++)&lt;br /&gt;
        pthread_create(&amp;amp;t, NULL, writer, (void *)(uintptr_t) i);&lt;br /&gt;
    while(1)&lt;br /&gt;
        pause();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
wlast non serve pi&amp;amp;ugrave;... [[User:Renzo|Renzo]] ([[User talk:Renzo|talk]]) 17:52, 13 November 2016 (CET)&lt;br /&gt;
&lt;br /&gt;
== RW2bis ==&lt;br /&gt;
Nella tua soluzione se i lettori sono &amp;quot;molto veloci&amp;quot; e non vanno mai a 0, lo scrittore non inizierà mai a scrivere.&lt;br /&gt;
&lt;br /&gt;
Cioè: Uno scrittore viene svegliato da ok2write solo se passa la condizione &lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
[..] &lt;br /&gt;
if (numberofReaders == 0 &amp;amp;&amp;amp; waitingWriters &amp;gt;0) &lt;br /&gt;
     semaphore_V(ok2write);&lt;br /&gt;
[..]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; --[[User:GabrieleCalarota|GabrieleCalarota]] ([[User talk:GabrieleCalarota|talk]]) 17:46, 13 November 2016 (CET)&lt;br /&gt;
&lt;br /&gt;
Non direi perche' nella startread se:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
    if (numberOfWriters &amp;gt; 0 || waitingWriters&amp;gt;0) &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
i lettori si bloccano. Quindi se c'e' almeno uno scrittore in attesa i lettori non entrano (e quindi prima o poi terminano e lasciano il posto ad uno scrittore).&lt;br /&gt;
[[User:Renzo|Renzo]] ([[User talk:Renzo|talk]]) 17:57, 13 November 2016 (CET)&lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
Ho pensato al caso limite seguente:&lt;br /&gt;
Supponiamo che ci siano dei lettori che stanno leggendo e ad un certo punto uno scrittore chiede di scrivere.&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;syntaxhighlight lang=C&amp;gt;         &lt;br /&gt;
       void startread(void) {&lt;br /&gt;
    // &amp;lt;await nw == 0 -&amp;gt; nr++&amp;gt;&lt;br /&gt;
    semaphore_P(mutex);&lt;br /&gt;
    if (numberOfWriters &amp;gt; 0 || waitingWriters&amp;gt;0) {&lt;br /&gt;
        waitingReaders++;   //Nuovo scrittore (t1)&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
        semaphore_P(ok2read);&lt;br /&gt;
        waitingReaders--;&lt;br /&gt;
    }&lt;br /&gt;
    numberOfReaders++;&lt;br /&gt;
    w_last=0;&lt;br /&gt;
    printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, numberOfReaders, numberOfWriters, waitingReaders, waitingWriters);&lt;br /&gt;
   if (waitingReaders &amp;gt; 0 )   //Vecchio scrittore(t1)&lt;br /&gt;
        semaphore_V(ok2read);&lt;br /&gt;
    else&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Non appena lo scrittore rilascia il mutex, un nuovo lettore chiede di leggere (e si addormenterà). Un lettore (lento) che era riuscito a entrare nel segmento startofread prima che lo scrittore entrasse in startofwrite, continua a leggere e risveglia uno dei nuovi lettori. Se i lettori continuano a richiedere di leggere continuamente, verranno addormentati e subito risvegliati. &lt;br /&gt;
&lt;br /&gt;
E' da considerarsi possibile? --[[User:GabrieleCalarota|GabrieleCalarota]] ([[User talk:GabrieleCalarota|talk]]) 19:11, 13 November 2016 (CET)&lt;br /&gt;
&lt;br /&gt;
Suppongo che &amp;quot;un nuovo scrittore chiede di leggere&amp;quot; si aun refuso e sia da intendere &amp;quot;un nuovo lettore chiede di leggere&amp;quot; (altrimenti ci sono crisi di identit&amp;amp;agrave;) e che &amp;quot;startofread&amp;quot; significhi &amp;quot;startread&amp;quot; e &amp;quot;startofwrite&amp;quot;  sia &amp;quot;startwrite&amp;quot;.&lt;br /&gt;
La &amp;quot;startread&amp;quot; viene eseguita in mutua esclusione, quindi non ci puo' essere &amp;quot;un lettore lento che sia riuscito ad entrare&amp;quot; nella funione startread. Se ha superato la P(mutex) iniziale o e' bloccato sulla ok2read o e' entrato. [[User:Renzo|Renzo]] ([[User talk:Renzo|talk]]) 19:37, 13 November 2016 (CET)&lt;/div&gt;</summary>
		<author><name>GabrieleCalarota</name></author>
	</entry>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=Zibaldone&amp;diff=1597</id>
		<title>Zibaldone</title>
		<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php?title=Zibaldone&amp;diff=1597"/>
		<updated>2016-11-13T18:12:33Z</updated>

		<summary type="html">&lt;p&gt;GabrieleCalarota: /* RW2bis */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== RW errato ==&lt;br /&gt;
Codice '''ERRATO''' dei lettori scrittori che dovrebbe non soffrire di problemi di starvation...&lt;br /&gt;
Esercizio: trovare gli errori.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
#include&amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include&amp;lt;stdint.h&amp;gt;&lt;br /&gt;
#include&amp;lt;pthread.h&amp;gt;&lt;br /&gt;
#include&amp;lt;semaphore.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define NREADER 3&lt;br /&gt;
#define NWRITER 3&lt;br /&gt;
semaphore mutex;&lt;br /&gt;
semaphore ok2read;&lt;br /&gt;
semaphore ok2write;&lt;br /&gt;
&lt;br /&gt;
int nr=0;&lt;br /&gt;
int nw=0;&lt;br /&gt;
int wr=0;&lt;br /&gt;
int ww=0;&lt;br /&gt;
int w_last;&lt;br /&gt;
&lt;br /&gt;
// (nw == 0 &amp;amp;&amp;amp; nr == 0) || (nr &amp;gt; 0 &amp;amp;&amp;amp; nw == 0) || nw == 1&lt;br /&gt;
// (nw == 0 &amp;amp;&amp;amp; nr &amp;gt;= 0) || nw == 1&lt;br /&gt;
&lt;br /&gt;
// this &amp;quot;baton&amp;quot; function has been left for reference only.&lt;br /&gt;
// code to implement &amp;quot;passing the baton&amp;quot; has been copied at the end of&lt;br /&gt;
// each ({start}|{end})({read}|{write}) function and reduced.&lt;br /&gt;
void baton(void) {&lt;br /&gt;
        if (nw == 0 &amp;amp;&amp;amp; nr == 0 &amp;amp;&amp;amp; ww &amp;gt; 0)&lt;br /&gt;
                semaphore_V(ok2write);&lt;br /&gt;
        else if (nw == 0 &amp;amp;&amp;amp; wr &amp;gt; 0 )&lt;br /&gt;
                semaphore_V(ok2read);&lt;br /&gt;
        else&lt;br /&gt;
                semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void startread(void) {&lt;br /&gt;
// &amp;lt;await nw == 0 -&amp;gt; nr++&amp;gt;&lt;br /&gt;
        semaphore_P(mutex);&lt;br /&gt;
        if (nw &amp;gt; 0 &amp;amp;&amp;amp; ww == 0) {&lt;br /&gt;
                wr++;&lt;br /&gt;
                semaphore_V(mutex);&lt;br /&gt;
                semaphore_P(ok2read);&lt;br /&gt;
                wr--;&lt;br /&gt;
        }&lt;br /&gt;
        nr++;&lt;br /&gt;
        w_last=0;&lt;br /&gt;
        printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, nr, nw, wr, ww);&lt;br /&gt;
        if (wr &amp;gt; 0 )&lt;br /&gt;
                semaphore_V(ok2read);&lt;br /&gt;
        else&lt;br /&gt;
                semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void endread(void) {&lt;br /&gt;
// &amp;lt;nr--&amp;gt;&lt;br /&gt;
        semaphore_P(mutex);&lt;br /&gt;
        nr--;&lt;br /&gt;
        printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, nr, nw, wr, ww);&lt;br /&gt;
        if (nr == 0 &amp;amp;&amp;amp; ww &amp;gt; 0)&lt;br /&gt;
                semaphore_V(ok2write);&lt;br /&gt;
        else&lt;br /&gt;
                semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void startwrite(void) {&lt;br /&gt;
// &amp;lt;await nw == 0 &amp;amp;&amp;amp; nr == 0 -&amp;gt; nw++&amp;gt;&lt;br /&gt;
        semaphore_P(mutex);&lt;br /&gt;
        if (nw &amp;gt; 0 || nr &amp;gt; 0) {&lt;br /&gt;
                ww++;&lt;br /&gt;
                semaphore_V(mutex);&lt;br /&gt;
                semaphore_P(ok2write);&lt;br /&gt;
                ww--;&lt;br /&gt;
        }&lt;br /&gt;
        nw++;&lt;br /&gt;
        w_last=1;&lt;br /&gt;
        printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, nr, nw, wr, ww);&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void endwrite(void) {&lt;br /&gt;
// &amp;lt;nw--&amp;gt;&lt;br /&gt;
        semaphore_P(mutex);&lt;br /&gt;
        nw--;&lt;br /&gt;
        printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, nr, nw, wr, ww);&lt;br /&gt;
        if (wr &amp;gt; 0 &amp;amp;&amp;amp; (ww == 0 || w_last))&lt;br /&gt;
                semaphore_V(ok2read);&lt;br /&gt;
        else if (ww &amp;gt; 0 &amp;amp;&amp;amp; (wr == 0 || !w_last))&lt;br /&gt;
                semaphore_V(ok2write);&lt;br /&gt;
        else&lt;br /&gt;
                semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void *reader(void *arg) {&lt;br /&gt;
        int i = (uintptr_t)arg;&lt;br /&gt;
        while (1) {&lt;br /&gt;
                //other code&lt;br /&gt;
                usleep(random() % 200000);&lt;br /&gt;
                startread();&lt;br /&gt;
                //read&lt;br /&gt;
                usleep(random() % 200000);&lt;br /&gt;
                endread();&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void *writer(void *arg) {&lt;br /&gt;
        int i = (uintptr_t)arg;&lt;br /&gt;
        while (1) {&lt;br /&gt;
                //other code&lt;br /&gt;
                usleep(random() % 200000);&lt;br /&gt;
                startwrite();&lt;br /&gt;
                //write&lt;br /&gt;
                usleep(random() % 200000);&lt;br /&gt;
                endwrite();&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//printf(&amp;quot;philo thinking: %d\n&amp;quot;,i);&lt;br /&gt;
/*while*/&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char *argv[]) {&lt;br /&gt;
        int i;&lt;br /&gt;
        pthread_t t;&lt;br /&gt;
        srandom(time(NULL));&lt;br /&gt;
        mutex=semaphore_create(1);&lt;br /&gt;
        ok2read=semaphore_create(0);&lt;br /&gt;
        ok2write=semaphore_create(0);&lt;br /&gt;
        for (i=0; i&amp;lt;NREADER; i++)&lt;br /&gt;
                pthread_create(&amp;amp;t, NULL, reader, (void *)(uintptr_t) i);&lt;br /&gt;
        for (i=0; i&amp;lt;NWRITER; i++)&lt;br /&gt;
                pthread_create(&amp;amp;t, NULL, writer, (void *)(uintptr_t) i);&lt;br /&gt;
        while(1)&lt;br /&gt;
                pause();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== RW di FedericoB ==&lt;br /&gt;
Propongo la seguente soluzione. Mi sembra che funzioni ma devo ancora capire perchè e documentarla bene. Ho provato prima a cercare il bug ma non ci sono riuscito. Ho quindi modificato il codice secondo ciò che mi sembrava sensato in base alle condizioni del problema. Ne possiamo parlare in aula oggi. --[[User:FedericoB|FedericoB]] ([[User talk:FedericoB|talk]]) 12:48, 11 November 2016 (CET)&lt;br /&gt;
Ho notato che l'errore non si manifesta più eliminando il controllo che ci siano scrittori in attesa quando un lettore vuole iniziare a scrivere. Non capisco come questo possa essere collegato al bug. --[[User:FedericoB|FedericoB]] ([[User talk:FedericoB|talk]]) 15:10, 11 November 2016 (CET)&lt;br /&gt;
&lt;br /&gt;
FedericoB, questa soluzione &amp;amp;egrave; quella con priorit&amp;amp;agrave; ai lettori, no? Se continuano ad arrivare lettori numberOfReaders non sar&amp;amp;agrave; mai zero e quindi gli scrittori non scriveranno mai. [[User:Renzo|Renzo]] ([[User talk:Renzo|talk]]) 10:34, 12 November 2016 (CET)&lt;br /&gt;
&lt;br /&gt;
SFIDA: ho trovato il modo di togliere la starvation aggiungendo 4 token (parole chiave, nomi di variabili, operatori, costanti) a questa soluzione di FedericoB. Chi trova la soluzione? [[User:Renzo|Renzo]] ([[User talk:Renzo|talk]]) 10:43, 12 November 2016 (CET) Ah! ho appena trovato una soluzione che prevede 2 soli token in pi&amp;amp;ugrave;! [[User:Renzo|Renzo]] ([[User talk:Renzo|talk]]) 10:47, 12 November 2016 (CET)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
#include&amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include&amp;lt;stdint.h&amp;gt;&lt;br /&gt;
#include&amp;lt;pthread.h&amp;gt;&lt;br /&gt;
#include&amp;lt;semaphore.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define NUMBER_OF_READERS 3&lt;br /&gt;
#define NUMBER_OF_WRITERS 3&lt;br /&gt;
semaphore mutex;&lt;br /&gt;
semaphore ok2read;&lt;br /&gt;
semaphore ok2write;&lt;br /&gt;
&lt;br /&gt;
int numberOfReaders=0;&lt;br /&gt;
int numberOfWriters=0;&lt;br /&gt;
int waitingReaders=0;&lt;br /&gt;
int waitingWriters=0;&lt;br /&gt;
&lt;br /&gt;
// (nw == 0 &amp;amp;&amp;amp; nr == 0) || (nr &amp;gt; 0 &amp;amp;&amp;amp; nw == 0) || nw == 1&lt;br /&gt;
// (nw == 0 &amp;amp;&amp;amp; nr &amp;gt;= 0) || nw == 1&lt;br /&gt;
&lt;br /&gt;
void startread(void) {&lt;br /&gt;
// &amp;lt;await nw == 0 -&amp;gt; nr++&amp;gt;&lt;br /&gt;
    semaphore_P(mutex);&lt;br /&gt;
    if (numberOfWriters &amp;gt; 0) {&lt;br /&gt;
        waitingReaders++;&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
        semaphore_P(ok2read);&lt;br /&gt;
        waitingReaders--;&lt;br /&gt;
    }&lt;br /&gt;
    numberOfReaders++;&lt;br /&gt;
    printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, numberOfReaders, numberOfWriters, waitingReaders, waitingWriters);&lt;br /&gt;
    if (waitingReaders &amp;gt; 0 )&lt;br /&gt;
        semaphore_V(ok2read);&lt;br /&gt;
    else&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void endread(void) {&lt;br /&gt;
// &amp;lt;nr--&amp;gt;&lt;br /&gt;
    semaphore_P(mutex);&lt;br /&gt;
    numberOfReaders--;&lt;br /&gt;
    printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, numberOfReaders, numberOfWriters, waitingReaders, waitingWriters);&lt;br /&gt;
    if (numberOfReaders == 0 &amp;amp;&amp;amp; waitingWriters &amp;gt; 0)&lt;br /&gt;
        semaphore_V(ok2write);&lt;br /&gt;
    else&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void startwrite(void) {&lt;br /&gt;
// &amp;lt;await nw == 0 &amp;amp;&amp;amp; nr == 0 -&amp;gt; nw++&amp;gt;&lt;br /&gt;
    semaphore_P(mutex);&lt;br /&gt;
    if (numberOfWriters &amp;gt; 0 || numberOfReaders &amp;gt; 0) {&lt;br /&gt;
        waitingWriters++;&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
        semaphore_P(ok2write);&lt;br /&gt;
        waitingWriters--;&lt;br /&gt;
    }&lt;br /&gt;
    numberOfWriters++;&lt;br /&gt;
    printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, numberOfReaders, numberOfWriters, waitingReaders, waitingWriters);&lt;br /&gt;
    semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void endwrite(void) {&lt;br /&gt;
// &amp;lt;nw--&amp;gt;&lt;br /&gt;
    semaphore_P(mutex);&lt;br /&gt;
    numberOfWriters--;&lt;br /&gt;
    printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, numberOfReaders, numberOfWriters, waitingReaders, waitingWriters);&lt;br /&gt;
    if (waitingReaders &amp;gt; 0)&lt;br /&gt;
        semaphore_V(ok2read);&lt;br /&gt;
    else if (waitingWriters &amp;gt; 0)&lt;br /&gt;
        semaphore_V(ok2write);&lt;br /&gt;
    else&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void *reader(void *arg) {&lt;br /&gt;
    int i = (uintptr_t)arg;&lt;br /&gt;
    while (1) {&lt;br /&gt;
        //other code&lt;br /&gt;
        usleep(random() % 200000);&lt;br /&gt;
        startread();&lt;br /&gt;
        //read&lt;br /&gt;
        usleep(random() % 200000);&lt;br /&gt;
        endread();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void *writer(void *arg) {&lt;br /&gt;
    int i = (uintptr_t)arg;&lt;br /&gt;
    while (1) {&lt;br /&gt;
        //other code&lt;br /&gt;
        usleep(random() % 200000);&lt;br /&gt;
        startwrite();&lt;br /&gt;
        //write&lt;br /&gt;
        usleep(random() % 200000);&lt;br /&gt;
        endwrite();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//printf(&amp;quot;philo thinking: %d\n&amp;quot;,i);&lt;br /&gt;
/*while*/&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char *argv[]) {&lt;br /&gt;
    int i;&lt;br /&gt;
    pthread_t t;&lt;br /&gt;
    srandom(time(NULL));&lt;br /&gt;
    mutex=semaphore_create(1);&lt;br /&gt;
    ok2read=semaphore_create(0);&lt;br /&gt;
    ok2write=semaphore_create(0);&lt;br /&gt;
    for (i=0; i&amp;lt;NUMBER_OF_READERS; i++)&lt;br /&gt;
        pthread_create(&amp;amp;t, NULL, reader, (void *)(uintptr_t) i);&lt;br /&gt;
    for (i=0; i&amp;lt;NUMBER_OF_WRITERS; i++)&lt;br /&gt;
        pthread_create(&amp;amp;t, NULL, writer, (void *)(uintptr_t) i);&lt;br /&gt;
    while(1)&lt;br /&gt;
        pause();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== RW2 ==&lt;br /&gt;
Buongiorno, guardando il codice visto a lezione mi sembra che cambiando la condizione del primo if nella startread() da &amp;quot;if (nw &amp;gt; 0 &amp;amp;&amp;amp; ww == 0)&amp;quot; a &amp;quot;if (nw &amp;gt; 0 || ww &amp;gt; 0)&amp;quot; la situazione migliori. In particolare con l'and tra quelle due condizioni si aveva che non veniva fatta la P sull'ok2read anche quando si aveva nw&amp;gt;0 (con ww!=0), cosa che invece dovrebbe fare. Lasciando il resto del codice uguale mi sembra che faccia quello che deve fare.. .&lt;br /&gt;
&lt;br /&gt;
Matteo.pincherle: Perch&amp;amp;eacute; non modifichi in programma di FedericoB, lo provi e pubblichi qui la patch? [[User:Renzo|Renzo]] ([[User talk:Renzo|talk]]) 10:42, 13 November 2016 (CET)&lt;br /&gt;
&lt;br /&gt;
== Patch ==&lt;br /&gt;
Così, se non sbaglio, quando c'è almeno uno scrittore in attesa non lascia entrare altri lettori. Fa esaurire la lettura dei presenti e poi lascia scrivere lo scrittore.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include&amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include&amp;lt;stdint.h&amp;gt;&lt;br /&gt;
#include&amp;lt;pthread.h&amp;gt;&lt;br /&gt;
#include&amp;lt;semaphore.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define NUMBER_OF_READERS 3&lt;br /&gt;
#define NUMBER_OF_WRITERS 3&lt;br /&gt;
semaphore mutex;&lt;br /&gt;
semaphore ok2read;&lt;br /&gt;
semaphore ok2write;&lt;br /&gt;
&lt;br /&gt;
int numberOfReaders=0;&lt;br /&gt;
int numberOfWriters=0;&lt;br /&gt;
int waitingReaders=0;&lt;br /&gt;
int waitingWriters=0;&lt;br /&gt;
int w_last;&lt;br /&gt;
&lt;br /&gt;
// (nw == 0 &amp;amp;&amp;amp; nr == 0) || (nr &amp;gt; 0 &amp;amp;&amp;amp; nw == 0) || nw == 1&lt;br /&gt;
// (nw == 0 &amp;amp;&amp;amp; nr &amp;gt;= 0) || nw == 1&lt;br /&gt;
&lt;br /&gt;
void startread(void) {&lt;br /&gt;
    // &amp;lt;await nw == 0 -&amp;gt; nr++&amp;gt;&lt;br /&gt;
    semaphore_P(mutex);&lt;br /&gt;
    if (numberOfWriters &amp;gt; 0 || waitingWriters&amp;gt;0) {&lt;br /&gt;
        waitingReaders++;&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
        semaphore_P(ok2read);&lt;br /&gt;
        waitingReaders--;&lt;br /&gt;
    }&lt;br /&gt;
    numberOfReaders++;&lt;br /&gt;
    w_last=0;&lt;br /&gt;
    printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, numberOfReaders, numberOfWriters, waitingReaders, waitingWriters);&lt;br /&gt;
    if (waitingReaders &amp;gt; 0 )&lt;br /&gt;
        semaphore_V(ok2read);&lt;br /&gt;
    else&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void endread(void) {&lt;br /&gt;
    // &amp;lt;nr--&amp;gt;&lt;br /&gt;
    semaphore_P(mutex);&lt;br /&gt;
    numberOfReaders--;&lt;br /&gt;
    printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, numberOfReaders, numberOfWriters, waitingReaders, waitingWriters);&lt;br /&gt;
    if (numberOfReaders == 0 &amp;amp;&amp;amp; waitingWriters &amp;gt; 0)&lt;br /&gt;
        semaphore_V(ok2write);&lt;br /&gt;
    else&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void startwrite(void) {&lt;br /&gt;
    // &amp;lt;await nw == 0 &amp;amp;&amp;amp; nr == 0 -&amp;gt; nw++&amp;gt;&lt;br /&gt;
    semaphore_P(mutex);&lt;br /&gt;
    if (numberOfWriters &amp;gt; 0 || numberOfReaders &amp;gt; 0) {&lt;br /&gt;
        waitingWriters++;&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
        semaphore_P(ok2write);&lt;br /&gt;
        waitingWriters--;&lt;br /&gt;
    }&lt;br /&gt;
    numberOfWriters++;&lt;br /&gt;
    w_last=1;&lt;br /&gt;
    printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, numberOfReaders, numberOfWriters, waitingReaders, waitingWriters);&lt;br /&gt;
    semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void endwrite(void) {&lt;br /&gt;
    // &amp;lt;nw--&amp;gt;&lt;br /&gt;
    semaphore_P(mutex);&lt;br /&gt;
    numberOfWriters--;&lt;br /&gt;
    printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, numberOfReaders, numberOfWriters, waitingReaders, waitingWriters);&lt;br /&gt;
    if (waitingReaders &amp;gt; 0 &amp;amp;&amp;amp; (waitingWriters==0 || w_last))&lt;br /&gt;
        semaphore_V(ok2read);&lt;br /&gt;
    else if (waitingWriters &amp;gt; 0 &amp;amp;&amp;amp; (waitingReaders==0 || !w_last))&lt;br /&gt;
        semaphore_V(ok2write);&lt;br /&gt;
    else&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void *reader(void *arg) {&lt;br /&gt;
    int i = (uintptr_t)arg;&lt;br /&gt;
    while (1) {&lt;br /&gt;
        //other code&lt;br /&gt;
        usleep(random() % 200000);&lt;br /&gt;
        startread();&lt;br /&gt;
        //read&lt;br /&gt;
        usleep(random() % 200000);&lt;br /&gt;
        endread();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void *writer(void *arg) {&lt;br /&gt;
    int i = (uintptr_t)arg;&lt;br /&gt;
    while (1) {&lt;br /&gt;
        //other code&lt;br /&gt;
        usleep(random() % 200000);&lt;br /&gt;
        startwrite();&lt;br /&gt;
        //write&lt;br /&gt;
        usleep(random() % 200000);&lt;br /&gt;
        endwrite();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char *argv[]) {&lt;br /&gt;
    int i;&lt;br /&gt;
    pthread_t t;&lt;br /&gt;
    srandom(time(NULL));&lt;br /&gt;
    mutex=semaphore_create(1);&lt;br /&gt;
    ok2read=semaphore_create(0);&lt;br /&gt;
    ok2write=semaphore_create(0);&lt;br /&gt;
    for (i=0; i&amp;lt;NUMBER_OF_READERS; i++)&lt;br /&gt;
        pthread_create(&amp;amp;t, NULL, reader, (void *)(uintptr_t) i);&lt;br /&gt;
    for (i=0; i&amp;lt;NUMBER_OF_WRITERS; i++)&lt;br /&gt;
        pthread_create(&amp;amp;t, NULL, writer, (void *)(uintptr_t) i);&lt;br /&gt;
    while(1)&lt;br /&gt;
        pause();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
wlast non serve pi&amp;amp;ugrave;... [[User:Renzo|Renzo]] ([[User talk:Renzo|talk]]) 17:52, 13 November 2016 (CET)&lt;br /&gt;
&lt;br /&gt;
== RW2bis ==&lt;br /&gt;
Nella tua soluzione se i lettori sono &amp;quot;molto veloci&amp;quot; e non vanno mai a 0, lo scrittore non inizierà mai a scrivere.&lt;br /&gt;
&lt;br /&gt;
Cioè: Uno scrittore viene svegliato da ok2write solo se passa la condizione &lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
[..] &lt;br /&gt;
if (numberofReaders == 0 &amp;amp;&amp;amp; waitingWriters &amp;gt;0) &lt;br /&gt;
     semaphore_V(ok2write);&lt;br /&gt;
[..]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; --[[User:GabrieleCalarota|GabrieleCalarota]] ([[User talk:GabrieleCalarota|talk]]) 17:46, 13 November 2016 (CET)&lt;br /&gt;
&lt;br /&gt;
Non direi perche' nella startread se:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
    if (numberOfWriters &amp;gt; 0 || waitingWriters&amp;gt;0) &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
i lettori si bloccano. Quindi se c'e' almeno uno scrittore in attesa i lettori non entrano (e quindi prima o poi terminano e lasciano il posto ad uno scrittore).&lt;br /&gt;
[[User:Renzo|Renzo]] ([[User talk:Renzo|talk]]) 17:57, 13 November 2016 (CET)&lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
Ho pensato al caso limite seguente:&lt;br /&gt;
Supponiamo che ci siano dei lettori che stanno leggendo e ad un certo punto uno scrittore chiede di scrivere.&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;syntaxhighlight lang=C&amp;gt;         &lt;br /&gt;
       void startread(void) {&lt;br /&gt;
    // &amp;lt;await nw == 0 -&amp;gt; nr++&amp;gt;&lt;br /&gt;
    semaphore_P(mutex);&lt;br /&gt;
    if (numberOfWriters &amp;gt; 0 || waitingWriters&amp;gt;0) {&lt;br /&gt;
        waitingReaders++;   //Nuovo scrittore (t1)&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
        semaphore_P(ok2read);&lt;br /&gt;
        waitingReaders--;&lt;br /&gt;
    }&lt;br /&gt;
    numberOfReaders++;&lt;br /&gt;
    w_last=0;&lt;br /&gt;
    printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, numberOfReaders, numberOfWriters, waitingReaders, waitingWriters);&lt;br /&gt;
   if (waitingReaders &amp;gt; 0 )   //Vecchio scrittore(t1)&lt;br /&gt;
        semaphore_V(ok2read);&lt;br /&gt;
    else&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Non appena lo scrittore rilascia il mutex, un nuovo scrittore chiede di leggere (e si addormenterà). Un lettore (lento) che era riuscito a entrare nel segmento startofread prima che lo scrittore entrasse in startofwrite, continua a leggere e risveglia uno dei nuovi lettori. Se i lettori continuano a richiedere di leggere continuamente, verranno addormentati e subito risvegliati. &lt;br /&gt;
&lt;br /&gt;
E' da considerarsi possibile? --[[User:GabrieleCalarota|GabrieleCalarota]] ([[User talk:GabrieleCalarota|talk]]) 19:11, 13 November 2016 (CET)&lt;/div&gt;</summary>
		<author><name>GabrieleCalarota</name></author>
	</entry>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=Zibaldone&amp;diff=1596</id>
		<title>Zibaldone</title>
		<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php?title=Zibaldone&amp;diff=1596"/>
		<updated>2016-11-13T18:12:08Z</updated>

		<summary type="html">&lt;p&gt;GabrieleCalarota: /* RW2bis */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== RW errato ==&lt;br /&gt;
Codice '''ERRATO''' dei lettori scrittori che dovrebbe non soffrire di problemi di starvation...&lt;br /&gt;
Esercizio: trovare gli errori.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
#include&amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include&amp;lt;stdint.h&amp;gt;&lt;br /&gt;
#include&amp;lt;pthread.h&amp;gt;&lt;br /&gt;
#include&amp;lt;semaphore.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define NREADER 3&lt;br /&gt;
#define NWRITER 3&lt;br /&gt;
semaphore mutex;&lt;br /&gt;
semaphore ok2read;&lt;br /&gt;
semaphore ok2write;&lt;br /&gt;
&lt;br /&gt;
int nr=0;&lt;br /&gt;
int nw=0;&lt;br /&gt;
int wr=0;&lt;br /&gt;
int ww=0;&lt;br /&gt;
int w_last;&lt;br /&gt;
&lt;br /&gt;
// (nw == 0 &amp;amp;&amp;amp; nr == 0) || (nr &amp;gt; 0 &amp;amp;&amp;amp; nw == 0) || nw == 1&lt;br /&gt;
// (nw == 0 &amp;amp;&amp;amp; nr &amp;gt;= 0) || nw == 1&lt;br /&gt;
&lt;br /&gt;
// this &amp;quot;baton&amp;quot; function has been left for reference only.&lt;br /&gt;
// code to implement &amp;quot;passing the baton&amp;quot; has been copied at the end of&lt;br /&gt;
// each ({start}|{end})({read}|{write}) function and reduced.&lt;br /&gt;
void baton(void) {&lt;br /&gt;
        if (nw == 0 &amp;amp;&amp;amp; nr == 0 &amp;amp;&amp;amp; ww &amp;gt; 0)&lt;br /&gt;
                semaphore_V(ok2write);&lt;br /&gt;
        else if (nw == 0 &amp;amp;&amp;amp; wr &amp;gt; 0 )&lt;br /&gt;
                semaphore_V(ok2read);&lt;br /&gt;
        else&lt;br /&gt;
                semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void startread(void) {&lt;br /&gt;
// &amp;lt;await nw == 0 -&amp;gt; nr++&amp;gt;&lt;br /&gt;
        semaphore_P(mutex);&lt;br /&gt;
        if (nw &amp;gt; 0 &amp;amp;&amp;amp; ww == 0) {&lt;br /&gt;
                wr++;&lt;br /&gt;
                semaphore_V(mutex);&lt;br /&gt;
                semaphore_P(ok2read);&lt;br /&gt;
                wr--;&lt;br /&gt;
        }&lt;br /&gt;
        nr++;&lt;br /&gt;
        w_last=0;&lt;br /&gt;
        printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, nr, nw, wr, ww);&lt;br /&gt;
        if (wr &amp;gt; 0 )&lt;br /&gt;
                semaphore_V(ok2read);&lt;br /&gt;
        else&lt;br /&gt;
                semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void endread(void) {&lt;br /&gt;
// &amp;lt;nr--&amp;gt;&lt;br /&gt;
        semaphore_P(mutex);&lt;br /&gt;
        nr--;&lt;br /&gt;
        printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, nr, nw, wr, ww);&lt;br /&gt;
        if (nr == 0 &amp;amp;&amp;amp; ww &amp;gt; 0)&lt;br /&gt;
                semaphore_V(ok2write);&lt;br /&gt;
        else&lt;br /&gt;
                semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void startwrite(void) {&lt;br /&gt;
// &amp;lt;await nw == 0 &amp;amp;&amp;amp; nr == 0 -&amp;gt; nw++&amp;gt;&lt;br /&gt;
        semaphore_P(mutex);&lt;br /&gt;
        if (nw &amp;gt; 0 || nr &amp;gt; 0) {&lt;br /&gt;
                ww++;&lt;br /&gt;
                semaphore_V(mutex);&lt;br /&gt;
                semaphore_P(ok2write);&lt;br /&gt;
                ww--;&lt;br /&gt;
        }&lt;br /&gt;
        nw++;&lt;br /&gt;
        w_last=1;&lt;br /&gt;
        printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, nr, nw, wr, ww);&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void endwrite(void) {&lt;br /&gt;
// &amp;lt;nw--&amp;gt;&lt;br /&gt;
        semaphore_P(mutex);&lt;br /&gt;
        nw--;&lt;br /&gt;
        printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, nr, nw, wr, ww);&lt;br /&gt;
        if (wr &amp;gt; 0 &amp;amp;&amp;amp; (ww == 0 || w_last))&lt;br /&gt;
                semaphore_V(ok2read);&lt;br /&gt;
        else if (ww &amp;gt; 0 &amp;amp;&amp;amp; (wr == 0 || !w_last))&lt;br /&gt;
                semaphore_V(ok2write);&lt;br /&gt;
        else&lt;br /&gt;
                semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void *reader(void *arg) {&lt;br /&gt;
        int i = (uintptr_t)arg;&lt;br /&gt;
        while (1) {&lt;br /&gt;
                //other code&lt;br /&gt;
                usleep(random() % 200000);&lt;br /&gt;
                startread();&lt;br /&gt;
                //read&lt;br /&gt;
                usleep(random() % 200000);&lt;br /&gt;
                endread();&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void *writer(void *arg) {&lt;br /&gt;
        int i = (uintptr_t)arg;&lt;br /&gt;
        while (1) {&lt;br /&gt;
                //other code&lt;br /&gt;
                usleep(random() % 200000);&lt;br /&gt;
                startwrite();&lt;br /&gt;
                //write&lt;br /&gt;
                usleep(random() % 200000);&lt;br /&gt;
                endwrite();&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//printf(&amp;quot;philo thinking: %d\n&amp;quot;,i);&lt;br /&gt;
/*while*/&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char *argv[]) {&lt;br /&gt;
        int i;&lt;br /&gt;
        pthread_t t;&lt;br /&gt;
        srandom(time(NULL));&lt;br /&gt;
        mutex=semaphore_create(1);&lt;br /&gt;
        ok2read=semaphore_create(0);&lt;br /&gt;
        ok2write=semaphore_create(0);&lt;br /&gt;
        for (i=0; i&amp;lt;NREADER; i++)&lt;br /&gt;
                pthread_create(&amp;amp;t, NULL, reader, (void *)(uintptr_t) i);&lt;br /&gt;
        for (i=0; i&amp;lt;NWRITER; i++)&lt;br /&gt;
                pthread_create(&amp;amp;t, NULL, writer, (void *)(uintptr_t) i);&lt;br /&gt;
        while(1)&lt;br /&gt;
                pause();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== RW di FedericoB ==&lt;br /&gt;
Propongo la seguente soluzione. Mi sembra che funzioni ma devo ancora capire perchè e documentarla bene. Ho provato prima a cercare il bug ma non ci sono riuscito. Ho quindi modificato il codice secondo ciò che mi sembrava sensato in base alle condizioni del problema. Ne possiamo parlare in aula oggi. --[[User:FedericoB|FedericoB]] ([[User talk:FedericoB|talk]]) 12:48, 11 November 2016 (CET)&lt;br /&gt;
Ho notato che l'errore non si manifesta più eliminando il controllo che ci siano scrittori in attesa quando un lettore vuole iniziare a scrivere. Non capisco come questo possa essere collegato al bug. --[[User:FedericoB|FedericoB]] ([[User talk:FedericoB|talk]]) 15:10, 11 November 2016 (CET)&lt;br /&gt;
&lt;br /&gt;
FedericoB, questa soluzione &amp;amp;egrave; quella con priorit&amp;amp;agrave; ai lettori, no? Se continuano ad arrivare lettori numberOfReaders non sar&amp;amp;agrave; mai zero e quindi gli scrittori non scriveranno mai. [[User:Renzo|Renzo]] ([[User talk:Renzo|talk]]) 10:34, 12 November 2016 (CET)&lt;br /&gt;
&lt;br /&gt;
SFIDA: ho trovato il modo di togliere la starvation aggiungendo 4 token (parole chiave, nomi di variabili, operatori, costanti) a questa soluzione di FedericoB. Chi trova la soluzione? [[User:Renzo|Renzo]] ([[User talk:Renzo|talk]]) 10:43, 12 November 2016 (CET) Ah! ho appena trovato una soluzione che prevede 2 soli token in pi&amp;amp;ugrave;! [[User:Renzo|Renzo]] ([[User talk:Renzo|talk]]) 10:47, 12 November 2016 (CET)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
#include&amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include&amp;lt;stdint.h&amp;gt;&lt;br /&gt;
#include&amp;lt;pthread.h&amp;gt;&lt;br /&gt;
#include&amp;lt;semaphore.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define NUMBER_OF_READERS 3&lt;br /&gt;
#define NUMBER_OF_WRITERS 3&lt;br /&gt;
semaphore mutex;&lt;br /&gt;
semaphore ok2read;&lt;br /&gt;
semaphore ok2write;&lt;br /&gt;
&lt;br /&gt;
int numberOfReaders=0;&lt;br /&gt;
int numberOfWriters=0;&lt;br /&gt;
int waitingReaders=0;&lt;br /&gt;
int waitingWriters=0;&lt;br /&gt;
&lt;br /&gt;
// (nw == 0 &amp;amp;&amp;amp; nr == 0) || (nr &amp;gt; 0 &amp;amp;&amp;amp; nw == 0) || nw == 1&lt;br /&gt;
// (nw == 0 &amp;amp;&amp;amp; nr &amp;gt;= 0) || nw == 1&lt;br /&gt;
&lt;br /&gt;
void startread(void) {&lt;br /&gt;
// &amp;lt;await nw == 0 -&amp;gt; nr++&amp;gt;&lt;br /&gt;
    semaphore_P(mutex);&lt;br /&gt;
    if (numberOfWriters &amp;gt; 0) {&lt;br /&gt;
        waitingReaders++;&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
        semaphore_P(ok2read);&lt;br /&gt;
        waitingReaders--;&lt;br /&gt;
    }&lt;br /&gt;
    numberOfReaders++;&lt;br /&gt;
    printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, numberOfReaders, numberOfWriters, waitingReaders, waitingWriters);&lt;br /&gt;
    if (waitingReaders &amp;gt; 0 )&lt;br /&gt;
        semaphore_V(ok2read);&lt;br /&gt;
    else&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void endread(void) {&lt;br /&gt;
// &amp;lt;nr--&amp;gt;&lt;br /&gt;
    semaphore_P(mutex);&lt;br /&gt;
    numberOfReaders--;&lt;br /&gt;
    printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, numberOfReaders, numberOfWriters, waitingReaders, waitingWriters);&lt;br /&gt;
    if (numberOfReaders == 0 &amp;amp;&amp;amp; waitingWriters &amp;gt; 0)&lt;br /&gt;
        semaphore_V(ok2write);&lt;br /&gt;
    else&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void startwrite(void) {&lt;br /&gt;
// &amp;lt;await nw == 0 &amp;amp;&amp;amp; nr == 0 -&amp;gt; nw++&amp;gt;&lt;br /&gt;
    semaphore_P(mutex);&lt;br /&gt;
    if (numberOfWriters &amp;gt; 0 || numberOfReaders &amp;gt; 0) {&lt;br /&gt;
        waitingWriters++;&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
        semaphore_P(ok2write);&lt;br /&gt;
        waitingWriters--;&lt;br /&gt;
    }&lt;br /&gt;
    numberOfWriters++;&lt;br /&gt;
    printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, numberOfReaders, numberOfWriters, waitingReaders, waitingWriters);&lt;br /&gt;
    semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void endwrite(void) {&lt;br /&gt;
// &amp;lt;nw--&amp;gt;&lt;br /&gt;
    semaphore_P(mutex);&lt;br /&gt;
    numberOfWriters--;&lt;br /&gt;
    printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, numberOfReaders, numberOfWriters, waitingReaders, waitingWriters);&lt;br /&gt;
    if (waitingReaders &amp;gt; 0)&lt;br /&gt;
        semaphore_V(ok2read);&lt;br /&gt;
    else if (waitingWriters &amp;gt; 0)&lt;br /&gt;
        semaphore_V(ok2write);&lt;br /&gt;
    else&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void *reader(void *arg) {&lt;br /&gt;
    int i = (uintptr_t)arg;&lt;br /&gt;
    while (1) {&lt;br /&gt;
        //other code&lt;br /&gt;
        usleep(random() % 200000);&lt;br /&gt;
        startread();&lt;br /&gt;
        //read&lt;br /&gt;
        usleep(random() % 200000);&lt;br /&gt;
        endread();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void *writer(void *arg) {&lt;br /&gt;
    int i = (uintptr_t)arg;&lt;br /&gt;
    while (1) {&lt;br /&gt;
        //other code&lt;br /&gt;
        usleep(random() % 200000);&lt;br /&gt;
        startwrite();&lt;br /&gt;
        //write&lt;br /&gt;
        usleep(random() % 200000);&lt;br /&gt;
        endwrite();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//printf(&amp;quot;philo thinking: %d\n&amp;quot;,i);&lt;br /&gt;
/*while*/&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char *argv[]) {&lt;br /&gt;
    int i;&lt;br /&gt;
    pthread_t t;&lt;br /&gt;
    srandom(time(NULL));&lt;br /&gt;
    mutex=semaphore_create(1);&lt;br /&gt;
    ok2read=semaphore_create(0);&lt;br /&gt;
    ok2write=semaphore_create(0);&lt;br /&gt;
    for (i=0; i&amp;lt;NUMBER_OF_READERS; i++)&lt;br /&gt;
        pthread_create(&amp;amp;t, NULL, reader, (void *)(uintptr_t) i);&lt;br /&gt;
    for (i=0; i&amp;lt;NUMBER_OF_WRITERS; i++)&lt;br /&gt;
        pthread_create(&amp;amp;t, NULL, writer, (void *)(uintptr_t) i);&lt;br /&gt;
    while(1)&lt;br /&gt;
        pause();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== RW2 ==&lt;br /&gt;
Buongiorno, guardando il codice visto a lezione mi sembra che cambiando la condizione del primo if nella startread() da &amp;quot;if (nw &amp;gt; 0 &amp;amp;&amp;amp; ww == 0)&amp;quot; a &amp;quot;if (nw &amp;gt; 0 || ww &amp;gt; 0)&amp;quot; la situazione migliori. In particolare con l'and tra quelle due condizioni si aveva che non veniva fatta la P sull'ok2read anche quando si aveva nw&amp;gt;0 (con ww!=0), cosa che invece dovrebbe fare. Lasciando il resto del codice uguale mi sembra che faccia quello che deve fare.. .&lt;br /&gt;
&lt;br /&gt;
Matteo.pincherle: Perch&amp;amp;eacute; non modifichi in programma di FedericoB, lo provi e pubblichi qui la patch? [[User:Renzo|Renzo]] ([[User talk:Renzo|talk]]) 10:42, 13 November 2016 (CET)&lt;br /&gt;
&lt;br /&gt;
== Patch ==&lt;br /&gt;
Così, se non sbaglio, quando c'è almeno uno scrittore in attesa non lascia entrare altri lettori. Fa esaurire la lettura dei presenti e poi lascia scrivere lo scrittore.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include&amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include&amp;lt;stdint.h&amp;gt;&lt;br /&gt;
#include&amp;lt;pthread.h&amp;gt;&lt;br /&gt;
#include&amp;lt;semaphore.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define NUMBER_OF_READERS 3&lt;br /&gt;
#define NUMBER_OF_WRITERS 3&lt;br /&gt;
semaphore mutex;&lt;br /&gt;
semaphore ok2read;&lt;br /&gt;
semaphore ok2write;&lt;br /&gt;
&lt;br /&gt;
int numberOfReaders=0;&lt;br /&gt;
int numberOfWriters=0;&lt;br /&gt;
int waitingReaders=0;&lt;br /&gt;
int waitingWriters=0;&lt;br /&gt;
int w_last;&lt;br /&gt;
&lt;br /&gt;
// (nw == 0 &amp;amp;&amp;amp; nr == 0) || (nr &amp;gt; 0 &amp;amp;&amp;amp; nw == 0) || nw == 1&lt;br /&gt;
// (nw == 0 &amp;amp;&amp;amp; nr &amp;gt;= 0) || nw == 1&lt;br /&gt;
&lt;br /&gt;
void startread(void) {&lt;br /&gt;
    // &amp;lt;await nw == 0 -&amp;gt; nr++&amp;gt;&lt;br /&gt;
    semaphore_P(mutex);&lt;br /&gt;
    if (numberOfWriters &amp;gt; 0 || waitingWriters&amp;gt;0) {&lt;br /&gt;
        waitingReaders++;&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
        semaphore_P(ok2read);&lt;br /&gt;
        waitingReaders--;&lt;br /&gt;
    }&lt;br /&gt;
    numberOfReaders++;&lt;br /&gt;
    w_last=0;&lt;br /&gt;
    printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, numberOfReaders, numberOfWriters, waitingReaders, waitingWriters);&lt;br /&gt;
    if (waitingReaders &amp;gt; 0 )&lt;br /&gt;
        semaphore_V(ok2read);&lt;br /&gt;
    else&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void endread(void) {&lt;br /&gt;
    // &amp;lt;nr--&amp;gt;&lt;br /&gt;
    semaphore_P(mutex);&lt;br /&gt;
    numberOfReaders--;&lt;br /&gt;
    printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, numberOfReaders, numberOfWriters, waitingReaders, waitingWriters);&lt;br /&gt;
    if (numberOfReaders == 0 &amp;amp;&amp;amp; waitingWriters &amp;gt; 0)&lt;br /&gt;
        semaphore_V(ok2write);&lt;br /&gt;
    else&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void startwrite(void) {&lt;br /&gt;
    // &amp;lt;await nw == 0 &amp;amp;&amp;amp; nr == 0 -&amp;gt; nw++&amp;gt;&lt;br /&gt;
    semaphore_P(mutex);&lt;br /&gt;
    if (numberOfWriters &amp;gt; 0 || numberOfReaders &amp;gt; 0) {&lt;br /&gt;
        waitingWriters++;&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
        semaphore_P(ok2write);&lt;br /&gt;
        waitingWriters--;&lt;br /&gt;
    }&lt;br /&gt;
    numberOfWriters++;&lt;br /&gt;
    w_last=1;&lt;br /&gt;
    printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, numberOfReaders, numberOfWriters, waitingReaders, waitingWriters);&lt;br /&gt;
    semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void endwrite(void) {&lt;br /&gt;
    // &amp;lt;nw--&amp;gt;&lt;br /&gt;
    semaphore_P(mutex);&lt;br /&gt;
    numberOfWriters--;&lt;br /&gt;
    printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, numberOfReaders, numberOfWriters, waitingReaders, waitingWriters);&lt;br /&gt;
    if (waitingReaders &amp;gt; 0 &amp;amp;&amp;amp; (waitingWriters==0 || w_last))&lt;br /&gt;
        semaphore_V(ok2read);&lt;br /&gt;
    else if (waitingWriters &amp;gt; 0 &amp;amp;&amp;amp; (waitingReaders==0 || !w_last))&lt;br /&gt;
        semaphore_V(ok2write);&lt;br /&gt;
    else&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void *reader(void *arg) {&lt;br /&gt;
    int i = (uintptr_t)arg;&lt;br /&gt;
    while (1) {&lt;br /&gt;
        //other code&lt;br /&gt;
        usleep(random() % 200000);&lt;br /&gt;
        startread();&lt;br /&gt;
        //read&lt;br /&gt;
        usleep(random() % 200000);&lt;br /&gt;
        endread();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void *writer(void *arg) {&lt;br /&gt;
    int i = (uintptr_t)arg;&lt;br /&gt;
    while (1) {&lt;br /&gt;
        //other code&lt;br /&gt;
        usleep(random() % 200000);&lt;br /&gt;
        startwrite();&lt;br /&gt;
        //write&lt;br /&gt;
        usleep(random() % 200000);&lt;br /&gt;
        endwrite();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char *argv[]) {&lt;br /&gt;
    int i;&lt;br /&gt;
    pthread_t t;&lt;br /&gt;
    srandom(time(NULL));&lt;br /&gt;
    mutex=semaphore_create(1);&lt;br /&gt;
    ok2read=semaphore_create(0);&lt;br /&gt;
    ok2write=semaphore_create(0);&lt;br /&gt;
    for (i=0; i&amp;lt;NUMBER_OF_READERS; i++)&lt;br /&gt;
        pthread_create(&amp;amp;t, NULL, reader, (void *)(uintptr_t) i);&lt;br /&gt;
    for (i=0; i&amp;lt;NUMBER_OF_WRITERS; i++)&lt;br /&gt;
        pthread_create(&amp;amp;t, NULL, writer, (void *)(uintptr_t) i);&lt;br /&gt;
    while(1)&lt;br /&gt;
        pause();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
wlast non serve pi&amp;amp;ugrave;... [[User:Renzo|Renzo]] ([[User talk:Renzo|talk]]) 17:52, 13 November 2016 (CET)&lt;br /&gt;
&lt;br /&gt;
== RW2bis ==&lt;br /&gt;
Tecnicamente nella tua soluzione se i lettori sono &amp;quot;molto veloci&amp;quot; e non vanno mai a 0, lo scrittore non inizierà mai a scrivere.&lt;br /&gt;
&lt;br /&gt;
Cioè: Uno scrittore viene svegliato da ok2write solo se passa la condizione &lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
[..] &lt;br /&gt;
if (numberofReaders == 0 &amp;amp;&amp;amp; waitingWriters &amp;gt;0) &lt;br /&gt;
     semaphore_V(ok2write);&lt;br /&gt;
[..]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; --[[User:GabrieleCalarota|GabrieleCalarota]] ([[User talk:GabrieleCalarota|talk]]) 17:46, 13 November 2016 (CET)&lt;br /&gt;
&lt;br /&gt;
Non direi perche' nella startread se:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
    if (numberOfWriters &amp;gt; 0 || waitingWriters&amp;gt;0) &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
i lettori si bloccano. Quindi se c'e' almeno uno scrittore in attesa i lettori non entrano (e quindi prima o poi terminano e lasciano il posto ad uno scrittore).&lt;br /&gt;
[[User:Renzo|Renzo]] ([[User talk:Renzo|talk]]) 17:57, 13 November 2016 (CET)&lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
Ho pensato al caso limite seguente:&lt;br /&gt;
Supponiamo che ci siano dei lettori che stanno leggendo e ad un certo punto uno scrittore chiede di scrivere.&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;syntaxhighlight lang=C&amp;gt;         &lt;br /&gt;
       void startread(void) {&lt;br /&gt;
    // &amp;lt;await nw == 0 -&amp;gt; nr++&amp;gt;&lt;br /&gt;
    semaphore_P(mutex);&lt;br /&gt;
    if (numberOfWriters &amp;gt; 0 || waitingWriters&amp;gt;0) {&lt;br /&gt;
        waitingReaders++;   //Nuovo scrittore (t1)&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
        semaphore_P(ok2read);&lt;br /&gt;
        waitingReaders--;&lt;br /&gt;
    }&lt;br /&gt;
    numberOfReaders++;&lt;br /&gt;
    w_last=0;&lt;br /&gt;
    printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, numberOfReaders, numberOfWriters, waitingReaders, waitingWriters);&lt;br /&gt;
   if (waitingReaders &amp;gt; 0 )   //Vecchio scrittore(t1)&lt;br /&gt;
        semaphore_V(ok2read);&lt;br /&gt;
    else&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Non appena lo scrittore rilascia il mutex, un nuovo scrittore chiede di leggere (e si addormenterà). Un lettore (lento) che era riuscito a entrare nel segmento startofread prima che lo scrittore entrasse in startofwrite, continua a leggere e risveglia uno dei nuovi lettori. Se i lettori continuano a richiedere di leggere continuamente, verranno addormentati e subito risvegliati. &lt;br /&gt;
&lt;br /&gt;
E' da considerarsi possibile? --[[User:GabrieleCalarota|GabrieleCalarota]] ([[User talk:GabrieleCalarota|talk]]) 19:11, 13 November 2016 (CET)&lt;/div&gt;</summary>
		<author><name>GabrieleCalarota</name></author>
	</entry>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=Zibaldone&amp;diff=1595</id>
		<title>Zibaldone</title>
		<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php?title=Zibaldone&amp;diff=1595"/>
		<updated>2016-11-13T18:11:14Z</updated>

		<summary type="html">&lt;p&gt;GabrieleCalarota: /* RW2bis */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== RW errato ==&lt;br /&gt;
Codice '''ERRATO''' dei lettori scrittori che dovrebbe non soffrire di problemi di starvation...&lt;br /&gt;
Esercizio: trovare gli errori.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
#include&amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include&amp;lt;stdint.h&amp;gt;&lt;br /&gt;
#include&amp;lt;pthread.h&amp;gt;&lt;br /&gt;
#include&amp;lt;semaphore.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define NREADER 3&lt;br /&gt;
#define NWRITER 3&lt;br /&gt;
semaphore mutex;&lt;br /&gt;
semaphore ok2read;&lt;br /&gt;
semaphore ok2write;&lt;br /&gt;
&lt;br /&gt;
int nr=0;&lt;br /&gt;
int nw=0;&lt;br /&gt;
int wr=0;&lt;br /&gt;
int ww=0;&lt;br /&gt;
int w_last;&lt;br /&gt;
&lt;br /&gt;
// (nw == 0 &amp;amp;&amp;amp; nr == 0) || (nr &amp;gt; 0 &amp;amp;&amp;amp; nw == 0) || nw == 1&lt;br /&gt;
// (nw == 0 &amp;amp;&amp;amp; nr &amp;gt;= 0) || nw == 1&lt;br /&gt;
&lt;br /&gt;
// this &amp;quot;baton&amp;quot; function has been left for reference only.&lt;br /&gt;
// code to implement &amp;quot;passing the baton&amp;quot; has been copied at the end of&lt;br /&gt;
// each ({start}|{end})({read}|{write}) function and reduced.&lt;br /&gt;
void baton(void) {&lt;br /&gt;
        if (nw == 0 &amp;amp;&amp;amp; nr == 0 &amp;amp;&amp;amp; ww &amp;gt; 0)&lt;br /&gt;
                semaphore_V(ok2write);&lt;br /&gt;
        else if (nw == 0 &amp;amp;&amp;amp; wr &amp;gt; 0 )&lt;br /&gt;
                semaphore_V(ok2read);&lt;br /&gt;
        else&lt;br /&gt;
                semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void startread(void) {&lt;br /&gt;
// &amp;lt;await nw == 0 -&amp;gt; nr++&amp;gt;&lt;br /&gt;
        semaphore_P(mutex);&lt;br /&gt;
        if (nw &amp;gt; 0 &amp;amp;&amp;amp; ww == 0) {&lt;br /&gt;
                wr++;&lt;br /&gt;
                semaphore_V(mutex);&lt;br /&gt;
                semaphore_P(ok2read);&lt;br /&gt;
                wr--;&lt;br /&gt;
        }&lt;br /&gt;
        nr++;&lt;br /&gt;
        w_last=0;&lt;br /&gt;
        printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, nr, nw, wr, ww);&lt;br /&gt;
        if (wr &amp;gt; 0 )&lt;br /&gt;
                semaphore_V(ok2read);&lt;br /&gt;
        else&lt;br /&gt;
                semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void endread(void) {&lt;br /&gt;
// &amp;lt;nr--&amp;gt;&lt;br /&gt;
        semaphore_P(mutex);&lt;br /&gt;
        nr--;&lt;br /&gt;
        printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, nr, nw, wr, ww);&lt;br /&gt;
        if (nr == 0 &amp;amp;&amp;amp; ww &amp;gt; 0)&lt;br /&gt;
                semaphore_V(ok2write);&lt;br /&gt;
        else&lt;br /&gt;
                semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void startwrite(void) {&lt;br /&gt;
// &amp;lt;await nw == 0 &amp;amp;&amp;amp; nr == 0 -&amp;gt; nw++&amp;gt;&lt;br /&gt;
        semaphore_P(mutex);&lt;br /&gt;
        if (nw &amp;gt; 0 || nr &amp;gt; 0) {&lt;br /&gt;
                ww++;&lt;br /&gt;
                semaphore_V(mutex);&lt;br /&gt;
                semaphore_P(ok2write);&lt;br /&gt;
                ww--;&lt;br /&gt;
        }&lt;br /&gt;
        nw++;&lt;br /&gt;
        w_last=1;&lt;br /&gt;
        printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, nr, nw, wr, ww);&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void endwrite(void) {&lt;br /&gt;
// &amp;lt;nw--&amp;gt;&lt;br /&gt;
        semaphore_P(mutex);&lt;br /&gt;
        nw--;&lt;br /&gt;
        printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, nr, nw, wr, ww);&lt;br /&gt;
        if (wr &amp;gt; 0 &amp;amp;&amp;amp; (ww == 0 || w_last))&lt;br /&gt;
                semaphore_V(ok2read);&lt;br /&gt;
        else if (ww &amp;gt; 0 &amp;amp;&amp;amp; (wr == 0 || !w_last))&lt;br /&gt;
                semaphore_V(ok2write);&lt;br /&gt;
        else&lt;br /&gt;
                semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void *reader(void *arg) {&lt;br /&gt;
        int i = (uintptr_t)arg;&lt;br /&gt;
        while (1) {&lt;br /&gt;
                //other code&lt;br /&gt;
                usleep(random() % 200000);&lt;br /&gt;
                startread();&lt;br /&gt;
                //read&lt;br /&gt;
                usleep(random() % 200000);&lt;br /&gt;
                endread();&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void *writer(void *arg) {&lt;br /&gt;
        int i = (uintptr_t)arg;&lt;br /&gt;
        while (1) {&lt;br /&gt;
                //other code&lt;br /&gt;
                usleep(random() % 200000);&lt;br /&gt;
                startwrite();&lt;br /&gt;
                //write&lt;br /&gt;
                usleep(random() % 200000);&lt;br /&gt;
                endwrite();&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//printf(&amp;quot;philo thinking: %d\n&amp;quot;,i);&lt;br /&gt;
/*while*/&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char *argv[]) {&lt;br /&gt;
        int i;&lt;br /&gt;
        pthread_t t;&lt;br /&gt;
        srandom(time(NULL));&lt;br /&gt;
        mutex=semaphore_create(1);&lt;br /&gt;
        ok2read=semaphore_create(0);&lt;br /&gt;
        ok2write=semaphore_create(0);&lt;br /&gt;
        for (i=0; i&amp;lt;NREADER; i++)&lt;br /&gt;
                pthread_create(&amp;amp;t, NULL, reader, (void *)(uintptr_t) i);&lt;br /&gt;
        for (i=0; i&amp;lt;NWRITER; i++)&lt;br /&gt;
                pthread_create(&amp;amp;t, NULL, writer, (void *)(uintptr_t) i);&lt;br /&gt;
        while(1)&lt;br /&gt;
                pause();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== RW di FedericoB ==&lt;br /&gt;
Propongo la seguente soluzione. Mi sembra che funzioni ma devo ancora capire perchè e documentarla bene. Ho provato prima a cercare il bug ma non ci sono riuscito. Ho quindi modificato il codice secondo ciò che mi sembrava sensato in base alle condizioni del problema. Ne possiamo parlare in aula oggi. --[[User:FedericoB|FedericoB]] ([[User talk:FedericoB|talk]]) 12:48, 11 November 2016 (CET)&lt;br /&gt;
Ho notato che l'errore non si manifesta più eliminando il controllo che ci siano scrittori in attesa quando un lettore vuole iniziare a scrivere. Non capisco come questo possa essere collegato al bug. --[[User:FedericoB|FedericoB]] ([[User talk:FedericoB|talk]]) 15:10, 11 November 2016 (CET)&lt;br /&gt;
&lt;br /&gt;
FedericoB, questa soluzione &amp;amp;egrave; quella con priorit&amp;amp;agrave; ai lettori, no? Se continuano ad arrivare lettori numberOfReaders non sar&amp;amp;agrave; mai zero e quindi gli scrittori non scriveranno mai. [[User:Renzo|Renzo]] ([[User talk:Renzo|talk]]) 10:34, 12 November 2016 (CET)&lt;br /&gt;
&lt;br /&gt;
SFIDA: ho trovato il modo di togliere la starvation aggiungendo 4 token (parole chiave, nomi di variabili, operatori, costanti) a questa soluzione di FedericoB. Chi trova la soluzione? [[User:Renzo|Renzo]] ([[User talk:Renzo|talk]]) 10:43, 12 November 2016 (CET) Ah! ho appena trovato una soluzione che prevede 2 soli token in pi&amp;amp;ugrave;! [[User:Renzo|Renzo]] ([[User talk:Renzo|talk]]) 10:47, 12 November 2016 (CET)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
#include&amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include&amp;lt;stdint.h&amp;gt;&lt;br /&gt;
#include&amp;lt;pthread.h&amp;gt;&lt;br /&gt;
#include&amp;lt;semaphore.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define NUMBER_OF_READERS 3&lt;br /&gt;
#define NUMBER_OF_WRITERS 3&lt;br /&gt;
semaphore mutex;&lt;br /&gt;
semaphore ok2read;&lt;br /&gt;
semaphore ok2write;&lt;br /&gt;
&lt;br /&gt;
int numberOfReaders=0;&lt;br /&gt;
int numberOfWriters=0;&lt;br /&gt;
int waitingReaders=0;&lt;br /&gt;
int waitingWriters=0;&lt;br /&gt;
&lt;br /&gt;
// (nw == 0 &amp;amp;&amp;amp; nr == 0) || (nr &amp;gt; 0 &amp;amp;&amp;amp; nw == 0) || nw == 1&lt;br /&gt;
// (nw == 0 &amp;amp;&amp;amp; nr &amp;gt;= 0) || nw == 1&lt;br /&gt;
&lt;br /&gt;
void startread(void) {&lt;br /&gt;
// &amp;lt;await nw == 0 -&amp;gt; nr++&amp;gt;&lt;br /&gt;
    semaphore_P(mutex);&lt;br /&gt;
    if (numberOfWriters &amp;gt; 0) {&lt;br /&gt;
        waitingReaders++;&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
        semaphore_P(ok2read);&lt;br /&gt;
        waitingReaders--;&lt;br /&gt;
    }&lt;br /&gt;
    numberOfReaders++;&lt;br /&gt;
    printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, numberOfReaders, numberOfWriters, waitingReaders, waitingWriters);&lt;br /&gt;
    if (waitingReaders &amp;gt; 0 )&lt;br /&gt;
        semaphore_V(ok2read);&lt;br /&gt;
    else&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void endread(void) {&lt;br /&gt;
// &amp;lt;nr--&amp;gt;&lt;br /&gt;
    semaphore_P(mutex);&lt;br /&gt;
    numberOfReaders--;&lt;br /&gt;
    printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, numberOfReaders, numberOfWriters, waitingReaders, waitingWriters);&lt;br /&gt;
    if (numberOfReaders == 0 &amp;amp;&amp;amp; waitingWriters &amp;gt; 0)&lt;br /&gt;
        semaphore_V(ok2write);&lt;br /&gt;
    else&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void startwrite(void) {&lt;br /&gt;
// &amp;lt;await nw == 0 &amp;amp;&amp;amp; nr == 0 -&amp;gt; nw++&amp;gt;&lt;br /&gt;
    semaphore_P(mutex);&lt;br /&gt;
    if (numberOfWriters &amp;gt; 0 || numberOfReaders &amp;gt; 0) {&lt;br /&gt;
        waitingWriters++;&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
        semaphore_P(ok2write);&lt;br /&gt;
        waitingWriters--;&lt;br /&gt;
    }&lt;br /&gt;
    numberOfWriters++;&lt;br /&gt;
    printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, numberOfReaders, numberOfWriters, waitingReaders, waitingWriters);&lt;br /&gt;
    semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void endwrite(void) {&lt;br /&gt;
// &amp;lt;nw--&amp;gt;&lt;br /&gt;
    semaphore_P(mutex);&lt;br /&gt;
    numberOfWriters--;&lt;br /&gt;
    printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, numberOfReaders, numberOfWriters, waitingReaders, waitingWriters);&lt;br /&gt;
    if (waitingReaders &amp;gt; 0)&lt;br /&gt;
        semaphore_V(ok2read);&lt;br /&gt;
    else if (waitingWriters &amp;gt; 0)&lt;br /&gt;
        semaphore_V(ok2write);&lt;br /&gt;
    else&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void *reader(void *arg) {&lt;br /&gt;
    int i = (uintptr_t)arg;&lt;br /&gt;
    while (1) {&lt;br /&gt;
        //other code&lt;br /&gt;
        usleep(random() % 200000);&lt;br /&gt;
        startread();&lt;br /&gt;
        //read&lt;br /&gt;
        usleep(random() % 200000);&lt;br /&gt;
        endread();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void *writer(void *arg) {&lt;br /&gt;
    int i = (uintptr_t)arg;&lt;br /&gt;
    while (1) {&lt;br /&gt;
        //other code&lt;br /&gt;
        usleep(random() % 200000);&lt;br /&gt;
        startwrite();&lt;br /&gt;
        //write&lt;br /&gt;
        usleep(random() % 200000);&lt;br /&gt;
        endwrite();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//printf(&amp;quot;philo thinking: %d\n&amp;quot;,i);&lt;br /&gt;
/*while*/&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char *argv[]) {&lt;br /&gt;
    int i;&lt;br /&gt;
    pthread_t t;&lt;br /&gt;
    srandom(time(NULL));&lt;br /&gt;
    mutex=semaphore_create(1);&lt;br /&gt;
    ok2read=semaphore_create(0);&lt;br /&gt;
    ok2write=semaphore_create(0);&lt;br /&gt;
    for (i=0; i&amp;lt;NUMBER_OF_READERS; i++)&lt;br /&gt;
        pthread_create(&amp;amp;t, NULL, reader, (void *)(uintptr_t) i);&lt;br /&gt;
    for (i=0; i&amp;lt;NUMBER_OF_WRITERS; i++)&lt;br /&gt;
        pthread_create(&amp;amp;t, NULL, writer, (void *)(uintptr_t) i);&lt;br /&gt;
    while(1)&lt;br /&gt;
        pause();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== RW2 ==&lt;br /&gt;
Buongiorno, guardando il codice visto a lezione mi sembra che cambiando la condizione del primo if nella startread() da &amp;quot;if (nw &amp;gt; 0 &amp;amp;&amp;amp; ww == 0)&amp;quot; a &amp;quot;if (nw &amp;gt; 0 || ww &amp;gt; 0)&amp;quot; la situazione migliori. In particolare con l'and tra quelle due condizioni si aveva che non veniva fatta la P sull'ok2read anche quando si aveva nw&amp;gt;0 (con ww!=0), cosa che invece dovrebbe fare. Lasciando il resto del codice uguale mi sembra che faccia quello che deve fare.. .&lt;br /&gt;
&lt;br /&gt;
Matteo.pincherle: Perch&amp;amp;eacute; non modifichi in programma di FedericoB, lo provi e pubblichi qui la patch? [[User:Renzo|Renzo]] ([[User talk:Renzo|talk]]) 10:42, 13 November 2016 (CET)&lt;br /&gt;
&lt;br /&gt;
== Patch ==&lt;br /&gt;
Così, se non sbaglio, quando c'è almeno uno scrittore in attesa non lascia entrare altri lettori. Fa esaurire la lettura dei presenti e poi lascia scrivere lo scrittore.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include&amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include&amp;lt;stdint.h&amp;gt;&lt;br /&gt;
#include&amp;lt;pthread.h&amp;gt;&lt;br /&gt;
#include&amp;lt;semaphore.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define NUMBER_OF_READERS 3&lt;br /&gt;
#define NUMBER_OF_WRITERS 3&lt;br /&gt;
semaphore mutex;&lt;br /&gt;
semaphore ok2read;&lt;br /&gt;
semaphore ok2write;&lt;br /&gt;
&lt;br /&gt;
int numberOfReaders=0;&lt;br /&gt;
int numberOfWriters=0;&lt;br /&gt;
int waitingReaders=0;&lt;br /&gt;
int waitingWriters=0;&lt;br /&gt;
int w_last;&lt;br /&gt;
&lt;br /&gt;
// (nw == 0 &amp;amp;&amp;amp; nr == 0) || (nr &amp;gt; 0 &amp;amp;&amp;amp; nw == 0) || nw == 1&lt;br /&gt;
// (nw == 0 &amp;amp;&amp;amp; nr &amp;gt;= 0) || nw == 1&lt;br /&gt;
&lt;br /&gt;
void startread(void) {&lt;br /&gt;
    // &amp;lt;await nw == 0 -&amp;gt; nr++&amp;gt;&lt;br /&gt;
    semaphore_P(mutex);&lt;br /&gt;
    if (numberOfWriters &amp;gt; 0 || waitingWriters&amp;gt;0) {&lt;br /&gt;
        waitingReaders++;&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
        semaphore_P(ok2read);&lt;br /&gt;
        waitingReaders--;&lt;br /&gt;
    }&lt;br /&gt;
    numberOfReaders++;&lt;br /&gt;
    w_last=0;&lt;br /&gt;
    printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, numberOfReaders, numberOfWriters, waitingReaders, waitingWriters);&lt;br /&gt;
    if (waitingReaders &amp;gt; 0 )&lt;br /&gt;
        semaphore_V(ok2read);&lt;br /&gt;
    else&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void endread(void) {&lt;br /&gt;
    // &amp;lt;nr--&amp;gt;&lt;br /&gt;
    semaphore_P(mutex);&lt;br /&gt;
    numberOfReaders--;&lt;br /&gt;
    printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, numberOfReaders, numberOfWriters, waitingReaders, waitingWriters);&lt;br /&gt;
    if (numberOfReaders == 0 &amp;amp;&amp;amp; waitingWriters &amp;gt; 0)&lt;br /&gt;
        semaphore_V(ok2write);&lt;br /&gt;
    else&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void startwrite(void) {&lt;br /&gt;
    // &amp;lt;await nw == 0 &amp;amp;&amp;amp; nr == 0 -&amp;gt; nw++&amp;gt;&lt;br /&gt;
    semaphore_P(mutex);&lt;br /&gt;
    if (numberOfWriters &amp;gt; 0 || numberOfReaders &amp;gt; 0) {&lt;br /&gt;
        waitingWriters++;&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
        semaphore_P(ok2write);&lt;br /&gt;
        waitingWriters--;&lt;br /&gt;
    }&lt;br /&gt;
    numberOfWriters++;&lt;br /&gt;
    w_last=1;&lt;br /&gt;
    printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, numberOfReaders, numberOfWriters, waitingReaders, waitingWriters);&lt;br /&gt;
    semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void endwrite(void) {&lt;br /&gt;
    // &amp;lt;nw--&amp;gt;&lt;br /&gt;
    semaphore_P(mutex);&lt;br /&gt;
    numberOfWriters--;&lt;br /&gt;
    printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, numberOfReaders, numberOfWriters, waitingReaders, waitingWriters);&lt;br /&gt;
    if (waitingReaders &amp;gt; 0 &amp;amp;&amp;amp; (waitingWriters==0 || w_last))&lt;br /&gt;
        semaphore_V(ok2read);&lt;br /&gt;
    else if (waitingWriters &amp;gt; 0 &amp;amp;&amp;amp; (waitingReaders==0 || !w_last))&lt;br /&gt;
        semaphore_V(ok2write);&lt;br /&gt;
    else&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void *reader(void *arg) {&lt;br /&gt;
    int i = (uintptr_t)arg;&lt;br /&gt;
    while (1) {&lt;br /&gt;
        //other code&lt;br /&gt;
        usleep(random() % 200000);&lt;br /&gt;
        startread();&lt;br /&gt;
        //read&lt;br /&gt;
        usleep(random() % 200000);&lt;br /&gt;
        endread();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void *writer(void *arg) {&lt;br /&gt;
    int i = (uintptr_t)arg;&lt;br /&gt;
    while (1) {&lt;br /&gt;
        //other code&lt;br /&gt;
        usleep(random() % 200000);&lt;br /&gt;
        startwrite();&lt;br /&gt;
        //write&lt;br /&gt;
        usleep(random() % 200000);&lt;br /&gt;
        endwrite();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char *argv[]) {&lt;br /&gt;
    int i;&lt;br /&gt;
    pthread_t t;&lt;br /&gt;
    srandom(time(NULL));&lt;br /&gt;
    mutex=semaphore_create(1);&lt;br /&gt;
    ok2read=semaphore_create(0);&lt;br /&gt;
    ok2write=semaphore_create(0);&lt;br /&gt;
    for (i=0; i&amp;lt;NUMBER_OF_READERS; i++)&lt;br /&gt;
        pthread_create(&amp;amp;t, NULL, reader, (void *)(uintptr_t) i);&lt;br /&gt;
    for (i=0; i&amp;lt;NUMBER_OF_WRITERS; i++)&lt;br /&gt;
        pthread_create(&amp;amp;t, NULL, writer, (void *)(uintptr_t) i);&lt;br /&gt;
    while(1)&lt;br /&gt;
        pause();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
wlast non serve pi&amp;amp;ugrave;... [[User:Renzo|Renzo]] ([[User talk:Renzo|talk]]) 17:52, 13 November 2016 (CET)&lt;br /&gt;
&lt;br /&gt;
== RW2bis ==&lt;br /&gt;
Tecnicamente nella tua soluzione se i lettori sono &amp;quot;molto veloci&amp;quot; e non vanno mai a 0, lo scrittore non inizierà mai a scrivere.&lt;br /&gt;
&lt;br /&gt;
Cioè: Uno scrittore viene svegliato da ok2write solo se passa la condizione &lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
[..] &lt;br /&gt;
if (numberofReaders == 0 &amp;amp;&amp;amp; waitingWriters &amp;gt;0) &lt;br /&gt;
     semaphore_V(ok2write);&lt;br /&gt;
[..]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; --[[User:GabrieleCalarota|GabrieleCalarota]] ([[User talk:GabrieleCalarota|talk]]) 17:46, 13 November 2016 (CET)&lt;br /&gt;
&lt;br /&gt;
Non direi perche' nella startread se:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
    if (numberOfWriters &amp;gt; 0 || waitingWriters&amp;gt;0) &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
i lettori si bloccano. Quindi se c'e' almeno uno scrittore in attesa i lettori non entrano (e quindi prima o poi terminano e lasciano il posto ad uno scrittore).&lt;br /&gt;
[[User:Renzo|Renzo]] ([[User talk:Renzo|talk]]) 17:57, 13 November 2016 (CET)&lt;br /&gt;
&lt;br /&gt;
 Ho pensato al caso limite seguente:&lt;br /&gt;
&lt;br /&gt;
 Supponiamo che ci siano dei lettori che stanno leggendo e ad un certo punto uno scrittore chiede di scrivere.&lt;br /&gt;
 &amp;lt;syntaxhighlight lang=C&amp;gt;         &lt;br /&gt;
       void startread(void) {&lt;br /&gt;
    // &amp;lt;await nw == 0 -&amp;gt; nr++&amp;gt;&lt;br /&gt;
    semaphore_P(mutex);&lt;br /&gt;
    if (numberOfWriters &amp;gt; 0 || waitingWriters&amp;gt;0) {&lt;br /&gt;
        waitingReaders++;   //Nuovo scrittore (t1)&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
        semaphore_P(ok2read);&lt;br /&gt;
        waitingReaders--;&lt;br /&gt;
    }&lt;br /&gt;
    numberOfReaders++;&lt;br /&gt;
    w_last=0;&lt;br /&gt;
    printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, numberOfReaders, numberOfWriters, waitingReaders, waitingWriters);&lt;br /&gt;
   if (waitingReaders &amp;gt; 0 )   //Vecchio scrittore(t1)&lt;br /&gt;
        semaphore_V(ok2read);&lt;br /&gt;
    else&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Non appena lo scrittore rilascia il mutex, un nuovo scrittore chiede di leggere (e si addormenterà). Un lettore (lento) che era riuscito a entrare nel segmento startofread prima che lo scrittore entrasse in startofwrite, continua a leggere e risveglia uno dei nuovi lettori. Se i lettori continuano a richiedere di leggere continuamente, verranno addormentati e subito risvegliati. &lt;br /&gt;
&lt;br /&gt;
E' da considerarsi possibile? --[[User:GabrieleCalarota|GabrieleCalarota]] ([[User talk:GabrieleCalarota|talk]]) 19:11, 13 November 2016 (CET)&lt;/div&gt;</summary>
		<author><name>GabrieleCalarota</name></author>
	</entry>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=Zibaldone&amp;diff=1594</id>
		<title>Zibaldone</title>
		<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php?title=Zibaldone&amp;diff=1594"/>
		<updated>2016-11-13T17:27:52Z</updated>

		<summary type="html">&lt;p&gt;GabrieleCalarota: /* RW2bis */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== RW errato ==&lt;br /&gt;
Codice '''ERRATO''' dei lettori scrittori che dovrebbe non soffrire di problemi di starvation...&lt;br /&gt;
Esercizio: trovare gli errori.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
#include&amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include&amp;lt;stdint.h&amp;gt;&lt;br /&gt;
#include&amp;lt;pthread.h&amp;gt;&lt;br /&gt;
#include&amp;lt;semaphore.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define NREADER 3&lt;br /&gt;
#define NWRITER 3&lt;br /&gt;
semaphore mutex;&lt;br /&gt;
semaphore ok2read;&lt;br /&gt;
semaphore ok2write;&lt;br /&gt;
&lt;br /&gt;
int nr=0;&lt;br /&gt;
int nw=0;&lt;br /&gt;
int wr=0;&lt;br /&gt;
int ww=0;&lt;br /&gt;
int w_last;&lt;br /&gt;
&lt;br /&gt;
// (nw == 0 &amp;amp;&amp;amp; nr == 0) || (nr &amp;gt; 0 &amp;amp;&amp;amp; nw == 0) || nw == 1&lt;br /&gt;
// (nw == 0 &amp;amp;&amp;amp; nr &amp;gt;= 0) || nw == 1&lt;br /&gt;
&lt;br /&gt;
// this &amp;quot;baton&amp;quot; function has been left for reference only.&lt;br /&gt;
// code to implement &amp;quot;passing the baton&amp;quot; has been copied at the end of&lt;br /&gt;
// each ({start}|{end})({read}|{write}) function and reduced.&lt;br /&gt;
void baton(void) {&lt;br /&gt;
        if (nw == 0 &amp;amp;&amp;amp; nr == 0 &amp;amp;&amp;amp; ww &amp;gt; 0)&lt;br /&gt;
                semaphore_V(ok2write);&lt;br /&gt;
        else if (nw == 0 &amp;amp;&amp;amp; wr &amp;gt; 0 )&lt;br /&gt;
                semaphore_V(ok2read);&lt;br /&gt;
        else&lt;br /&gt;
                semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void startread(void) {&lt;br /&gt;
// &amp;lt;await nw == 0 -&amp;gt; nr++&amp;gt;&lt;br /&gt;
        semaphore_P(mutex);&lt;br /&gt;
        if (nw &amp;gt; 0 &amp;amp;&amp;amp; ww == 0) {&lt;br /&gt;
                wr++;&lt;br /&gt;
                semaphore_V(mutex);&lt;br /&gt;
                semaphore_P(ok2read);&lt;br /&gt;
                wr--;&lt;br /&gt;
        }&lt;br /&gt;
        nr++;&lt;br /&gt;
        w_last=0;&lt;br /&gt;
        printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, nr, nw, wr, ww);&lt;br /&gt;
        if (wr &amp;gt; 0 )&lt;br /&gt;
                semaphore_V(ok2read);&lt;br /&gt;
        else&lt;br /&gt;
                semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void endread(void) {&lt;br /&gt;
// &amp;lt;nr--&amp;gt;&lt;br /&gt;
        semaphore_P(mutex);&lt;br /&gt;
        nr--;&lt;br /&gt;
        printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, nr, nw, wr, ww);&lt;br /&gt;
        if (nr == 0 &amp;amp;&amp;amp; ww &amp;gt; 0)&lt;br /&gt;
                semaphore_V(ok2write);&lt;br /&gt;
        else&lt;br /&gt;
                semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void startwrite(void) {&lt;br /&gt;
// &amp;lt;await nw == 0 &amp;amp;&amp;amp; nr == 0 -&amp;gt; nw++&amp;gt;&lt;br /&gt;
        semaphore_P(mutex);&lt;br /&gt;
        if (nw &amp;gt; 0 || nr &amp;gt; 0) {&lt;br /&gt;
                ww++;&lt;br /&gt;
                semaphore_V(mutex);&lt;br /&gt;
                semaphore_P(ok2write);&lt;br /&gt;
                ww--;&lt;br /&gt;
        }&lt;br /&gt;
        nw++;&lt;br /&gt;
        w_last=1;&lt;br /&gt;
        printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, nr, nw, wr, ww);&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void endwrite(void) {&lt;br /&gt;
// &amp;lt;nw--&amp;gt;&lt;br /&gt;
        semaphore_P(mutex);&lt;br /&gt;
        nw--;&lt;br /&gt;
        printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, nr, nw, wr, ww);&lt;br /&gt;
        if (wr &amp;gt; 0 &amp;amp;&amp;amp; (ww == 0 || w_last))&lt;br /&gt;
                semaphore_V(ok2read);&lt;br /&gt;
        else if (ww &amp;gt; 0 &amp;amp;&amp;amp; (wr == 0 || !w_last))&lt;br /&gt;
                semaphore_V(ok2write);&lt;br /&gt;
        else&lt;br /&gt;
                semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void *reader(void *arg) {&lt;br /&gt;
        int i = (uintptr_t)arg;&lt;br /&gt;
        while (1) {&lt;br /&gt;
                //other code&lt;br /&gt;
                usleep(random() % 200000);&lt;br /&gt;
                startread();&lt;br /&gt;
                //read&lt;br /&gt;
                usleep(random() % 200000);&lt;br /&gt;
                endread();&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void *writer(void *arg) {&lt;br /&gt;
        int i = (uintptr_t)arg;&lt;br /&gt;
        while (1) {&lt;br /&gt;
                //other code&lt;br /&gt;
                usleep(random() % 200000);&lt;br /&gt;
                startwrite();&lt;br /&gt;
                //write&lt;br /&gt;
                usleep(random() % 200000);&lt;br /&gt;
                endwrite();&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//printf(&amp;quot;philo thinking: %d\n&amp;quot;,i);&lt;br /&gt;
/*while*/&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char *argv[]) {&lt;br /&gt;
        int i;&lt;br /&gt;
        pthread_t t;&lt;br /&gt;
        srandom(time(NULL));&lt;br /&gt;
        mutex=semaphore_create(1);&lt;br /&gt;
        ok2read=semaphore_create(0);&lt;br /&gt;
        ok2write=semaphore_create(0);&lt;br /&gt;
        for (i=0; i&amp;lt;NREADER; i++)&lt;br /&gt;
                pthread_create(&amp;amp;t, NULL, reader, (void *)(uintptr_t) i);&lt;br /&gt;
        for (i=0; i&amp;lt;NWRITER; i++)&lt;br /&gt;
                pthread_create(&amp;amp;t, NULL, writer, (void *)(uintptr_t) i);&lt;br /&gt;
        while(1)&lt;br /&gt;
                pause();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== RW di FedericoB ==&lt;br /&gt;
Propongo la seguente soluzione. Mi sembra che funzioni ma devo ancora capire perchè e documentarla bene. Ho provato prima a cercare il bug ma non ci sono riuscito. Ho quindi modificato il codice secondo ciò che mi sembrava sensato in base alle condizioni del problema. Ne possiamo parlare in aula oggi. --[[User:FedericoB|FedericoB]] ([[User talk:FedericoB|talk]]) 12:48, 11 November 2016 (CET)&lt;br /&gt;
Ho notato che l'errore non si manifesta più eliminando il controllo che ci siano scrittori in attesa quando un lettore vuole iniziare a scrivere. Non capisco come questo possa essere collegato al bug. --[[User:FedericoB|FedericoB]] ([[User talk:FedericoB|talk]]) 15:10, 11 November 2016 (CET)&lt;br /&gt;
&lt;br /&gt;
FedericoB, questa soluzione &amp;amp;egrave; quella con priorit&amp;amp;agrave; ai lettori, no? Se continuano ad arrivare lettori numberOfReaders non sar&amp;amp;agrave; mai zero e quindi gli scrittori non scriveranno mai. [[User:Renzo|Renzo]] ([[User talk:Renzo|talk]]) 10:34, 12 November 2016 (CET)&lt;br /&gt;
&lt;br /&gt;
SFIDA: ho trovato il modo di togliere la starvation aggiungendo 4 token (parole chiave, nomi di variabili, operatori, costanti) a questa soluzione di FedericoB. Chi trova la soluzione? [[User:Renzo|Renzo]] ([[User talk:Renzo|talk]]) 10:43, 12 November 2016 (CET) Ah! ho appena trovato una soluzione che prevede 2 soli token in pi&amp;amp;ugrave;! [[User:Renzo|Renzo]] ([[User talk:Renzo|talk]]) 10:47, 12 November 2016 (CET)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
#include&amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include&amp;lt;stdint.h&amp;gt;&lt;br /&gt;
#include&amp;lt;pthread.h&amp;gt;&lt;br /&gt;
#include&amp;lt;semaphore.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define NUMBER_OF_READERS 3&lt;br /&gt;
#define NUMBER_OF_WRITERS 3&lt;br /&gt;
semaphore mutex;&lt;br /&gt;
semaphore ok2read;&lt;br /&gt;
semaphore ok2write;&lt;br /&gt;
&lt;br /&gt;
int numberOfReaders=0;&lt;br /&gt;
int numberOfWriters=0;&lt;br /&gt;
int waitingReaders=0;&lt;br /&gt;
int waitingWriters=0;&lt;br /&gt;
&lt;br /&gt;
// (nw == 0 &amp;amp;&amp;amp; nr == 0) || (nr &amp;gt; 0 &amp;amp;&amp;amp; nw == 0) || nw == 1&lt;br /&gt;
// (nw == 0 &amp;amp;&amp;amp; nr &amp;gt;= 0) || nw == 1&lt;br /&gt;
&lt;br /&gt;
void startread(void) {&lt;br /&gt;
// &amp;lt;await nw == 0 -&amp;gt; nr++&amp;gt;&lt;br /&gt;
    semaphore_P(mutex);&lt;br /&gt;
    if (numberOfWriters &amp;gt; 0) {&lt;br /&gt;
        waitingReaders++;&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
        semaphore_P(ok2read);&lt;br /&gt;
        waitingReaders--;&lt;br /&gt;
    }&lt;br /&gt;
    numberOfReaders++;&lt;br /&gt;
    printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, numberOfReaders, numberOfWriters, waitingReaders, waitingWriters);&lt;br /&gt;
    if (waitingReaders &amp;gt; 0 )&lt;br /&gt;
        semaphore_V(ok2read);&lt;br /&gt;
    else&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void endread(void) {&lt;br /&gt;
// &amp;lt;nr--&amp;gt;&lt;br /&gt;
    semaphore_P(mutex);&lt;br /&gt;
    numberOfReaders--;&lt;br /&gt;
    printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, numberOfReaders, numberOfWriters, waitingReaders, waitingWriters);&lt;br /&gt;
    if (numberOfReaders == 0 &amp;amp;&amp;amp; waitingWriters &amp;gt; 0)&lt;br /&gt;
        semaphore_V(ok2write);&lt;br /&gt;
    else&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void startwrite(void) {&lt;br /&gt;
// &amp;lt;await nw == 0 &amp;amp;&amp;amp; nr == 0 -&amp;gt; nw++&amp;gt;&lt;br /&gt;
    semaphore_P(mutex);&lt;br /&gt;
    if (numberOfWriters &amp;gt; 0 || numberOfReaders &amp;gt; 0) {&lt;br /&gt;
        waitingWriters++;&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
        semaphore_P(ok2write);&lt;br /&gt;
        waitingWriters--;&lt;br /&gt;
    }&lt;br /&gt;
    numberOfWriters++;&lt;br /&gt;
    printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, numberOfReaders, numberOfWriters, waitingReaders, waitingWriters);&lt;br /&gt;
    semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void endwrite(void) {&lt;br /&gt;
// &amp;lt;nw--&amp;gt;&lt;br /&gt;
    semaphore_P(mutex);&lt;br /&gt;
    numberOfWriters--;&lt;br /&gt;
    printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, numberOfReaders, numberOfWriters, waitingReaders, waitingWriters);&lt;br /&gt;
    if (waitingReaders &amp;gt; 0)&lt;br /&gt;
        semaphore_V(ok2read);&lt;br /&gt;
    else if (waitingWriters &amp;gt; 0)&lt;br /&gt;
        semaphore_V(ok2write);&lt;br /&gt;
    else&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void *reader(void *arg) {&lt;br /&gt;
    int i = (uintptr_t)arg;&lt;br /&gt;
    while (1) {&lt;br /&gt;
        //other code&lt;br /&gt;
        usleep(random() % 200000);&lt;br /&gt;
        startread();&lt;br /&gt;
        //read&lt;br /&gt;
        usleep(random() % 200000);&lt;br /&gt;
        endread();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void *writer(void *arg) {&lt;br /&gt;
    int i = (uintptr_t)arg;&lt;br /&gt;
    while (1) {&lt;br /&gt;
        //other code&lt;br /&gt;
        usleep(random() % 200000);&lt;br /&gt;
        startwrite();&lt;br /&gt;
        //write&lt;br /&gt;
        usleep(random() % 200000);&lt;br /&gt;
        endwrite();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//printf(&amp;quot;philo thinking: %d\n&amp;quot;,i);&lt;br /&gt;
/*while*/&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char *argv[]) {&lt;br /&gt;
    int i;&lt;br /&gt;
    pthread_t t;&lt;br /&gt;
    srandom(time(NULL));&lt;br /&gt;
    mutex=semaphore_create(1);&lt;br /&gt;
    ok2read=semaphore_create(0);&lt;br /&gt;
    ok2write=semaphore_create(0);&lt;br /&gt;
    for (i=0; i&amp;lt;NUMBER_OF_READERS; i++)&lt;br /&gt;
        pthread_create(&amp;amp;t, NULL, reader, (void *)(uintptr_t) i);&lt;br /&gt;
    for (i=0; i&amp;lt;NUMBER_OF_WRITERS; i++)&lt;br /&gt;
        pthread_create(&amp;amp;t, NULL, writer, (void *)(uintptr_t) i);&lt;br /&gt;
    while(1)&lt;br /&gt;
        pause();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== RW2 ==&lt;br /&gt;
Buongiorno, guardando il codice visto a lezione mi sembra che cambiando la condizione del primo if nella startread() da &amp;quot;if (nw &amp;gt; 0 &amp;amp;&amp;amp; ww == 0)&amp;quot; a &amp;quot;if (nw &amp;gt; 0 || ww &amp;gt; 0)&amp;quot; la situazione migliori. In particolare con l'and tra quelle due condizioni si aveva che non veniva fatta la P sull'ok2read anche quando si aveva nw&amp;gt;0 (con ww!=0), cosa che invece dovrebbe fare. Lasciando il resto del codice uguale mi sembra che faccia quello che deve fare.. .&lt;br /&gt;
&lt;br /&gt;
Matteo.pincherle: Perch&amp;amp;eacute; non modifichi in programma di FedericoB, lo provi e pubblichi qui la patch? [[User:Renzo|Renzo]] ([[User talk:Renzo|talk]]) 10:42, 13 November 2016 (CET)&lt;br /&gt;
&lt;br /&gt;
== Patch ==&lt;br /&gt;
Così, se non sbaglio, quando c'è almeno uno scrittore in attesa non lascia entrare altri lettori. Fa esaurire la lettura dei presenti e poi lascia scrivere lo scrittore.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include&amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include&amp;lt;stdint.h&amp;gt;&lt;br /&gt;
#include&amp;lt;pthread.h&amp;gt;&lt;br /&gt;
#include&amp;lt;semaphore.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define NUMBER_OF_READERS 3&lt;br /&gt;
#define NUMBER_OF_WRITERS 3&lt;br /&gt;
semaphore mutex;&lt;br /&gt;
semaphore ok2read;&lt;br /&gt;
semaphore ok2write;&lt;br /&gt;
&lt;br /&gt;
int numberOfReaders=0;&lt;br /&gt;
int numberOfWriters=0;&lt;br /&gt;
int waitingReaders=0;&lt;br /&gt;
int waitingWriters=0;&lt;br /&gt;
int w_last;&lt;br /&gt;
&lt;br /&gt;
// (nw == 0 &amp;amp;&amp;amp; nr == 0) || (nr &amp;gt; 0 &amp;amp;&amp;amp; nw == 0) || nw == 1&lt;br /&gt;
// (nw == 0 &amp;amp;&amp;amp; nr &amp;gt;= 0) || nw == 1&lt;br /&gt;
&lt;br /&gt;
void startread(void) {&lt;br /&gt;
    // &amp;lt;await nw == 0 -&amp;gt; nr++&amp;gt;&lt;br /&gt;
    semaphore_P(mutex);&lt;br /&gt;
    if (numberOfWriters &amp;gt; 0 || waitingWriters&amp;gt;0) {&lt;br /&gt;
        waitingReaders++;&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
        semaphore_P(ok2read);&lt;br /&gt;
        waitingReaders--;&lt;br /&gt;
    }&lt;br /&gt;
    numberOfReaders++;&lt;br /&gt;
    w_last=0;&lt;br /&gt;
    printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, numberOfReaders, numberOfWriters, waitingReaders, waitingWriters);&lt;br /&gt;
    if (waitingReaders &amp;gt; 0 )&lt;br /&gt;
        semaphore_V(ok2read);&lt;br /&gt;
    else&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void endread(void) {&lt;br /&gt;
    // &amp;lt;nr--&amp;gt;&lt;br /&gt;
    semaphore_P(mutex);&lt;br /&gt;
    numberOfReaders--;&lt;br /&gt;
    printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, numberOfReaders, numberOfWriters, waitingReaders, waitingWriters);&lt;br /&gt;
    if (numberOfReaders == 0 &amp;amp;&amp;amp; waitingWriters &amp;gt; 0)&lt;br /&gt;
        semaphore_V(ok2write);&lt;br /&gt;
    else&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void startwrite(void) {&lt;br /&gt;
    // &amp;lt;await nw == 0 &amp;amp;&amp;amp; nr == 0 -&amp;gt; nw++&amp;gt;&lt;br /&gt;
    semaphore_P(mutex);&lt;br /&gt;
    if (numberOfWriters &amp;gt; 0 || numberOfReaders &amp;gt; 0) {&lt;br /&gt;
        waitingWriters++;&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
        semaphore_P(ok2write);&lt;br /&gt;
        waitingWriters--;&lt;br /&gt;
    }&lt;br /&gt;
    numberOfWriters++;&lt;br /&gt;
    w_last=1;&lt;br /&gt;
    printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, numberOfReaders, numberOfWriters, waitingReaders, waitingWriters);&lt;br /&gt;
    semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void endwrite(void) {&lt;br /&gt;
    // &amp;lt;nw--&amp;gt;&lt;br /&gt;
    semaphore_P(mutex);&lt;br /&gt;
    numberOfWriters--;&lt;br /&gt;
    printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, numberOfReaders, numberOfWriters, waitingReaders, waitingWriters);&lt;br /&gt;
    if (waitingReaders &amp;gt; 0 &amp;amp;&amp;amp; (waitingWriters==0 || w_last))&lt;br /&gt;
        semaphore_V(ok2read);&lt;br /&gt;
    else if (waitingWriters &amp;gt; 0 &amp;amp;&amp;amp; (waitingReaders==0 || !w_last))&lt;br /&gt;
        semaphore_V(ok2write);&lt;br /&gt;
    else&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void *reader(void *arg) {&lt;br /&gt;
    int i = (uintptr_t)arg;&lt;br /&gt;
    while (1) {&lt;br /&gt;
        //other code&lt;br /&gt;
        usleep(random() % 200000);&lt;br /&gt;
        startread();&lt;br /&gt;
        //read&lt;br /&gt;
        usleep(random() % 200000);&lt;br /&gt;
        endread();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void *writer(void *arg) {&lt;br /&gt;
    int i = (uintptr_t)arg;&lt;br /&gt;
    while (1) {&lt;br /&gt;
        //other code&lt;br /&gt;
        usleep(random() % 200000);&lt;br /&gt;
        startwrite();&lt;br /&gt;
        //write&lt;br /&gt;
        usleep(random() % 200000);&lt;br /&gt;
        endwrite();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char *argv[]) {&lt;br /&gt;
    int i;&lt;br /&gt;
    pthread_t t;&lt;br /&gt;
    srandom(time(NULL));&lt;br /&gt;
    mutex=semaphore_create(1);&lt;br /&gt;
    ok2read=semaphore_create(0);&lt;br /&gt;
    ok2write=semaphore_create(0);&lt;br /&gt;
    for (i=0; i&amp;lt;NUMBER_OF_READERS; i++)&lt;br /&gt;
        pthread_create(&amp;amp;t, NULL, reader, (void *)(uintptr_t) i);&lt;br /&gt;
    for (i=0; i&amp;lt;NUMBER_OF_WRITERS; i++)&lt;br /&gt;
        pthread_create(&amp;amp;t, NULL, writer, (void *)(uintptr_t) i);&lt;br /&gt;
    while(1)&lt;br /&gt;
        pause();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
wlast non serve pi&amp;amp;ugrave;... [[User:Renzo|Renzo]] ([[User talk:Renzo|talk]]) 17:52, 13 November 2016 (CET)&lt;br /&gt;
&lt;br /&gt;
== RW2bis ==&lt;br /&gt;
Tecnicamente nella tua soluzione se i lettori sono &amp;quot;molto veloci&amp;quot; e non vanno mai a 0, lo scrittore non inizierà mai a scrivere.&lt;br /&gt;
&lt;br /&gt;
Cioè: Uno scrittore viene svegliato da ok2write solo se passa la condizione &lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
[..] &lt;br /&gt;
if (numberofReaders == 0 &amp;amp;&amp;amp; waitingWriters &amp;gt;0) &lt;br /&gt;
     semaphore_V(ok2write);&lt;br /&gt;
[..]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; --[[User:GabrieleCalarota|GabrieleCalarota]] ([[User talk:GabrieleCalarota|talk]]) 17:46, 13 November 2016 (CET)&lt;br /&gt;
&lt;br /&gt;
Non direi perche' nella startread se:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
    if (numberOfWriters &amp;gt; 0 || waitingWriters&amp;gt;0) &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
i lettori si bloccano. Quindi se c'e' almeno uno scrittore in attesa i lettori non entrano (e quindi prima o poi terminano e lasciano il posto ad uno scrittore).&lt;br /&gt;
[[User:Renzo|Renzo]] ([[User talk:Renzo|talk]]) 17:57, 13 November 2016 (CET)&lt;/div&gt;</summary>
		<author><name>GabrieleCalarota</name></author>
	</entry>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=Zibaldone&amp;diff=1593</id>
		<title>Zibaldone</title>
		<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php?title=Zibaldone&amp;diff=1593"/>
		<updated>2016-11-13T17:27:31Z</updated>

		<summary type="html">&lt;p&gt;GabrieleCalarota: /* RW2bis */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== RW errato ==&lt;br /&gt;
Codice '''ERRATO''' dei lettori scrittori che dovrebbe non soffrire di problemi di starvation...&lt;br /&gt;
Esercizio: trovare gli errori.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
#include&amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include&amp;lt;stdint.h&amp;gt;&lt;br /&gt;
#include&amp;lt;pthread.h&amp;gt;&lt;br /&gt;
#include&amp;lt;semaphore.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define NREADER 3&lt;br /&gt;
#define NWRITER 3&lt;br /&gt;
semaphore mutex;&lt;br /&gt;
semaphore ok2read;&lt;br /&gt;
semaphore ok2write;&lt;br /&gt;
&lt;br /&gt;
int nr=0;&lt;br /&gt;
int nw=0;&lt;br /&gt;
int wr=0;&lt;br /&gt;
int ww=0;&lt;br /&gt;
int w_last;&lt;br /&gt;
&lt;br /&gt;
// (nw == 0 &amp;amp;&amp;amp; nr == 0) || (nr &amp;gt; 0 &amp;amp;&amp;amp; nw == 0) || nw == 1&lt;br /&gt;
// (nw == 0 &amp;amp;&amp;amp; nr &amp;gt;= 0) || nw == 1&lt;br /&gt;
&lt;br /&gt;
// this &amp;quot;baton&amp;quot; function has been left for reference only.&lt;br /&gt;
// code to implement &amp;quot;passing the baton&amp;quot; has been copied at the end of&lt;br /&gt;
// each ({start}|{end})({read}|{write}) function and reduced.&lt;br /&gt;
void baton(void) {&lt;br /&gt;
        if (nw == 0 &amp;amp;&amp;amp; nr == 0 &amp;amp;&amp;amp; ww &amp;gt; 0)&lt;br /&gt;
                semaphore_V(ok2write);&lt;br /&gt;
        else if (nw == 0 &amp;amp;&amp;amp; wr &amp;gt; 0 )&lt;br /&gt;
                semaphore_V(ok2read);&lt;br /&gt;
        else&lt;br /&gt;
                semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void startread(void) {&lt;br /&gt;
// &amp;lt;await nw == 0 -&amp;gt; nr++&amp;gt;&lt;br /&gt;
        semaphore_P(mutex);&lt;br /&gt;
        if (nw &amp;gt; 0 &amp;amp;&amp;amp; ww == 0) {&lt;br /&gt;
                wr++;&lt;br /&gt;
                semaphore_V(mutex);&lt;br /&gt;
                semaphore_P(ok2read);&lt;br /&gt;
                wr--;&lt;br /&gt;
        }&lt;br /&gt;
        nr++;&lt;br /&gt;
        w_last=0;&lt;br /&gt;
        printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, nr, nw, wr, ww);&lt;br /&gt;
        if (wr &amp;gt; 0 )&lt;br /&gt;
                semaphore_V(ok2read);&lt;br /&gt;
        else&lt;br /&gt;
                semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void endread(void) {&lt;br /&gt;
// &amp;lt;nr--&amp;gt;&lt;br /&gt;
        semaphore_P(mutex);&lt;br /&gt;
        nr--;&lt;br /&gt;
        printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, nr, nw, wr, ww);&lt;br /&gt;
        if (nr == 0 &amp;amp;&amp;amp; ww &amp;gt; 0)&lt;br /&gt;
                semaphore_V(ok2write);&lt;br /&gt;
        else&lt;br /&gt;
                semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void startwrite(void) {&lt;br /&gt;
// &amp;lt;await nw == 0 &amp;amp;&amp;amp; nr == 0 -&amp;gt; nw++&amp;gt;&lt;br /&gt;
        semaphore_P(mutex);&lt;br /&gt;
        if (nw &amp;gt; 0 || nr &amp;gt; 0) {&lt;br /&gt;
                ww++;&lt;br /&gt;
                semaphore_V(mutex);&lt;br /&gt;
                semaphore_P(ok2write);&lt;br /&gt;
                ww--;&lt;br /&gt;
        }&lt;br /&gt;
        nw++;&lt;br /&gt;
        w_last=1;&lt;br /&gt;
        printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, nr, nw, wr, ww);&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void endwrite(void) {&lt;br /&gt;
// &amp;lt;nw--&amp;gt;&lt;br /&gt;
        semaphore_P(mutex);&lt;br /&gt;
        nw--;&lt;br /&gt;
        printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, nr, nw, wr, ww);&lt;br /&gt;
        if (wr &amp;gt; 0 &amp;amp;&amp;amp; (ww == 0 || w_last))&lt;br /&gt;
                semaphore_V(ok2read);&lt;br /&gt;
        else if (ww &amp;gt; 0 &amp;amp;&amp;amp; (wr == 0 || !w_last))&lt;br /&gt;
                semaphore_V(ok2write);&lt;br /&gt;
        else&lt;br /&gt;
                semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void *reader(void *arg) {&lt;br /&gt;
        int i = (uintptr_t)arg;&lt;br /&gt;
        while (1) {&lt;br /&gt;
                //other code&lt;br /&gt;
                usleep(random() % 200000);&lt;br /&gt;
                startread();&lt;br /&gt;
                //read&lt;br /&gt;
                usleep(random() % 200000);&lt;br /&gt;
                endread();&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void *writer(void *arg) {&lt;br /&gt;
        int i = (uintptr_t)arg;&lt;br /&gt;
        while (1) {&lt;br /&gt;
                //other code&lt;br /&gt;
                usleep(random() % 200000);&lt;br /&gt;
                startwrite();&lt;br /&gt;
                //write&lt;br /&gt;
                usleep(random() % 200000);&lt;br /&gt;
                endwrite();&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//printf(&amp;quot;philo thinking: %d\n&amp;quot;,i);&lt;br /&gt;
/*while*/&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char *argv[]) {&lt;br /&gt;
        int i;&lt;br /&gt;
        pthread_t t;&lt;br /&gt;
        srandom(time(NULL));&lt;br /&gt;
        mutex=semaphore_create(1);&lt;br /&gt;
        ok2read=semaphore_create(0);&lt;br /&gt;
        ok2write=semaphore_create(0);&lt;br /&gt;
        for (i=0; i&amp;lt;NREADER; i++)&lt;br /&gt;
                pthread_create(&amp;amp;t, NULL, reader, (void *)(uintptr_t) i);&lt;br /&gt;
        for (i=0; i&amp;lt;NWRITER; i++)&lt;br /&gt;
                pthread_create(&amp;amp;t, NULL, writer, (void *)(uintptr_t) i);&lt;br /&gt;
        while(1)&lt;br /&gt;
                pause();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== RW di FedericoB ==&lt;br /&gt;
Propongo la seguente soluzione. Mi sembra che funzioni ma devo ancora capire perchè e documentarla bene. Ho provato prima a cercare il bug ma non ci sono riuscito. Ho quindi modificato il codice secondo ciò che mi sembrava sensato in base alle condizioni del problema. Ne possiamo parlare in aula oggi. --[[User:FedericoB|FedericoB]] ([[User talk:FedericoB|talk]]) 12:48, 11 November 2016 (CET)&lt;br /&gt;
Ho notato che l'errore non si manifesta più eliminando il controllo che ci siano scrittori in attesa quando un lettore vuole iniziare a scrivere. Non capisco come questo possa essere collegato al bug. --[[User:FedericoB|FedericoB]] ([[User talk:FedericoB|talk]]) 15:10, 11 November 2016 (CET)&lt;br /&gt;
&lt;br /&gt;
FedericoB, questa soluzione &amp;amp;egrave; quella con priorit&amp;amp;agrave; ai lettori, no? Se continuano ad arrivare lettori numberOfReaders non sar&amp;amp;agrave; mai zero e quindi gli scrittori non scriveranno mai. [[User:Renzo|Renzo]] ([[User talk:Renzo|talk]]) 10:34, 12 November 2016 (CET)&lt;br /&gt;
&lt;br /&gt;
SFIDA: ho trovato il modo di togliere la starvation aggiungendo 4 token (parole chiave, nomi di variabili, operatori, costanti) a questa soluzione di FedericoB. Chi trova la soluzione? [[User:Renzo|Renzo]] ([[User talk:Renzo|talk]]) 10:43, 12 November 2016 (CET) Ah! ho appena trovato una soluzione che prevede 2 soli token in pi&amp;amp;ugrave;! [[User:Renzo|Renzo]] ([[User talk:Renzo|talk]]) 10:47, 12 November 2016 (CET)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
#include&amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include&amp;lt;stdint.h&amp;gt;&lt;br /&gt;
#include&amp;lt;pthread.h&amp;gt;&lt;br /&gt;
#include&amp;lt;semaphore.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define NUMBER_OF_READERS 3&lt;br /&gt;
#define NUMBER_OF_WRITERS 3&lt;br /&gt;
semaphore mutex;&lt;br /&gt;
semaphore ok2read;&lt;br /&gt;
semaphore ok2write;&lt;br /&gt;
&lt;br /&gt;
int numberOfReaders=0;&lt;br /&gt;
int numberOfWriters=0;&lt;br /&gt;
int waitingReaders=0;&lt;br /&gt;
int waitingWriters=0;&lt;br /&gt;
&lt;br /&gt;
// (nw == 0 &amp;amp;&amp;amp; nr == 0) || (nr &amp;gt; 0 &amp;amp;&amp;amp; nw == 0) || nw == 1&lt;br /&gt;
// (nw == 0 &amp;amp;&amp;amp; nr &amp;gt;= 0) || nw == 1&lt;br /&gt;
&lt;br /&gt;
void startread(void) {&lt;br /&gt;
// &amp;lt;await nw == 0 -&amp;gt; nr++&amp;gt;&lt;br /&gt;
    semaphore_P(mutex);&lt;br /&gt;
    if (numberOfWriters &amp;gt; 0) {&lt;br /&gt;
        waitingReaders++;&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
        semaphore_P(ok2read);&lt;br /&gt;
        waitingReaders--;&lt;br /&gt;
    }&lt;br /&gt;
    numberOfReaders++;&lt;br /&gt;
    printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, numberOfReaders, numberOfWriters, waitingReaders, waitingWriters);&lt;br /&gt;
    if (waitingReaders &amp;gt; 0 )&lt;br /&gt;
        semaphore_V(ok2read);&lt;br /&gt;
    else&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void endread(void) {&lt;br /&gt;
// &amp;lt;nr--&amp;gt;&lt;br /&gt;
    semaphore_P(mutex);&lt;br /&gt;
    numberOfReaders--;&lt;br /&gt;
    printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, numberOfReaders, numberOfWriters, waitingReaders, waitingWriters);&lt;br /&gt;
    if (numberOfReaders == 0 &amp;amp;&amp;amp; waitingWriters &amp;gt; 0)&lt;br /&gt;
        semaphore_V(ok2write);&lt;br /&gt;
    else&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void startwrite(void) {&lt;br /&gt;
// &amp;lt;await nw == 0 &amp;amp;&amp;amp; nr == 0 -&amp;gt; nw++&amp;gt;&lt;br /&gt;
    semaphore_P(mutex);&lt;br /&gt;
    if (numberOfWriters &amp;gt; 0 || numberOfReaders &amp;gt; 0) {&lt;br /&gt;
        waitingWriters++;&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
        semaphore_P(ok2write);&lt;br /&gt;
        waitingWriters--;&lt;br /&gt;
    }&lt;br /&gt;
    numberOfWriters++;&lt;br /&gt;
    printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, numberOfReaders, numberOfWriters, waitingReaders, waitingWriters);&lt;br /&gt;
    semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void endwrite(void) {&lt;br /&gt;
// &amp;lt;nw--&amp;gt;&lt;br /&gt;
    semaphore_P(mutex);&lt;br /&gt;
    numberOfWriters--;&lt;br /&gt;
    printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, numberOfReaders, numberOfWriters, waitingReaders, waitingWriters);&lt;br /&gt;
    if (waitingReaders &amp;gt; 0)&lt;br /&gt;
        semaphore_V(ok2read);&lt;br /&gt;
    else if (waitingWriters &amp;gt; 0)&lt;br /&gt;
        semaphore_V(ok2write);&lt;br /&gt;
    else&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void *reader(void *arg) {&lt;br /&gt;
    int i = (uintptr_t)arg;&lt;br /&gt;
    while (1) {&lt;br /&gt;
        //other code&lt;br /&gt;
        usleep(random() % 200000);&lt;br /&gt;
        startread();&lt;br /&gt;
        //read&lt;br /&gt;
        usleep(random() % 200000);&lt;br /&gt;
        endread();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void *writer(void *arg) {&lt;br /&gt;
    int i = (uintptr_t)arg;&lt;br /&gt;
    while (1) {&lt;br /&gt;
        //other code&lt;br /&gt;
        usleep(random() % 200000);&lt;br /&gt;
        startwrite();&lt;br /&gt;
        //write&lt;br /&gt;
        usleep(random() % 200000);&lt;br /&gt;
        endwrite();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//printf(&amp;quot;philo thinking: %d\n&amp;quot;,i);&lt;br /&gt;
/*while*/&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char *argv[]) {&lt;br /&gt;
    int i;&lt;br /&gt;
    pthread_t t;&lt;br /&gt;
    srandom(time(NULL));&lt;br /&gt;
    mutex=semaphore_create(1);&lt;br /&gt;
    ok2read=semaphore_create(0);&lt;br /&gt;
    ok2write=semaphore_create(0);&lt;br /&gt;
    for (i=0; i&amp;lt;NUMBER_OF_READERS; i++)&lt;br /&gt;
        pthread_create(&amp;amp;t, NULL, reader, (void *)(uintptr_t) i);&lt;br /&gt;
    for (i=0; i&amp;lt;NUMBER_OF_WRITERS; i++)&lt;br /&gt;
        pthread_create(&amp;amp;t, NULL, writer, (void *)(uintptr_t) i);&lt;br /&gt;
    while(1)&lt;br /&gt;
        pause();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== RW2 ==&lt;br /&gt;
Buongiorno, guardando il codice visto a lezione mi sembra che cambiando la condizione del primo if nella startread() da &amp;quot;if (nw &amp;gt; 0 &amp;amp;&amp;amp; ww == 0)&amp;quot; a &amp;quot;if (nw &amp;gt; 0 || ww &amp;gt; 0)&amp;quot; la situazione migliori. In particolare con l'and tra quelle due condizioni si aveva che non veniva fatta la P sull'ok2read anche quando si aveva nw&amp;gt;0 (con ww!=0), cosa che invece dovrebbe fare. Lasciando il resto del codice uguale mi sembra che faccia quello che deve fare.. .&lt;br /&gt;
&lt;br /&gt;
Matteo.pincherle: Perch&amp;amp;eacute; non modifichi in programma di FedericoB, lo provi e pubblichi qui la patch? [[User:Renzo|Renzo]] ([[User talk:Renzo|talk]]) 10:42, 13 November 2016 (CET)&lt;br /&gt;
&lt;br /&gt;
== Patch ==&lt;br /&gt;
Così, se non sbaglio, quando c'è almeno uno scrittore in attesa non lascia entrare altri lettori. Fa esaurire la lettura dei presenti e poi lascia scrivere lo scrittore.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include&amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include&amp;lt;stdint.h&amp;gt;&lt;br /&gt;
#include&amp;lt;pthread.h&amp;gt;&lt;br /&gt;
#include&amp;lt;semaphore.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define NUMBER_OF_READERS 3&lt;br /&gt;
#define NUMBER_OF_WRITERS 3&lt;br /&gt;
semaphore mutex;&lt;br /&gt;
semaphore ok2read;&lt;br /&gt;
semaphore ok2write;&lt;br /&gt;
&lt;br /&gt;
int numberOfReaders=0;&lt;br /&gt;
int numberOfWriters=0;&lt;br /&gt;
int waitingReaders=0;&lt;br /&gt;
int waitingWriters=0;&lt;br /&gt;
int w_last;&lt;br /&gt;
&lt;br /&gt;
// (nw == 0 &amp;amp;&amp;amp; nr == 0) || (nr &amp;gt; 0 &amp;amp;&amp;amp; nw == 0) || nw == 1&lt;br /&gt;
// (nw == 0 &amp;amp;&amp;amp; nr &amp;gt;= 0) || nw == 1&lt;br /&gt;
&lt;br /&gt;
void startread(void) {&lt;br /&gt;
    // &amp;lt;await nw == 0 -&amp;gt; nr++&amp;gt;&lt;br /&gt;
    semaphore_P(mutex);&lt;br /&gt;
    if (numberOfWriters &amp;gt; 0 || waitingWriters&amp;gt;0) {&lt;br /&gt;
        waitingReaders++;&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
        semaphore_P(ok2read);&lt;br /&gt;
        waitingReaders--;&lt;br /&gt;
    }&lt;br /&gt;
    numberOfReaders++;&lt;br /&gt;
    w_last=0;&lt;br /&gt;
    printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, numberOfReaders, numberOfWriters, waitingReaders, waitingWriters);&lt;br /&gt;
    if (waitingReaders &amp;gt; 0 )&lt;br /&gt;
        semaphore_V(ok2read);&lt;br /&gt;
    else&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void endread(void) {&lt;br /&gt;
    // &amp;lt;nr--&amp;gt;&lt;br /&gt;
    semaphore_P(mutex);&lt;br /&gt;
    numberOfReaders--;&lt;br /&gt;
    printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, numberOfReaders, numberOfWriters, waitingReaders, waitingWriters);&lt;br /&gt;
    if (numberOfReaders == 0 &amp;amp;&amp;amp; waitingWriters &amp;gt; 0)&lt;br /&gt;
        semaphore_V(ok2write);&lt;br /&gt;
    else&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void startwrite(void) {&lt;br /&gt;
    // &amp;lt;await nw == 0 &amp;amp;&amp;amp; nr == 0 -&amp;gt; nw++&amp;gt;&lt;br /&gt;
    semaphore_P(mutex);&lt;br /&gt;
    if (numberOfWriters &amp;gt; 0 || numberOfReaders &amp;gt; 0) {&lt;br /&gt;
        waitingWriters++;&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
        semaphore_P(ok2write);&lt;br /&gt;
        waitingWriters--;&lt;br /&gt;
    }&lt;br /&gt;
    numberOfWriters++;&lt;br /&gt;
    w_last=1;&lt;br /&gt;
    printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, numberOfReaders, numberOfWriters, waitingReaders, waitingWriters);&lt;br /&gt;
    semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void endwrite(void) {&lt;br /&gt;
    // &amp;lt;nw--&amp;gt;&lt;br /&gt;
    semaphore_P(mutex);&lt;br /&gt;
    numberOfWriters--;&lt;br /&gt;
    printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, numberOfReaders, numberOfWriters, waitingReaders, waitingWriters);&lt;br /&gt;
    if (waitingReaders &amp;gt; 0 &amp;amp;&amp;amp; (waitingWriters==0 || w_last))&lt;br /&gt;
        semaphore_V(ok2read);&lt;br /&gt;
    else if (waitingWriters &amp;gt; 0 &amp;amp;&amp;amp; (waitingReaders==0 || !w_last))&lt;br /&gt;
        semaphore_V(ok2write);&lt;br /&gt;
    else&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void *reader(void *arg) {&lt;br /&gt;
    int i = (uintptr_t)arg;&lt;br /&gt;
    while (1) {&lt;br /&gt;
        //other code&lt;br /&gt;
        usleep(random() % 200000);&lt;br /&gt;
        startread();&lt;br /&gt;
        //read&lt;br /&gt;
        usleep(random() % 200000);&lt;br /&gt;
        endread();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void *writer(void *arg) {&lt;br /&gt;
    int i = (uintptr_t)arg;&lt;br /&gt;
    while (1) {&lt;br /&gt;
        //other code&lt;br /&gt;
        usleep(random() % 200000);&lt;br /&gt;
        startwrite();&lt;br /&gt;
        //write&lt;br /&gt;
        usleep(random() % 200000);&lt;br /&gt;
        endwrite();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char *argv[]) {&lt;br /&gt;
    int i;&lt;br /&gt;
    pthread_t t;&lt;br /&gt;
    srandom(time(NULL));&lt;br /&gt;
    mutex=semaphore_create(1);&lt;br /&gt;
    ok2read=semaphore_create(0);&lt;br /&gt;
    ok2write=semaphore_create(0);&lt;br /&gt;
    for (i=0; i&amp;lt;NUMBER_OF_READERS; i++)&lt;br /&gt;
        pthread_create(&amp;amp;t, NULL, reader, (void *)(uintptr_t) i);&lt;br /&gt;
    for (i=0; i&amp;lt;NUMBER_OF_WRITERS; i++)&lt;br /&gt;
        pthread_create(&amp;amp;t, NULL, writer, (void *)(uintptr_t) i);&lt;br /&gt;
    while(1)&lt;br /&gt;
        pause();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
wlast non serve pi&amp;amp;ugrave;... [[User:Renzo|Renzo]] ([[User talk:Renzo|talk]]) 17:52, 13 November 2016 (CET)&lt;br /&gt;
&lt;br /&gt;
== RW2bis ==&lt;br /&gt;
Tecnicamente nella tua soluzione se i lettori sono &amp;quot;molto veloci&amp;quot; e non vanno mai a 0, lo scrittore non inizierà mai a scrivere.&lt;br /&gt;
&lt;br /&gt;
Cioè: Uno scrittore viene svegliato da ok2write solo se passa la condizione &lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
[..] &lt;br /&gt;
if (numberofReaders == 0 &amp;amp;&amp;amp; waitingWriters &amp;gt;0) &lt;br /&gt;
     semaphore_V(ok2write);&lt;br /&gt;
[..]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; --[[User:GabrieleCalarota|GabrieleCalarota]] ([[User talk:GabrieleCalarota|talk]]) 17:46, 13 November 2016 (CET)&lt;br /&gt;
&lt;br /&gt;
Non direi perche' nella startread se:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
    if (numberOfWriters &amp;gt; 0 || waitingWriters&amp;gt;0) &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
i lettori si bloccano. Quindi se c'e' almeno uno scrittore in attesa i lettori non entrano (e quindi prima o poi terminano e lasciano il posto ad uno scrittore).&lt;br /&gt;
[[User:Renzo|Renzo]] ([[User talk:Renzo|talk]]) 17:57, 13 November 2016 (CET)&lt;br /&gt;
&lt;br /&gt;
Mi riferivo alla soluzione proposta da Federico B (sezione RW). --[[User:GabrieleCalarota|GabrieleCalarota]] ([[User talk:GabrieleCalarota|talk]]) 18:27, 13 November 2016 (CET)&lt;/div&gt;</summary>
		<author><name>GabrieleCalarota</name></author>
	</entry>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=Zibaldone&amp;diff=1592</id>
		<title>Zibaldone</title>
		<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php?title=Zibaldone&amp;diff=1592"/>
		<updated>2016-11-13T17:27:17Z</updated>

		<summary type="html">&lt;p&gt;GabrieleCalarota: /* RW2bis */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== RW errato ==&lt;br /&gt;
Codice '''ERRATO''' dei lettori scrittori che dovrebbe non soffrire di problemi di starvation...&lt;br /&gt;
Esercizio: trovare gli errori.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
#include&amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include&amp;lt;stdint.h&amp;gt;&lt;br /&gt;
#include&amp;lt;pthread.h&amp;gt;&lt;br /&gt;
#include&amp;lt;semaphore.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define NREADER 3&lt;br /&gt;
#define NWRITER 3&lt;br /&gt;
semaphore mutex;&lt;br /&gt;
semaphore ok2read;&lt;br /&gt;
semaphore ok2write;&lt;br /&gt;
&lt;br /&gt;
int nr=0;&lt;br /&gt;
int nw=0;&lt;br /&gt;
int wr=0;&lt;br /&gt;
int ww=0;&lt;br /&gt;
int w_last;&lt;br /&gt;
&lt;br /&gt;
// (nw == 0 &amp;amp;&amp;amp; nr == 0) || (nr &amp;gt; 0 &amp;amp;&amp;amp; nw == 0) || nw == 1&lt;br /&gt;
// (nw == 0 &amp;amp;&amp;amp; nr &amp;gt;= 0) || nw == 1&lt;br /&gt;
&lt;br /&gt;
// this &amp;quot;baton&amp;quot; function has been left for reference only.&lt;br /&gt;
// code to implement &amp;quot;passing the baton&amp;quot; has been copied at the end of&lt;br /&gt;
// each ({start}|{end})({read}|{write}) function and reduced.&lt;br /&gt;
void baton(void) {&lt;br /&gt;
        if (nw == 0 &amp;amp;&amp;amp; nr == 0 &amp;amp;&amp;amp; ww &amp;gt; 0)&lt;br /&gt;
                semaphore_V(ok2write);&lt;br /&gt;
        else if (nw == 0 &amp;amp;&amp;amp; wr &amp;gt; 0 )&lt;br /&gt;
                semaphore_V(ok2read);&lt;br /&gt;
        else&lt;br /&gt;
                semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void startread(void) {&lt;br /&gt;
// &amp;lt;await nw == 0 -&amp;gt; nr++&amp;gt;&lt;br /&gt;
        semaphore_P(mutex);&lt;br /&gt;
        if (nw &amp;gt; 0 &amp;amp;&amp;amp; ww == 0) {&lt;br /&gt;
                wr++;&lt;br /&gt;
                semaphore_V(mutex);&lt;br /&gt;
                semaphore_P(ok2read);&lt;br /&gt;
                wr--;&lt;br /&gt;
        }&lt;br /&gt;
        nr++;&lt;br /&gt;
        w_last=0;&lt;br /&gt;
        printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, nr, nw, wr, ww);&lt;br /&gt;
        if (wr &amp;gt; 0 )&lt;br /&gt;
                semaphore_V(ok2read);&lt;br /&gt;
        else&lt;br /&gt;
                semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void endread(void) {&lt;br /&gt;
// &amp;lt;nr--&amp;gt;&lt;br /&gt;
        semaphore_P(mutex);&lt;br /&gt;
        nr--;&lt;br /&gt;
        printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, nr, nw, wr, ww);&lt;br /&gt;
        if (nr == 0 &amp;amp;&amp;amp; ww &amp;gt; 0)&lt;br /&gt;
                semaphore_V(ok2write);&lt;br /&gt;
        else&lt;br /&gt;
                semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void startwrite(void) {&lt;br /&gt;
// &amp;lt;await nw == 0 &amp;amp;&amp;amp; nr == 0 -&amp;gt; nw++&amp;gt;&lt;br /&gt;
        semaphore_P(mutex);&lt;br /&gt;
        if (nw &amp;gt; 0 || nr &amp;gt; 0) {&lt;br /&gt;
                ww++;&lt;br /&gt;
                semaphore_V(mutex);&lt;br /&gt;
                semaphore_P(ok2write);&lt;br /&gt;
                ww--;&lt;br /&gt;
        }&lt;br /&gt;
        nw++;&lt;br /&gt;
        w_last=1;&lt;br /&gt;
        printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, nr, nw, wr, ww);&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void endwrite(void) {&lt;br /&gt;
// &amp;lt;nw--&amp;gt;&lt;br /&gt;
        semaphore_P(mutex);&lt;br /&gt;
        nw--;&lt;br /&gt;
        printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, nr, nw, wr, ww);&lt;br /&gt;
        if (wr &amp;gt; 0 &amp;amp;&amp;amp; (ww == 0 || w_last))&lt;br /&gt;
                semaphore_V(ok2read);&lt;br /&gt;
        else if (ww &amp;gt; 0 &amp;amp;&amp;amp; (wr == 0 || !w_last))&lt;br /&gt;
                semaphore_V(ok2write);&lt;br /&gt;
        else&lt;br /&gt;
                semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void *reader(void *arg) {&lt;br /&gt;
        int i = (uintptr_t)arg;&lt;br /&gt;
        while (1) {&lt;br /&gt;
                //other code&lt;br /&gt;
                usleep(random() % 200000);&lt;br /&gt;
                startread();&lt;br /&gt;
                //read&lt;br /&gt;
                usleep(random() % 200000);&lt;br /&gt;
                endread();&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void *writer(void *arg) {&lt;br /&gt;
        int i = (uintptr_t)arg;&lt;br /&gt;
        while (1) {&lt;br /&gt;
                //other code&lt;br /&gt;
                usleep(random() % 200000);&lt;br /&gt;
                startwrite();&lt;br /&gt;
                //write&lt;br /&gt;
                usleep(random() % 200000);&lt;br /&gt;
                endwrite();&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//printf(&amp;quot;philo thinking: %d\n&amp;quot;,i);&lt;br /&gt;
/*while*/&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char *argv[]) {&lt;br /&gt;
        int i;&lt;br /&gt;
        pthread_t t;&lt;br /&gt;
        srandom(time(NULL));&lt;br /&gt;
        mutex=semaphore_create(1);&lt;br /&gt;
        ok2read=semaphore_create(0);&lt;br /&gt;
        ok2write=semaphore_create(0);&lt;br /&gt;
        for (i=0; i&amp;lt;NREADER; i++)&lt;br /&gt;
                pthread_create(&amp;amp;t, NULL, reader, (void *)(uintptr_t) i);&lt;br /&gt;
        for (i=0; i&amp;lt;NWRITER; i++)&lt;br /&gt;
                pthread_create(&amp;amp;t, NULL, writer, (void *)(uintptr_t) i);&lt;br /&gt;
        while(1)&lt;br /&gt;
                pause();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== RW di FedericoB ==&lt;br /&gt;
Propongo la seguente soluzione. Mi sembra che funzioni ma devo ancora capire perchè e documentarla bene. Ho provato prima a cercare il bug ma non ci sono riuscito. Ho quindi modificato il codice secondo ciò che mi sembrava sensato in base alle condizioni del problema. Ne possiamo parlare in aula oggi. --[[User:FedericoB|FedericoB]] ([[User talk:FedericoB|talk]]) 12:48, 11 November 2016 (CET)&lt;br /&gt;
Ho notato che l'errore non si manifesta più eliminando il controllo che ci siano scrittori in attesa quando un lettore vuole iniziare a scrivere. Non capisco come questo possa essere collegato al bug. --[[User:FedericoB|FedericoB]] ([[User talk:FedericoB|talk]]) 15:10, 11 November 2016 (CET)&lt;br /&gt;
&lt;br /&gt;
FedericoB, questa soluzione &amp;amp;egrave; quella con priorit&amp;amp;agrave; ai lettori, no? Se continuano ad arrivare lettori numberOfReaders non sar&amp;amp;agrave; mai zero e quindi gli scrittori non scriveranno mai. [[User:Renzo|Renzo]] ([[User talk:Renzo|talk]]) 10:34, 12 November 2016 (CET)&lt;br /&gt;
&lt;br /&gt;
SFIDA: ho trovato il modo di togliere la starvation aggiungendo 4 token (parole chiave, nomi di variabili, operatori, costanti) a questa soluzione di FedericoB. Chi trova la soluzione? [[User:Renzo|Renzo]] ([[User talk:Renzo|talk]]) 10:43, 12 November 2016 (CET) Ah! ho appena trovato una soluzione che prevede 2 soli token in pi&amp;amp;ugrave;! [[User:Renzo|Renzo]] ([[User talk:Renzo|talk]]) 10:47, 12 November 2016 (CET)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
#include&amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include&amp;lt;stdint.h&amp;gt;&lt;br /&gt;
#include&amp;lt;pthread.h&amp;gt;&lt;br /&gt;
#include&amp;lt;semaphore.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define NUMBER_OF_READERS 3&lt;br /&gt;
#define NUMBER_OF_WRITERS 3&lt;br /&gt;
semaphore mutex;&lt;br /&gt;
semaphore ok2read;&lt;br /&gt;
semaphore ok2write;&lt;br /&gt;
&lt;br /&gt;
int numberOfReaders=0;&lt;br /&gt;
int numberOfWriters=0;&lt;br /&gt;
int waitingReaders=0;&lt;br /&gt;
int waitingWriters=0;&lt;br /&gt;
&lt;br /&gt;
// (nw == 0 &amp;amp;&amp;amp; nr == 0) || (nr &amp;gt; 0 &amp;amp;&amp;amp; nw == 0) || nw == 1&lt;br /&gt;
// (nw == 0 &amp;amp;&amp;amp; nr &amp;gt;= 0) || nw == 1&lt;br /&gt;
&lt;br /&gt;
void startread(void) {&lt;br /&gt;
// &amp;lt;await nw == 0 -&amp;gt; nr++&amp;gt;&lt;br /&gt;
    semaphore_P(mutex);&lt;br /&gt;
    if (numberOfWriters &amp;gt; 0) {&lt;br /&gt;
        waitingReaders++;&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
        semaphore_P(ok2read);&lt;br /&gt;
        waitingReaders--;&lt;br /&gt;
    }&lt;br /&gt;
    numberOfReaders++;&lt;br /&gt;
    printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, numberOfReaders, numberOfWriters, waitingReaders, waitingWriters);&lt;br /&gt;
    if (waitingReaders &amp;gt; 0 )&lt;br /&gt;
        semaphore_V(ok2read);&lt;br /&gt;
    else&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void endread(void) {&lt;br /&gt;
// &amp;lt;nr--&amp;gt;&lt;br /&gt;
    semaphore_P(mutex);&lt;br /&gt;
    numberOfReaders--;&lt;br /&gt;
    printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, numberOfReaders, numberOfWriters, waitingReaders, waitingWriters);&lt;br /&gt;
    if (numberOfReaders == 0 &amp;amp;&amp;amp; waitingWriters &amp;gt; 0)&lt;br /&gt;
        semaphore_V(ok2write);&lt;br /&gt;
    else&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void startwrite(void) {&lt;br /&gt;
// &amp;lt;await nw == 0 &amp;amp;&amp;amp; nr == 0 -&amp;gt; nw++&amp;gt;&lt;br /&gt;
    semaphore_P(mutex);&lt;br /&gt;
    if (numberOfWriters &amp;gt; 0 || numberOfReaders &amp;gt; 0) {&lt;br /&gt;
        waitingWriters++;&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
        semaphore_P(ok2write);&lt;br /&gt;
        waitingWriters--;&lt;br /&gt;
    }&lt;br /&gt;
    numberOfWriters++;&lt;br /&gt;
    printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, numberOfReaders, numberOfWriters, waitingReaders, waitingWriters);&lt;br /&gt;
    semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void endwrite(void) {&lt;br /&gt;
// &amp;lt;nw--&amp;gt;&lt;br /&gt;
    semaphore_P(mutex);&lt;br /&gt;
    numberOfWriters--;&lt;br /&gt;
    printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, numberOfReaders, numberOfWriters, waitingReaders, waitingWriters);&lt;br /&gt;
    if (waitingReaders &amp;gt; 0)&lt;br /&gt;
        semaphore_V(ok2read);&lt;br /&gt;
    else if (waitingWriters &amp;gt; 0)&lt;br /&gt;
        semaphore_V(ok2write);&lt;br /&gt;
    else&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void *reader(void *arg) {&lt;br /&gt;
    int i = (uintptr_t)arg;&lt;br /&gt;
    while (1) {&lt;br /&gt;
        //other code&lt;br /&gt;
        usleep(random() % 200000);&lt;br /&gt;
        startread();&lt;br /&gt;
        //read&lt;br /&gt;
        usleep(random() % 200000);&lt;br /&gt;
        endread();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void *writer(void *arg) {&lt;br /&gt;
    int i = (uintptr_t)arg;&lt;br /&gt;
    while (1) {&lt;br /&gt;
        //other code&lt;br /&gt;
        usleep(random() % 200000);&lt;br /&gt;
        startwrite();&lt;br /&gt;
        //write&lt;br /&gt;
        usleep(random() % 200000);&lt;br /&gt;
        endwrite();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//printf(&amp;quot;philo thinking: %d\n&amp;quot;,i);&lt;br /&gt;
/*while*/&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char *argv[]) {&lt;br /&gt;
    int i;&lt;br /&gt;
    pthread_t t;&lt;br /&gt;
    srandom(time(NULL));&lt;br /&gt;
    mutex=semaphore_create(1);&lt;br /&gt;
    ok2read=semaphore_create(0);&lt;br /&gt;
    ok2write=semaphore_create(0);&lt;br /&gt;
    for (i=0; i&amp;lt;NUMBER_OF_READERS; i++)&lt;br /&gt;
        pthread_create(&amp;amp;t, NULL, reader, (void *)(uintptr_t) i);&lt;br /&gt;
    for (i=0; i&amp;lt;NUMBER_OF_WRITERS; i++)&lt;br /&gt;
        pthread_create(&amp;amp;t, NULL, writer, (void *)(uintptr_t) i);&lt;br /&gt;
    while(1)&lt;br /&gt;
        pause();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== RW2 ==&lt;br /&gt;
Buongiorno, guardando il codice visto a lezione mi sembra che cambiando la condizione del primo if nella startread() da &amp;quot;if (nw &amp;gt; 0 &amp;amp;&amp;amp; ww == 0)&amp;quot; a &amp;quot;if (nw &amp;gt; 0 || ww &amp;gt; 0)&amp;quot; la situazione migliori. In particolare con l'and tra quelle due condizioni si aveva che non veniva fatta la P sull'ok2read anche quando si aveva nw&amp;gt;0 (con ww!=0), cosa che invece dovrebbe fare. Lasciando il resto del codice uguale mi sembra che faccia quello che deve fare.. .&lt;br /&gt;
&lt;br /&gt;
Matteo.pincherle: Perch&amp;amp;eacute; non modifichi in programma di FedericoB, lo provi e pubblichi qui la patch? [[User:Renzo|Renzo]] ([[User talk:Renzo|talk]]) 10:42, 13 November 2016 (CET)&lt;br /&gt;
&lt;br /&gt;
== Patch ==&lt;br /&gt;
Così, se non sbaglio, quando c'è almeno uno scrittore in attesa non lascia entrare altri lettori. Fa esaurire la lettura dei presenti e poi lascia scrivere lo scrittore.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include&amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include&amp;lt;stdint.h&amp;gt;&lt;br /&gt;
#include&amp;lt;pthread.h&amp;gt;&lt;br /&gt;
#include&amp;lt;semaphore.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define NUMBER_OF_READERS 3&lt;br /&gt;
#define NUMBER_OF_WRITERS 3&lt;br /&gt;
semaphore mutex;&lt;br /&gt;
semaphore ok2read;&lt;br /&gt;
semaphore ok2write;&lt;br /&gt;
&lt;br /&gt;
int numberOfReaders=0;&lt;br /&gt;
int numberOfWriters=0;&lt;br /&gt;
int waitingReaders=0;&lt;br /&gt;
int waitingWriters=0;&lt;br /&gt;
int w_last;&lt;br /&gt;
&lt;br /&gt;
// (nw == 0 &amp;amp;&amp;amp; nr == 0) || (nr &amp;gt; 0 &amp;amp;&amp;amp; nw == 0) || nw == 1&lt;br /&gt;
// (nw == 0 &amp;amp;&amp;amp; nr &amp;gt;= 0) || nw == 1&lt;br /&gt;
&lt;br /&gt;
void startread(void) {&lt;br /&gt;
    // &amp;lt;await nw == 0 -&amp;gt; nr++&amp;gt;&lt;br /&gt;
    semaphore_P(mutex);&lt;br /&gt;
    if (numberOfWriters &amp;gt; 0 || waitingWriters&amp;gt;0) {&lt;br /&gt;
        waitingReaders++;&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
        semaphore_P(ok2read);&lt;br /&gt;
        waitingReaders--;&lt;br /&gt;
    }&lt;br /&gt;
    numberOfReaders++;&lt;br /&gt;
    w_last=0;&lt;br /&gt;
    printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, numberOfReaders, numberOfWriters, waitingReaders, waitingWriters);&lt;br /&gt;
    if (waitingReaders &amp;gt; 0 )&lt;br /&gt;
        semaphore_V(ok2read);&lt;br /&gt;
    else&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void endread(void) {&lt;br /&gt;
    // &amp;lt;nr--&amp;gt;&lt;br /&gt;
    semaphore_P(mutex);&lt;br /&gt;
    numberOfReaders--;&lt;br /&gt;
    printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, numberOfReaders, numberOfWriters, waitingReaders, waitingWriters);&lt;br /&gt;
    if (numberOfReaders == 0 &amp;amp;&amp;amp; waitingWriters &amp;gt; 0)&lt;br /&gt;
        semaphore_V(ok2write);&lt;br /&gt;
    else&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void startwrite(void) {&lt;br /&gt;
    // &amp;lt;await nw == 0 &amp;amp;&amp;amp; nr == 0 -&amp;gt; nw++&amp;gt;&lt;br /&gt;
    semaphore_P(mutex);&lt;br /&gt;
    if (numberOfWriters &amp;gt; 0 || numberOfReaders &amp;gt; 0) {&lt;br /&gt;
        waitingWriters++;&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
        semaphore_P(ok2write);&lt;br /&gt;
        waitingWriters--;&lt;br /&gt;
    }&lt;br /&gt;
    numberOfWriters++;&lt;br /&gt;
    w_last=1;&lt;br /&gt;
    printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, numberOfReaders, numberOfWriters, waitingReaders, waitingWriters);&lt;br /&gt;
    semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void endwrite(void) {&lt;br /&gt;
    // &amp;lt;nw--&amp;gt;&lt;br /&gt;
    semaphore_P(mutex);&lt;br /&gt;
    numberOfWriters--;&lt;br /&gt;
    printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, numberOfReaders, numberOfWriters, waitingReaders, waitingWriters);&lt;br /&gt;
    if (waitingReaders &amp;gt; 0 &amp;amp;&amp;amp; (waitingWriters==0 || w_last))&lt;br /&gt;
        semaphore_V(ok2read);&lt;br /&gt;
    else if (waitingWriters &amp;gt; 0 &amp;amp;&amp;amp; (waitingReaders==0 || !w_last))&lt;br /&gt;
        semaphore_V(ok2write);&lt;br /&gt;
    else&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void *reader(void *arg) {&lt;br /&gt;
    int i = (uintptr_t)arg;&lt;br /&gt;
    while (1) {&lt;br /&gt;
        //other code&lt;br /&gt;
        usleep(random() % 200000);&lt;br /&gt;
        startread();&lt;br /&gt;
        //read&lt;br /&gt;
        usleep(random() % 200000);&lt;br /&gt;
        endread();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void *writer(void *arg) {&lt;br /&gt;
    int i = (uintptr_t)arg;&lt;br /&gt;
    while (1) {&lt;br /&gt;
        //other code&lt;br /&gt;
        usleep(random() % 200000);&lt;br /&gt;
        startwrite();&lt;br /&gt;
        //write&lt;br /&gt;
        usleep(random() % 200000);&lt;br /&gt;
        endwrite();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char *argv[]) {&lt;br /&gt;
    int i;&lt;br /&gt;
    pthread_t t;&lt;br /&gt;
    srandom(time(NULL));&lt;br /&gt;
    mutex=semaphore_create(1);&lt;br /&gt;
    ok2read=semaphore_create(0);&lt;br /&gt;
    ok2write=semaphore_create(0);&lt;br /&gt;
    for (i=0; i&amp;lt;NUMBER_OF_READERS; i++)&lt;br /&gt;
        pthread_create(&amp;amp;t, NULL, reader, (void *)(uintptr_t) i);&lt;br /&gt;
    for (i=0; i&amp;lt;NUMBER_OF_WRITERS; i++)&lt;br /&gt;
        pthread_create(&amp;amp;t, NULL, writer, (void *)(uintptr_t) i);&lt;br /&gt;
    while(1)&lt;br /&gt;
        pause();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
wlast non serve pi&amp;amp;ugrave;... [[User:Renzo|Renzo]] ([[User talk:Renzo|talk]]) 17:52, 13 November 2016 (CET)&lt;br /&gt;
&lt;br /&gt;
== RW2bis ==&lt;br /&gt;
Tecnicamente nella tua soluzione se i lettori sono &amp;quot;molto veloci&amp;quot; e non vanno mai a 0, lo scrittore non inizierà mai a scrivere.&lt;br /&gt;
&lt;br /&gt;
Cioè: Uno scrittore viene svegliato da ok2write solo se passa la condizione &lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
[..] &lt;br /&gt;
if (numberofReaders == 0 &amp;amp;&amp;amp; waitingWriters &amp;gt;0) &lt;br /&gt;
     semaphore_V(ok2write);&lt;br /&gt;
[..]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; --[[User:GabrieleCalarota|GabrieleCalarota]] ([[User talk:GabrieleCalarota|talk]]) 17:46, 13 November 2016 (CET)&lt;br /&gt;
&lt;br /&gt;
Non direi perche' nella startread se:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
    if (numberOfWriters &amp;gt; 0 || waitingWriters&amp;gt;0) &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
i lettori si bloccano. Quindi se c'e' almeno uno scrittore in attesa i lettori non entrano (e quindi prima o poi terminano e lasciano il posto ad uno scrittore).&lt;br /&gt;
[[User:Renzo|Renzo]] ([[User talk:Renzo|talk]]) 17:57, 13 November 2016 (CET)&lt;br /&gt;
&lt;br /&gt;
Mi riferivo alla soluzione proposta da Federico B (sezione RW).&lt;/div&gt;</summary>
		<author><name>GabrieleCalarota</name></author>
	</entry>
	<entry>
		<id>https://so.v2.cs.unibo.it/wiki/index.php?title=Zibaldone&amp;diff=1588</id>
		<title>Zibaldone</title>
		<link rel="alternate" type="text/html" href="https://so.v2.cs.unibo.it/wiki/index.php?title=Zibaldone&amp;diff=1588"/>
		<updated>2016-11-13T16:46:46Z</updated>

		<summary type="html">&lt;p&gt;GabrieleCalarota: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== RW errato ==&lt;br /&gt;
Codice '''ERRATO''' dei lettori scrittori che dovrebbe non soffrire di problemi di starvation...&lt;br /&gt;
Esercizio: trovare gli errori.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
#include&amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include&amp;lt;stdint.h&amp;gt;&lt;br /&gt;
#include&amp;lt;pthread.h&amp;gt;&lt;br /&gt;
#include&amp;lt;semaphore.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define NREADER 3&lt;br /&gt;
#define NWRITER 3&lt;br /&gt;
semaphore mutex;&lt;br /&gt;
semaphore ok2read;&lt;br /&gt;
semaphore ok2write;&lt;br /&gt;
&lt;br /&gt;
int nr=0;&lt;br /&gt;
int nw=0;&lt;br /&gt;
int wr=0;&lt;br /&gt;
int ww=0;&lt;br /&gt;
int w_last;&lt;br /&gt;
&lt;br /&gt;
// (nw == 0 &amp;amp;&amp;amp; nr == 0) || (nr &amp;gt; 0 &amp;amp;&amp;amp; nw == 0) || nw == 1&lt;br /&gt;
// (nw == 0 &amp;amp;&amp;amp; nr &amp;gt;= 0) || nw == 1&lt;br /&gt;
&lt;br /&gt;
// this &amp;quot;baton&amp;quot; function has been left for reference only.&lt;br /&gt;
// code to implement &amp;quot;passing the baton&amp;quot; has been copied at the end of&lt;br /&gt;
// each ({start}|{end})({read}|{write}) function and reduced.&lt;br /&gt;
void baton(void) {&lt;br /&gt;
        if (nw == 0 &amp;amp;&amp;amp; nr == 0 &amp;amp;&amp;amp; ww &amp;gt; 0)&lt;br /&gt;
                semaphore_V(ok2write);&lt;br /&gt;
        else if (nw == 0 &amp;amp;&amp;amp; wr &amp;gt; 0 )&lt;br /&gt;
                semaphore_V(ok2read);&lt;br /&gt;
        else&lt;br /&gt;
                semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void startread(void) {&lt;br /&gt;
// &amp;lt;await nw == 0 -&amp;gt; nr++&amp;gt;&lt;br /&gt;
        semaphore_P(mutex);&lt;br /&gt;
        if (nw &amp;gt; 0 &amp;amp;&amp;amp; ww == 0) {&lt;br /&gt;
                wr++;&lt;br /&gt;
                semaphore_V(mutex);&lt;br /&gt;
                semaphore_P(ok2read);&lt;br /&gt;
                wr--;&lt;br /&gt;
        }&lt;br /&gt;
        nr++;&lt;br /&gt;
        w_last=0;&lt;br /&gt;
        printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, nr, nw, wr, ww);&lt;br /&gt;
        if (wr &amp;gt; 0 )&lt;br /&gt;
                semaphore_V(ok2read);&lt;br /&gt;
        else&lt;br /&gt;
                semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void endread(void) {&lt;br /&gt;
// &amp;lt;nr--&amp;gt;&lt;br /&gt;
        semaphore_P(mutex);&lt;br /&gt;
        nr--;&lt;br /&gt;
        printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, nr, nw, wr, ww);&lt;br /&gt;
        if (nr == 0 &amp;amp;&amp;amp; ww &amp;gt; 0)&lt;br /&gt;
                semaphore_V(ok2write);&lt;br /&gt;
        else&lt;br /&gt;
                semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void startwrite(void) {&lt;br /&gt;
// &amp;lt;await nw == 0 &amp;amp;&amp;amp; nr == 0 -&amp;gt; nw++&amp;gt;&lt;br /&gt;
        semaphore_P(mutex);&lt;br /&gt;
        if (nw &amp;gt; 0 || nr &amp;gt; 0) {&lt;br /&gt;
                ww++;&lt;br /&gt;
                semaphore_V(mutex);&lt;br /&gt;
                semaphore_P(ok2write);&lt;br /&gt;
                ww--;&lt;br /&gt;
        }&lt;br /&gt;
        nw++;&lt;br /&gt;
        w_last=1;&lt;br /&gt;
        printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, nr, nw, wr, ww);&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void endwrite(void) {&lt;br /&gt;
// &amp;lt;nw--&amp;gt;&lt;br /&gt;
        semaphore_P(mutex);&lt;br /&gt;
        nw--;&lt;br /&gt;
        printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, nr, nw, wr, ww);&lt;br /&gt;
        if (wr &amp;gt; 0 &amp;amp;&amp;amp; (ww == 0 || w_last))&lt;br /&gt;
                semaphore_V(ok2read);&lt;br /&gt;
        else if (ww &amp;gt; 0 &amp;amp;&amp;amp; (wr == 0 || !w_last))&lt;br /&gt;
                semaphore_V(ok2write);&lt;br /&gt;
        else&lt;br /&gt;
                semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void *reader(void *arg) {&lt;br /&gt;
        int i = (uintptr_t)arg;&lt;br /&gt;
        while (1) {&lt;br /&gt;
                //other code&lt;br /&gt;
                usleep(random() % 200000);&lt;br /&gt;
                startread();&lt;br /&gt;
                //read&lt;br /&gt;
                usleep(random() % 200000);&lt;br /&gt;
                endread();&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void *writer(void *arg) {&lt;br /&gt;
        int i = (uintptr_t)arg;&lt;br /&gt;
        while (1) {&lt;br /&gt;
                //other code&lt;br /&gt;
                usleep(random() % 200000);&lt;br /&gt;
                startwrite();&lt;br /&gt;
                //write&lt;br /&gt;
                usleep(random() % 200000);&lt;br /&gt;
                endwrite();&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//printf(&amp;quot;philo thinking: %d\n&amp;quot;,i);&lt;br /&gt;
/*while*/&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char *argv[]) {&lt;br /&gt;
        int i;&lt;br /&gt;
        pthread_t t;&lt;br /&gt;
        srandom(time(NULL));&lt;br /&gt;
        mutex=semaphore_create(1);&lt;br /&gt;
        ok2read=semaphore_create(0);&lt;br /&gt;
        ok2write=semaphore_create(0);&lt;br /&gt;
        for (i=0; i&amp;lt;NREADER; i++)&lt;br /&gt;
                pthread_create(&amp;amp;t, NULL, reader, (void *)(uintptr_t) i);&lt;br /&gt;
        for (i=0; i&amp;lt;NWRITER; i++)&lt;br /&gt;
                pthread_create(&amp;amp;t, NULL, writer, (void *)(uintptr_t) i);&lt;br /&gt;
        while(1)&lt;br /&gt;
                pause();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== RW di FedericoB ==&lt;br /&gt;
Propongo la seguente soluzione. Mi sembra che funzioni ma devo ancora capire perchè e documentarla bene. Ho provato prima a cercare il bug ma non ci sono riuscito. Ho quindi modificato il codice secondo ciò che mi sembrava sensato in base alle condizioni del problema. Ne possiamo parlare in aula oggi. --[[User:FedericoB|FedericoB]] ([[User talk:FedericoB|talk]]) 12:48, 11 November 2016 (CET)&lt;br /&gt;
Ho notato che l'errore non si manifesta più eliminando il controllo che ci siano scrittori in attesa quando un lettore vuole iniziare a scrivere. Non capisco come questo possa essere collegato al bug. --[[User:FedericoB|FedericoB]] ([[User talk:FedericoB|talk]]) 15:10, 11 November 2016 (CET)&lt;br /&gt;
&lt;br /&gt;
FedericoB, questa soluzione &amp;amp;egrave; quella con priorit&amp;amp;agrave; ai lettori, no? Se continuano ad arrivare lettori numberOfReaders non sar&amp;amp;agrave; mai zero e quindi gli scrittori non scriveranno mai. [[User:Renzo|Renzo]] ([[User talk:Renzo|talk]]) 10:34, 12 November 2016 (CET)&lt;br /&gt;
&lt;br /&gt;
SFIDA: ho trovato il modo di togliere la starvation aggiungendo 4 token (parole chiave, nomi di variabili, operatori, costanti) a questa soluzione di FedericoB. Chi trova la soluzione? [[User:Renzo|Renzo]] ([[User talk:Renzo|talk]]) 10:43, 12 November 2016 (CET) Ah! ho appena trovato una soluzione che prevede 2 soli token in pi&amp;amp;ugrave;! [[User:Renzo|Renzo]] ([[User talk:Renzo|talk]]) 10:47, 12 November 2016 (CET)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
#include&amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include&amp;lt;stdint.h&amp;gt;&lt;br /&gt;
#include&amp;lt;pthread.h&amp;gt;&lt;br /&gt;
#include&amp;lt;semaphore.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define NUMBER_OF_READERS 3&lt;br /&gt;
#define NUMBER_OF_WRITERS 3&lt;br /&gt;
semaphore mutex;&lt;br /&gt;
semaphore ok2read;&lt;br /&gt;
semaphore ok2write;&lt;br /&gt;
&lt;br /&gt;
int numberOfReaders=0;&lt;br /&gt;
int numberOfWriters=0;&lt;br /&gt;
int waitingReaders=0;&lt;br /&gt;
int waitingWriters=0;&lt;br /&gt;
&lt;br /&gt;
// (nw == 0 &amp;amp;&amp;amp; nr == 0) || (nr &amp;gt; 0 &amp;amp;&amp;amp; nw == 0) || nw == 1&lt;br /&gt;
// (nw == 0 &amp;amp;&amp;amp; nr &amp;gt;= 0) || nw == 1&lt;br /&gt;
&lt;br /&gt;
void startread(void) {&lt;br /&gt;
// &amp;lt;await nw == 0 -&amp;gt; nr++&amp;gt;&lt;br /&gt;
    semaphore_P(mutex);&lt;br /&gt;
    if (numberOfWriters &amp;gt; 0) {&lt;br /&gt;
        waitingReaders++;&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
        semaphore_P(ok2read);&lt;br /&gt;
        waitingReaders--;&lt;br /&gt;
    }&lt;br /&gt;
    numberOfReaders++;&lt;br /&gt;
    printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, numberOfReaders, numberOfWriters, waitingReaders, waitingWriters);&lt;br /&gt;
    if (waitingReaders &amp;gt; 0 )&lt;br /&gt;
        semaphore_V(ok2read);&lt;br /&gt;
    else&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void endread(void) {&lt;br /&gt;
// &amp;lt;nr--&amp;gt;&lt;br /&gt;
    semaphore_P(mutex);&lt;br /&gt;
    numberOfReaders--;&lt;br /&gt;
    printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, numberOfReaders, numberOfWriters, waitingReaders, waitingWriters);&lt;br /&gt;
    if (numberOfReaders == 0 &amp;amp;&amp;amp; waitingWriters &amp;gt; 0)&lt;br /&gt;
        semaphore_V(ok2write);&lt;br /&gt;
    else&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void startwrite(void) {&lt;br /&gt;
// &amp;lt;await nw == 0 &amp;amp;&amp;amp; nr == 0 -&amp;gt; nw++&amp;gt;&lt;br /&gt;
    semaphore_P(mutex);&lt;br /&gt;
    if (numberOfWriters &amp;gt; 0 || numberOfReaders &amp;gt; 0) {&lt;br /&gt;
        waitingWriters++;&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
        semaphore_P(ok2write);&lt;br /&gt;
        waitingWriters--;&lt;br /&gt;
    }&lt;br /&gt;
    numberOfWriters++;&lt;br /&gt;
    printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, numberOfReaders, numberOfWriters, waitingReaders, waitingWriters);&lt;br /&gt;
    semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void endwrite(void) {&lt;br /&gt;
// &amp;lt;nw--&amp;gt;&lt;br /&gt;
    semaphore_P(mutex);&lt;br /&gt;
    numberOfWriters--;&lt;br /&gt;
    printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, numberOfReaders, numberOfWriters, waitingReaders, waitingWriters);&lt;br /&gt;
    if (waitingReaders &amp;gt; 0)&lt;br /&gt;
        semaphore_V(ok2read);&lt;br /&gt;
    else if (waitingWriters &amp;gt; 0)&lt;br /&gt;
        semaphore_V(ok2write);&lt;br /&gt;
    else&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void *reader(void *arg) {&lt;br /&gt;
    int i = (uintptr_t)arg;&lt;br /&gt;
    while (1) {&lt;br /&gt;
        //other code&lt;br /&gt;
        usleep(random() % 200000);&lt;br /&gt;
        startread();&lt;br /&gt;
        //read&lt;br /&gt;
        usleep(random() % 200000);&lt;br /&gt;
        endread();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void *writer(void *arg) {&lt;br /&gt;
    int i = (uintptr_t)arg;&lt;br /&gt;
    while (1) {&lt;br /&gt;
        //other code&lt;br /&gt;
        usleep(random() % 200000);&lt;br /&gt;
        startwrite();&lt;br /&gt;
        //write&lt;br /&gt;
        usleep(random() % 200000);&lt;br /&gt;
        endwrite();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
//printf(&amp;quot;philo thinking: %d\n&amp;quot;,i);&lt;br /&gt;
/*while*/&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char *argv[]) {&lt;br /&gt;
    int i;&lt;br /&gt;
    pthread_t t;&lt;br /&gt;
    srandom(time(NULL));&lt;br /&gt;
    mutex=semaphore_create(1);&lt;br /&gt;
    ok2read=semaphore_create(0);&lt;br /&gt;
    ok2write=semaphore_create(0);&lt;br /&gt;
    for (i=0; i&amp;lt;NUMBER_OF_READERS; i++)&lt;br /&gt;
        pthread_create(&amp;amp;t, NULL, reader, (void *)(uintptr_t) i);&lt;br /&gt;
    for (i=0; i&amp;lt;NUMBER_OF_WRITERS; i++)&lt;br /&gt;
        pthread_create(&amp;amp;t, NULL, writer, (void *)(uintptr_t) i);&lt;br /&gt;
    while(1)&lt;br /&gt;
        pause();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== RW2 ==&lt;br /&gt;
Buongiorno, guardando il codice visto a lezione mi sembra che cambiando la condizione del primo if nella startread() da &amp;quot;if (nw &amp;gt; 0 &amp;amp;&amp;amp; ww == 0)&amp;quot; a &amp;quot;if (nw &amp;gt; 0 || ww &amp;gt; 0)&amp;quot; la situazione migliori. In particolare con l'and tra quelle due condizioni si aveva che non veniva fatta la P sull'ok2read anche quando si aveva nw&amp;gt;0 (con ww!=0), cosa che invece dovrebbe fare. Lasciando il resto del codice uguale mi sembra che faccia quello che deve fare.. .&lt;br /&gt;
&lt;br /&gt;
Matteo.pincherle: Perch&amp;amp;eacute; non modifichi in programma di FedericoB, lo provi e pubblichi qui la patch? [[User:Renzo|Renzo]] ([[User talk:Renzo|talk]]) 10:42, 13 November 2016 (CET)&lt;br /&gt;
&lt;br /&gt;
== Patch ==&lt;br /&gt;
Così, se non sbaglio, quando c'è almeno uno scrittore in attesa non lascia entrare altri lettori. Fa esaurire la lettura dei presenti e poi lascia scrivere lo scrittore.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include&amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include&amp;lt;stdint.h&amp;gt;&lt;br /&gt;
#include&amp;lt;pthread.h&amp;gt;&lt;br /&gt;
#include&amp;lt;semaphore.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define NUMBER_OF_READERS 3&lt;br /&gt;
#define NUMBER_OF_WRITERS 3&lt;br /&gt;
semaphore mutex;&lt;br /&gt;
semaphore ok2read;&lt;br /&gt;
semaphore ok2write;&lt;br /&gt;
&lt;br /&gt;
int numberOfReaders=0;&lt;br /&gt;
int numberOfWriters=0;&lt;br /&gt;
int waitingReaders=0;&lt;br /&gt;
int waitingWriters=0;&lt;br /&gt;
int w_last;&lt;br /&gt;
&lt;br /&gt;
// (nw == 0 &amp;amp;&amp;amp; nr == 0) || (nr &amp;gt; 0 &amp;amp;&amp;amp; nw == 0) || nw == 1&lt;br /&gt;
// (nw == 0 &amp;amp;&amp;amp; nr &amp;gt;= 0) || nw == 1&lt;br /&gt;
&lt;br /&gt;
void startread(void) {&lt;br /&gt;
    // &amp;lt;await nw == 0 -&amp;gt; nr++&amp;gt;&lt;br /&gt;
    semaphore_P(mutex);&lt;br /&gt;
    if (numberOfWriters &amp;gt; 0 || waitingWriters&amp;gt;0) {&lt;br /&gt;
        waitingReaders++;&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
        semaphore_P(ok2read);&lt;br /&gt;
        waitingReaders--;&lt;br /&gt;
    }&lt;br /&gt;
    numberOfReaders++;&lt;br /&gt;
    w_last=0;&lt;br /&gt;
    printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, numberOfReaders, numberOfWriters, waitingReaders, waitingWriters);&lt;br /&gt;
    if (waitingReaders &amp;gt; 0 )&lt;br /&gt;
        semaphore_V(ok2read);&lt;br /&gt;
    else&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void endread(void) {&lt;br /&gt;
    // &amp;lt;nr--&amp;gt;&lt;br /&gt;
    semaphore_P(mutex);&lt;br /&gt;
    numberOfReaders--;&lt;br /&gt;
    printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, numberOfReaders, numberOfWriters, waitingReaders, waitingWriters);&lt;br /&gt;
    if (numberOfReaders == 0 &amp;amp;&amp;amp; waitingWriters &amp;gt; 0)&lt;br /&gt;
        semaphore_V(ok2write);&lt;br /&gt;
    else&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void startwrite(void) {&lt;br /&gt;
    // &amp;lt;await nw == 0 &amp;amp;&amp;amp; nr == 0 -&amp;gt; nw++&amp;gt;&lt;br /&gt;
    semaphore_P(mutex);&lt;br /&gt;
    if (numberOfWriters &amp;gt; 0 || numberOfReaders &amp;gt; 0) {&lt;br /&gt;
        waitingWriters++;&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
        semaphore_P(ok2write);&lt;br /&gt;
        waitingWriters--;&lt;br /&gt;
    }&lt;br /&gt;
    numberOfWriters++;&lt;br /&gt;
    w_last=1;&lt;br /&gt;
    printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, numberOfReaders, numberOfWriters, waitingReaders, waitingWriters);&lt;br /&gt;
    semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void endwrite(void) {&lt;br /&gt;
    // &amp;lt;nw--&amp;gt;&lt;br /&gt;
    semaphore_P(mutex);&lt;br /&gt;
    numberOfWriters--;&lt;br /&gt;
    printf(&amp;quot;NR %d - NW %d - WR %d - WW %d \n&amp;quot;, numberOfReaders, numberOfWriters, waitingReaders, waitingWriters);&lt;br /&gt;
    if (waitingReaders &amp;gt; 0 &amp;amp;&amp;amp; (waitingWriters==0 || w_last))&lt;br /&gt;
        semaphore_V(ok2read);&lt;br /&gt;
    else if (waitingWriters &amp;gt; 0 &amp;amp;&amp;amp; (waitingReaders==0 || !w_last))&lt;br /&gt;
        semaphore_V(ok2write);&lt;br /&gt;
    else&lt;br /&gt;
        semaphore_V(mutex);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void *reader(void *arg) {&lt;br /&gt;
    int i = (uintptr_t)arg;&lt;br /&gt;
    while (1) {&lt;br /&gt;
        //other code&lt;br /&gt;
        usleep(random() % 200000);&lt;br /&gt;
        startread();&lt;br /&gt;
        //read&lt;br /&gt;
        usleep(random() % 200000);&lt;br /&gt;
        endread();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void *writer(void *arg) {&lt;br /&gt;
    int i = (uintptr_t)arg;&lt;br /&gt;
    while (1) {&lt;br /&gt;
        //other code&lt;br /&gt;
        usleep(random() % 200000);&lt;br /&gt;
        startwrite();&lt;br /&gt;
        //write&lt;br /&gt;
        usleep(random() % 200000);&lt;br /&gt;
        endwrite();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char *argv[]) {&lt;br /&gt;
    int i;&lt;br /&gt;
    pthread_t t;&lt;br /&gt;
    srandom(time(NULL));&lt;br /&gt;
    mutex=semaphore_create(1);&lt;br /&gt;
    ok2read=semaphore_create(0);&lt;br /&gt;
    ok2write=semaphore_create(0);&lt;br /&gt;
    for (i=0; i&amp;lt;NUMBER_OF_READERS; i++)&lt;br /&gt;
        pthread_create(&amp;amp;t, NULL, reader, (void *)(uintptr_t) i);&lt;br /&gt;
    for (i=0; i&amp;lt;NUMBER_OF_WRITERS; i++)&lt;br /&gt;
        pthread_create(&amp;amp;t, NULL, writer, (void *)(uintptr_t) i);&lt;br /&gt;
    while(1)&lt;br /&gt;
        pause();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== RW2bis ==&lt;br /&gt;
Tecnicamente nella tua soluzione se i lettori sono &amp;quot;molto veloci&amp;quot; e non vanno mai a 0, lo scrittore non inizierà mai a scrivere.&lt;br /&gt;
&lt;br /&gt;
Cioè: Uno scrittore viene svegliato da ok2write solo se passa la condizione &lt;br /&gt;
&amp;lt;syntaxhighlight lang=C&amp;gt;&lt;br /&gt;
[..] &lt;br /&gt;
if (numberofReaders == 0 &amp;amp;&amp;amp; waitingWriters &amp;gt;0) &lt;br /&gt;
     semaphore_V(ok2write);&lt;br /&gt;
[..]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; --[[User:GabrieleCalarota|GabrieleCalarota]] ([[User talk:GabrieleCalarota|talk]]) 17:46, 13 November 2016 (CET)&lt;/div&gt;</summary>
		<author><name>GabrieleCalarota</name></author>
	</entry>
</feed>