From: Simone Piccardi Date: Thu, 29 Aug 2002 17:00:36 +0000 (+0000) Subject: Riscritta buona parte dei semafori con SystemV X-Git-Url: https://gapil.gnulinux.it/gitweb/?a=commitdiff_plain;h=78c18e4e71e33917d898013e2d75061c29564ac0;p=gapil.git Riscritta buona parte dei semafori con SystemV --- diff --git a/fileadv.tex b/fileadv.tex index a3118b0..3b0575a 100644 --- a/fileadv.tex +++ b/fileadv.tex @@ -388,10 +388,11 @@ implementata sia direttamente nel kernel, che in user space attraverso l'uso di thread. Al momento\footnote{fino ai kernel della serie 2.4.x, nella serie 2.5.x è però iniziato un lavoro completo di riscrittura di tutto il sistema di I/O, che prevede anche l'introduzione di un nuovo layer per l'I/O - asincrono.} esiste una sola versione stabile di questa interfaccia, quella -delle \acr{glibc}, che è realizzata completamente in user space. Esistono -comunque vari progetti sperimentali (come il KAIO della SGI, o i patch di -Benjamin La Haise) che prevedono un supporto diretto da parte del kernel. + asincrono (effettuato a partire dal 2.5.32).} esiste una sola versione +stabile di questa interfaccia, quella delle \acr{glibc}, che è realizzata +completamente in user space. Esistono comunque vari progetti sperimentali +(come il KAIO della SGI, o i patch di Benjamin La Haise) che prevedono un +supporto diretto da parte del kernel. Lo standard prevede che tutte le operazioni di I/O asincrono siano controllate attraverso l'uso di una apposita struttura \type{aiocb} (il cui nome sta per diff --git a/ipc.tex b/ipc.tex index a7cb576..6bb3836 100644 --- a/ipc.tex +++ b/ipc.tex @@ -1368,7 +1368,7 @@ eseguire; i valori possibili sono: riceveranno un errore di \macro{EIDRM}, e tutti processi in attesa su funzioni di di lettura o di scrittura sulla coda saranno svegliati ricevendo il medesimo errore. Questo comando può essere eseguito solo da un processo - con userid effettivo corrispondente al creatore a o al proprietario della + con userid effettivo corrispondente al creatore o al proprietario della coda, o all'amministratore. \item[\macro{IPC\_SET}] Permette di modificare i permessi ed il proprietario della coda, ed il limite massimo sulle dimensioni del totale dei messaggi in @@ -1415,10 +1415,10 @@ La funzione inserisce il messaggio sulla coda specificata da \param{msqid}; il messaggio ha lunghezza specificata da \param{msgsz} ed è passato attraverso l'argomento \param{msgp}. Quest'ultimo deve venire passato sempre in una forma che corrisponda alla struttura \var{msgbuf} riportata in -\figref{fig:ipc_msbug}. La dimensione massima per il testo di un messaggio +\figref{fig:ipc_msbuf}. La dimensione massima per il testo di un messaggio non può comunque superare il limite \macro{MSGMAX}. -La struttura di \figref{fig:ipc_msbug} comunque è solo un modello, tanto che +La struttura di \figref{fig:ipc_msbuf} comunque è solo un modello, tanto che la definizione contenuta in \file{sys/msg.h} usa esplicitamente per il secondo campo il valore \code{mtext[1]}, che non è di nessuna utilità ai fini pratici. La sola cosa che conta è che abbia come primo membro un campo \var{mtype}, @@ -1428,7 +1428,7 @@ invece pu del messaggio. In generale pertanto per inviare un messaggio con \func{msgsnd} si usa -ridefinire una struttura simile a quella di \figref{fig:ipc_msbug}, adattando +ridefinire una struttura simile a quella di \figref{fig:ipc_msbuf}, adattando alle proprie esigenze il campo \var{mtype}, (o ridefinendo come si vuole il corpo del messaggio, anche con più campi o con strutture più complesse) avendo però la cura di mantenere nel primo campo un valore di tipo \ctyp{long} che ne @@ -1438,7 +1438,7 @@ Si tenga presente che la lunghezza che deve essere indicata in questo argomento è solo quella del messaggio, non quella di tutta la struttura, se cioè \var{message} è una propria struttura che si passa alla funzione, \param{msgsz} dovrà essere uguale a \code{sizeof(message)-sizeof(long)}, (se -consideriamo il caso dell'esempio in \figref{fig:ipc_msbug}, \param{msgsz} +consideriamo il caso dell'esempio in \figref{fig:ipc_msbuf}, \param{msgsz} dovrà essere pari a \macro{LENGHT}). \begin{figure}[!htb] @@ -1452,14 +1452,14 @@ dovr \end{lstlisting} \end{minipage} \normalsize - \caption{Schema della struttura \var{msgbug}, da utilizzare come argomento + \caption{Schema della struttura \var{msgbuf}, da utilizzare come argomento per inviare/ricevere messaggi.} - \label{fig:ipc_msbug} + \label{fig:ipc_msbuf} \end{figure} Per capire meglio il funzionamento della funzione riprendiamo in considerazione la struttura della coda illustrata in -\secref{fig:ipc_mq_schema}. Alla chiamata di \func{msgsnd} il nuovo messaggio +\figref{fig:ipc_mq_schema}. Alla chiamata di \func{msgsnd} il nuovo messaggio sarà aggiunto in fondo alla lista inserendo una nuova struttura \var{msg}, il puntatore \var{msg\_last} di \var{msqid\_ds} verrà aggiornato, come pure il puntatore al messaggio successivo per quello che era il precedente ultimo @@ -1525,9 +1525,9 @@ rimosso dalla stessa) La funzione legge un messaggio dalla coda specificata scrivendolo nel buffer indicato da \param{msgp}, che avrà un formato analogo a quello di -\figref{fig:ipc_msbug}. L'argomento \param{msgsz} indica la lunghezza massima +\figref{fig:ipc_msbuf}. L'argomento \param{msgsz} indica la lunghezza massima del testo del messaggio (equivalente al valore del parametro \macro{LENGHT} -nell'esempio di \figref{fig:ipc_msbug}). +nell'esempio di \figref{fig:ipc_msbuf}). Se il testo del messaggio ha lunghezza inferiore a \param{msgsz} esso viene rimosso dalla coda; in caso contrario, se \param{msgflg} è impostato a @@ -1587,11 +1587,49 @@ il tipo di messaggio, per restituire indietro le frasi ai client. \subsection{Semafori} \label{sec:ipc_sysv_sem} -Il secondo oggetto introdotto dal \textit{System V IPC} è quello dei semafori. -Un semaforo è uno speciale contatore che permette di controllare l'accesso a -risorse condivise. La funzione che permette di creare o ottenere -l'identificatore di un insieme di semafori è \func{semget}, ed il suo prototipo -è: +I semafori non sono meccanismi di intercomunicazione diretta come quelli +(pipe, fifo e code di messaggi) visti finora, e non consentono di scambiare +dati fra processi, ma servono piuttosto come meccanismi di sincronizzazione o +di protezione per le \textsl{sezioni critiche}\index{sezioni critiche} del +codice (si ricordi quanto detto in \secref{sec:proc_race_cond}). + +Un semaforo è uno speciale contatore, mantenuto nel kernel, che permette, a +seconda del suo valore, di consentire o meno la prosecuzione dell'esecuzione +del codice. In questo modo l'accesso ad una risorsa condivisa da più processi +può essere controllato, associando ad essa un semaforo che consente di +assicurare che non più di un processo alla volta possa usarla. + +Il concetto di semaforo è uno dei concetti base nella programmazione ed è +assolutamente generico, così come del tutto generali sono modalità con cui lo +si utilizza. Un processo che deve accedere ad una risorsa eseguirà un +controllo del semaforo: se questo è positivo il suo valore sarà decrementato, +indicando che si è consumato una unità della risorsa, ed il processo potrà +proseguire nell'utilizzo di quest'ultima, provvedendo a rilasciarla, una volta +completate le operazioni volute, reincrementando il semaforo. + +Se al momento del controllo il valore del semaforo è nullo, siamo invece in +una situazione in cui la risorsa non è disponibile, ed il processo si +bloccherà in stato di \textit{sleep} fin quando chi la sta utilizzando non la +rilascerà, incrementando il valore del semaforo. Non appena il semaforo torna +positivo, indicando che la risorsa è disponibile, il processo sarà svegliato, +e si potrà operare come nel caso precedente (decremento del semaforo, accesso +alla risorsa, incremento del semaforo). + +Per poter implementare questo tipo di logica le operazioni di controllo e +decremento del contatore associato al semaforo devono essere atomiche, +pertanto una realizzazione di un oggetto di questo tipo è necessariamente +demandata al kernel. La forma più semplice di semaforo è quella del +\textsl{semaforo binario}, o \textit{mutex}, in cui un valore diverso da zero +(normalmente 1) indica la libertà di accesso, e un valore nullo l'occupazione +della risorsa; in generale però si possono usare semafori con valori interi, +utilizzando il valore del contatore come indicatore del ``numero di risorse'' +ancora disponibili. + +Il sistema di comunicazione interprocesso di System V IPC prevede anche i +semafori, ma gli oggetti utilizzati non sono semafori singoli, ma gruppi di +semafori detti \textsl{insiemi} (o \textit{semaphore set}); la funzione che +permette di creare o ottenere l'identificatore di un insieme di semafori è +\func{semget}, ed il suo prototipo è: \begin{functions} \headdecl{sys/types.h} \headdecl{sys/ipc.h} @@ -1606,15 +1644,55 @@ l'identificatore di un insieme di semafori valori visti per \func{msgget}.} \end{functions} -La funzione è del tutto analoga a \func{msgget} ed identico è l'uso degli -argomenti \param{key} e \param{flag}, per cui non ripeteremo quanto detto al -proposito in \secref{sec:ipc_sysv_mq}. L'argomento \param{nsems} permette di -specificare quanti semafori deve contenere l'insieme qualora se ne richieda la -creazione, e deve essere nullo quando si effettua una richiesta -dell'identificatore di un insieme già esistente. +La funzione è del tutto analoga a \func{msgget}, solo che in questo caso +restituisce l'identificatore di un insieme di semafori, in particolare è +identico l'uso degli argomenti \param{key} e \param{flag}, per cui non +ripeteremo quanto detto al proposito in \secref{sec:ipc_sysv_mq}. L'argomento +\param{nsems} permette di specificare quanti semafori deve contenere l'insieme +quando se ne richieda la creazione, e deve essere nullo quando si effettua una +richiesta dell'identificatore di un insieme già esistente. + +Purtroppo questa implementazione complica inutilmente lo schema elementare che +abbiamo descritto, dato che non è possibile definire un singolo semaforo, ma +se ne deve creare per forza un insieme. Ma questa in definitiva è solo una +complicazione inutile, il problema è che i semafori del System V IPC soffrono +di altri due ben più gravi difetti. + +Il primo grave difetto è che non esiste una funzione che permetta di creare ed +inizializzare un semaforo in un'unica chiamata; occorre prima creare l'insieme +dei semafori con \func{semget} e poi inizializzarlo con \func{semctl}, si +perde così ogni possibilità di esegure atomicamente questa operazione. + +Il secondo difetto deriva dalla caratteristica generale degli oggetti del +System V IPC di essere risorse globali di sistema, che non vengono cancellate +quando nessuno le usa più; ci si così a trova a dover affrontare +esplicitamente il caso in cui un processo termina per un qualche errore, +lasciando un semaforo occupato, che resterà tale fino al successivo riavvio +del sistema. Come vedremo esistono delle modalità per evitare tutto ciò, ma +diventa necessario indicare esplicitamente che si vuole il ripristino del +semaforo all'uscita del processo. + +\begin{figure}[!htb] + \footnotesize \centering + \begin{minipage}[c]{15cm} + \begin{lstlisting}[labelstep=0]{} +struct semid_ds +{ + struct ipc_perm sem_perm; /* operation permission struct */ + time_t sem_otime; /* last semop() time */ + time_t sem_ctime; /* last time changed by semctl() */ + unsigned long int sem_nsems; /* number of semaphores in set */ +}; + \end{lstlisting} + \end{minipage} + \normalsize + \caption{La struttura \var{semid\_ds}, associata a ciascun insieme di + semafori.} + \label{fig:ipc_semid_sd} +\end{figure} A ciascun insieme di semafori è associata una struttura \var{semid\_ds}, -riportata in \figref{fig:ipc_semid_sd}, come nel caso delle code di messaggi +riportata in \figref{fig:ipc_semid_sd}. Come nel caso delle code di messaggi quando si crea un nuovo insieme di semafori con \func{semget} questa struttura viene inizializzata, in particolare il campo \var{sem\_perm} viene inizializzato come illustrato in \secref{sec:ipc_sysv_access_control} (si @@ -1629,29 +1707,42 @@ alterare il semaforo), per quanto riguarda gli altri campi invece: effettuata, viene inizializzato a zero. \end{itemize*} +Ciascun semaforo dell'isnsieme è realizzato come una struttura di tipo +\var{sem} che ne contiene i dati essenziali, la sua definizione\footnote{si è + riportata la definizione originaria del kernel 1.0, che contiene la prima + realizzazione del System V IPC in Linux. In realtà questa struttura ormai è + ridotta ai soli due primi membri, e gli altri vengono calcolati + dinamicamente. La si è utilizzata a scopo di esempio, perché indica tutti i + valori associati ad un semaforo, restituiti dalle funzioni di controllo, e + citati dalla pagine di manuale.} è riportata in \figref{fig:ipc_sem}. Di +norma questa struttura non è accessibile in user space, ma lo sono, in maniera +indiretta, tramite l'uso delle funzioni di controllo, i valori in essa +specificati, che indicano rispettivamente: il valore del semaforo, il +\acr{pid} dell'ultimo processo che ha eseguito una operazione, il numero di +processi in attesa che esso venga incrementato ed il numero di processi in +attesa che esso si annulli. + \begin{figure}[!htb] \footnotesize \centering \begin{minipage}[c]{15cm} \begin{lstlisting}[labelstep=0]{} -struct semid_ds -{ - struct ipc_perm sem_perm; /* operation permission struct */ - time_t sem_otime; /* last semop() time */ - time_t sem_ctime; /* last time changed by semctl() */ - unsigned long int sem_nsems; /* number of semaphores in set */ +struct sem { + short sempid; /* pid of last operation */ + ushort semval; /* current value */ + ushort semncnt; /* num procs awaiting increase in semval */ + ushort semzcnt; /* num procs awaiting semval = 0 */ }; \end{lstlisting} \end{minipage} \normalsize - \caption{La struttura \var{semid\_ds}, associata a ciascun insieme di - semafori.} - \label{fig:ipc_semid_sd} + \caption{La struttura \var{sem}, che contiene i dati di un signolo semaforo.} + \label{fig:ipc_sem} \end{figure} Come per le code di messaggi anche per gli insiemi di semafori esistono una serie di limiti, i cui valori sono associati ad altrettante costanti, che si -sono riportate in \tabref{tab:ipc_sem_limits}. Alcuni di questi sono -accessibili e modificabili al solito attraverso \func{sysctl} o scrivendo +sono riportate in \tabref{tab:ipc_sem_limits}. Alcuni di questi limiti sono +al solito accessibili e modificabili attraverso \func{sysctl} o scrivendo direttamente nel file \file{/proc/sys/kernel/sem}. \begin{table}[htb] @@ -1680,75 +1771,22 @@ direttamente nel file \file{/proc/sys/kernel/sem}. \label{tab:ipc_sem_limits} \end{table} -I semafori non sono meccanismi di intercomunicazione diretta come quelli -(pipe, fifo e code di messaggi) visti finora, e non consentono di scambiare -dati fra processi, ma servono piuttosto come meccanismi di sincronizzazione o -di protezione per le \textsl{sezioni critiche}\index{sezioni critiche} del -codice (si ricordi quanto detto in \secref{sec:proc_race_cond}). - -Un semaforo è uno speciale contatore, mantenuto nel kernel, che permette, a -seconda del suo valore, di consentire o meno la prosecuzione dell'esecuzione -del codice. In questo modo l'accesso ad una risorsa condivisa da più processi -può essere controllato, associando ad essa un semaforo che consente di -assicurare che non più di un processo alla volta possa usarla. - -Il concetto di semaforo è uno dei concetti base nella programmazione ed è -assolutamente generico, così come del tutto generali sono modalità con cui lo -si utilizza. Un processo che deve accedere ad una risorsa eseguirà un -controllo del semaforo: se questo è positivo il suo valore sarà decrementato, -indicando che si è consumato una unità della risorsa, ed il processo potrà -proseguire nell'utilizzo di quest'ultima, provvedendo a rilasciarla, una volta -completate le operazioni volute, reincrementando il semaforo. - -Se al momento del controllo il valore del semaforo è nullo, siamo invece in -una situazione in cui la risorsa non è disponibile, ed il processo si -bloccherà in stato di \textit{sleep} fin quando chi la sta utilizzando non la -rilascerà, incrementando il valore del semaforo. Non appena il semaforo torna -positivo, indicando che la risorsa è disponibile, il processo sarà svegliato, -e si potrà operare come nel caso precedente (decremento del semaforo, accesso -alla risorsa, incremento del semaforo). - -Per poter implementare questo tipo di logica le operazioni di controllo e -decremento del contatore associato al semaforo devono essere atomiche, -pertanto una realizzazione di un oggetto di questo tipo è necessariamente -demandata al kernel. La forma più semplice di semaforo è quella del -\textsl{semaforo binaria}, o \textit{mutex}, in cui un valore diverso da zero -(normalmente 1) indica la libertà di accesso, e un valore nullo l'occupazione -della risorsa; in generale però si possono usare semafori con valori interi, -utilizzando il valore del contatore come indicatore del ``numero di risorse'' -ancora disponibili. - -Purtroppo l'implementazione effettuata nel sistema di intercomunicazione di -System V complica inutilmente questo schema elementare: anzittutto non è -possibile definire un singolo semaforo, ma se ne deve creare per forza un -insieme, specificando il numero di semafori che esso deve contenere con -l'argomento \param{nsem} di \func{semget}. - -Ma i difetti maggiori dei semafori nel System V IPC sono due: il primo è che -non esiste una funzione che permetta di creare ed inizializzare un semaforo in -un'unica operazione atomica; occorre prima creare l'insieme con \func{semget} -e poi inizializzarlo con \func{semctl}. - -Il secondo è che essendo i semafori delle risorse globali di sistema, che non -vengono cancellate quando nessuno le usa più, ci si trova a dover affrontare -esplicitamente il caso in cui un processo termina per un qualche errore, -lasciando un semaforo occupato, che resterà tale per sempre, a meno di non -rimediare la situazione con opportune operazioni di ripristino. - -Come accennato una volta creato l'insieme di semafori per l'inizializzazione -dei valori occorre ricorrere ad una funzione separata, \func{semctl}, che è -quella che effettua le operazioni di controllo; il suo prototipo è: +La funzione che permette di effettuare le varie operazioni di controllo sui +semafori (fra le quali, come accennato, è impropriamente compresa anche la +loro inizializzazione) è \func{semctl}; il suo prototipo è: \begin{functions} \headdecl{sys/types.h} \headdecl{sys/ipc.h} \headdecl{sys/sem.h} - \funcdecl{int semctl(int semid, int semnum, int cmd, ...)} + \funcdecl{int semctl(int semid, int semnum, int cmd)} + \funcdecl{int semctl(int semid, int semnum, int cmd, union semun arg)} Esegue le operazioni di controllo su un semaforo o un insieme di semafori. - \bodydesc{La funzione restituisce 0 in caso di successo o -1 in caso di - errore, nel qual caso \var{errno} viene settato a: + \bodydesc{La funzione restituisce in caso di successo un valore positivo + quanto usata con tre argomenti ed un valore nullo quando usata con + quattro. In caso di errore restituisce -1, ed \var{errno} viene settata a: \begin{errlist} \item[\macro{EACCES}] Il processo non ha i privilegi per eseguire l'operazione richiesta. @@ -1764,9 +1802,87 @@ quella che effettua le operazioni di controllo; il suo prototipo \end{functions} La funzione può avere tre o quattro parametri, a seconda dell'operazione -specificata con \param{cmd} +specificata con \param{cmd}, ed opera o sull'intero insieme specificato da +\param{semid} o sul sigolo semaforo di un insieme, specificato da +\param{semnum}. Qualora la funzione operi con quattro argomenti \param{arg} è +un argomento generico che deve essere una \var{union semun}, si è riportato la +relativa definizione in \figref{fig:ipc_semun}. +\begin{figure}[!htb] + \footnotesize \centering + \begin{minipage}[c]{15cm} + \begin{lstlisting}[labelstep=0]{} +union semun { + int val; /* value for SETVAL */ + struct semid_ds *buf; /* buffer for IPC_STAT, IPC_SET */ + unsigned short *array; /* array for GETALL, SETALL */ + /* Linux specific part: */ + struct seminfo *__buf; /* buffer for IPC_INFO */ +}; + \end{lstlisting} + \end{minipage} + \normalsize + \caption{La definizione dei possibili valori di una \var{union semun}, usata + come quarto argomento della funzione \func{semctl}.} + \label{fig:ipc_semun} +\end{figure} + +Il comportamento della funzione, come il numero di parametri, dipende dal +valore dell'argomento \param{cmd}, che specifica l'azione da intraprendere; i +possibili valori legali per questo argomento sono: +\begin{basedescript}{\desclabelwidth{2.2cm}\desclabelstyle{\nextlinelabel}} +\item[\macro{IPC\_STAT}] Legge i dati dell'insieme di semafori, copiando il + contenuto della relativa struttura \var{semid\_ds} all'indirizzo specificato + con \var{arg.buf}. Occorre avere il permesso di lettura. L'argomento + \param{semnum} viene ignorato. +\item[\macro{IPC\_RMID}] Rimuove l'insieme di semafori e le relative strutture + dati, con effetto immediato. Tutti i processi che erano stato di + \textit{sleep} vengono svegliati, ritornando con un errore di \macro{EIDRM}. + L'userid effettivo del processo deve corrispondere o al creatore o al + proprietario dell'insieme, o all'amministratore. L'argomento \param{semnum} + viene ignorato. +\item[\macro{IPC\_SET}] Permette di modificare i permessi ed il proprietario + dell'insieme. I valori devono essere passati in una struttura + \var{semid\_ds} puntata da \param{arg.buf} di cui saranno usati soltanto i + campi \var{sem\_perm.uid}, \var{sem\_perm.gid} e i nove bit meno + significativi di \var{sem\_perm.mode}. L'userid effettivo del processo deve + corrispondere o al creatore o al proprietario dell'insieme, o + all'amministratore. L'argomento \param{semnum} viene ignorato. +\item[\macro{GETALL}] Restituisce il valore corrente di ciascun semaforo + dell'insieme (il campo \var{semval} di \var{sem}) nel vettore indicato da + \param{arg.array}. Occorre avere il permesso di lettura. L'argomento + \param{semnum} viene ignorato. +\item[\macro{GETNCNT}] Restituisce come valore di ritorno della funzione il + numero di processi in attesa che il semaforo \param{semnum} dell'insieme + venga incrementato (il campo \var{semncnt} di \var{sem}); va invocata con + tre argomenti. Occorre avere il permesso di lettura. +\item[\macro{GETPID}] Restituisce come valore di ritorno della funzione il + \acr{pid} dell'ultimo processo che ha compiuto una operazione sul semaforo + \param{semnum} dell'insieme (il campo \var{sempid} di \var{sem}); va + invocata con tre argomenti. Occorre avere il permesso di lettura. +\item[\macro{GETVAL}] Restituisce come valore di ritorno della funzione il il + valore corrente del semaforo \param{semnum} dell'insieme (il campo + \var{semval} di \var{sem}); va invocata con tre argomenti. Occorre avere il + permesso di lettura. +\item[\macro{GETZCNT}] Restituisce come valore di ritorno della funzione il + numero di processi in attesa che il valore del semaforo \param{semnum} + dell'insieme diventi nullo (il campo \var{semncnt} di \var{sem}); va + invocata con tre argomenti. Occorre avere il permesso di lettura. +\item[\macro{SETALL}] Inizializza il valore di tutti i semafori dell'insieme, + aggiornando il campo \var{sem\_ctime} di \var{semid\_ds}. I valori devono + essere passati nel vettore indicato da \param{arg.array}. Si devono avere i + privilegi di scrittura sul semaforo. L'argomento \param{semnum} viene + ignorato. +\item[\macro{SETVAL}] Inizializza il semaforo \param{semnum} al valore passato + dall'argomento \param{arg.val}, aggiornando il campo \var{sem\_ctime} di + \var{semid\_ds}. Si devono avere i privilegi di scrittura sul semaforo. +\end{basedescript} +Quando si imposta il valore di un semaforo (sia che lo si faccia per tutto +l'insieme con \macro{SETALL}, che per uno solo con \macro{SETVAL}, i processi +in attesa su di esso reagiscono di conseguenza al cambiamento di valore. +Inoltre la coda delle operazioni di ripristino viene cancellata per tutti i +semafori il cui valore viene modificato.