# Primitive Sincrone * Send bloccante e receive bloccante *(vedi slides)* ## Guardie di output Una guardia solitamente era trattata come una *recv* bloccante (**guardia di input**), ma possono esistere anche guardie della forma: ``` (); ``` Che e' definita come **guardia di output**. **Mescolare guardie di input e guardie di output puo' creare situazioni di deadlock.** *(vedi slides per esempi)* Questo e' dovuto principalmente alla scelta non deterministica tra piu' guardie valide. Per questo motivo si decide di non utilizzare le guardie di output, a parte in alcuni casi specifici. ## Processi servitori: gestione di pool di risorse equivalenti **Caso sincrono** *(slides per implementazione)* ## Processi servitori: gestione di una risorsa dedicata *(vedi slides)* ## Simulazione di un semaforo Le primitive sincrone hanno lo stesso potere di tutte le primitive viste precedentemente. *(vedi slides per implementazione semaforo)* ## Prod/Cons con buffer di lunghezza finita *(slides per implementazione)* Il processo buffer e' un server che gestisce inserimento ed estrazione dalla coda. Vedi anche esempio con guardie di output, che utilizza primitive di send per mandare i dati al consumatore. ## Prod / Cons con N processi server Il buffer di N dati e' realizzato da N processi dati, produttore e consumatore estrerni. *(slides per implementazione)* Questa soluzione e' semplice, ma presuppone hardware con **elevato parallelismo**. ## Specifica di strategie di priorita' *(slides per implementazione)* I processi aspettano per ottenere una risorsa, ma quando questa si libera viene svegliato il processo con **priorita' piu' alta**. Caso analogo con send asincrona. I clienti in attesa sono inseriti in ordine di priorita' in una coda, e si presuppone un'unica risorsa (non un pool). E' praticamente uguale al caso asincrono. ## Lettori / Scrittori *(slides per implementazione)* Soluzione identica al caso asincrono. In questa soluzione pero' **non e' necessario gestire le code**. ## Note sulle primitive sincrone Difficilmente sono implementate a livello kernel, perche' e' possibile realizzarle con le asincrone. # Chiamate di procedura remota e rendez-vous (esteso) Chiamata di procedura remota e rendez-vous esteso sono due concetti simili: * Chiamata di procedura remota e' relativa alle soluzioni **multithreading** * Rendez-vous esteso e' relativo alle soluzioni single thread (single server con interrupt) La loro funzione e' pero' la stessa: * Il client effettua una richiesta sul server, richiedendo una procedura. Nel caso RPC, questa procedura viene eseguita su un processo (thread) separato. Nel caso del rendez-vous esteso, l'operazione richiesta e' specificata come una serie di istruzioni che possono comparire in un punto qualunque del server. Il server usa quindi un *accept* che interrompe l'esecuzione e passa all'esecuzione delle istruzioni. *(vedi slides per dettagli e implementazione)* ### Esempio RPC: servizio di sveglia Insieme di N processi clienti possono richiedere di essere svegliati da un processo servitore, dopo un tempo da loro prefissato. *(slides per grafico)* Il server utilizzera' quindi un clock, che opera su un processo separato, e una serie di N thread relativi ai singoli processi, che sono spawnati una volta che il clock raggiunge i tempi prefissati. I thread si occupano di svegliare i processi. *(slides per implementazione)* ### Rendez-vous Il servizio richiesto e' specificato come insieme di istruzioni che possono comparire in un punto qualunque del processo servitore: ``` accept (in , out ); (S1, ... , SN) -> S0; ``` * Nota: S1, ... SN sono servizi da eseguire in rendez-vous, mentre S0 e' una procedura eseguita solo dal server, non in rendez-vous. #### Accept * Bloccante: se non sono presenti richieste, provoca la sospensione del server * Se lo stesso servizio e' richiesto da piu' processi, si utilizza una coda FIFO * Lo schema di comunicazione e' quindi **asimmetrico da molti a uno**. *(slides per grafico di esecuzione)* ##### Selezione delle richieste in base ai parametri di ingresso Con accept, la selezione della richiesta da servire **puo' dipendere anche dai parametri d'ingresso della richiesta stessa**. In questo caso la guardia logica che condiziona l'esecuzione dell'azione puo' essere espressa anche in termini dei parametri di ingresso. Questo richiede una doppia interazione tra server e client, la prima per trasmettere i parametri, la seconda per la richiesta stessa. *NB: il numero di parametri deve essere limitato* #### Esempio: sveglia In questo esempio con rendez-vous del processo sveglia ci sono 3 tipi di richieste: *(vedi slides)* *(slides per implementazione)* In questo esempio, il client manda due richieste: nella prima manda il tempo dopo cui vuole essere svegliato, nella seconda manda l'effettiva richiesta di sveglia. Il server riceve la prima richiesta e la memorizza. Quando riceve la seconda richiesta, riordina il vettore *tempo-di-sveglia* in cui ha inserito il tempo indicato, e sveglia il processo dopo il tempo ricevuto. #### Esempio: r&w I lettori fanno tutte le *call*, gli scrittori fanno tutti gli *accept*. *(vedi slides per implementazione)* # Linguaggi CSP: Communication Sequential Process Modello di interazione tra processi, che utilizzano una comunicazione sincrona (di solito sono sulla stessa board, vari processori). *(vedi slides)*