Newsgroup: it.comp.programmare.win32
Titolo: Sincronizzazione di thread

 writes:
EB> Ho notato che inserendo dei tempi di ritardo nel loop di controllo
EB> all'interno del thread1, tutto funziona correttamente; eliminando questi
EB> ritardi, l'applicazione di TEST si blocca sulla richiesta di entrare nella
EB> sezione critica.
Forse  ho un  idea.  Sleep(0) provoca  un  immediato rescheduling  dei
thread  in attesa della  CPU (può  accadere che  il thread  che chiama
Sleep(0) riceva  immediatamente la CPU  se nessun thread  con priorità
maggiore o uguale alla sua è ready), quindi la CPU arriva al thread di
TEST con la sezione libera. 
A naso,  (non ho  visto il  codice) c'è una  chiamata in  Thread1, tra
l'acquisizione ed  il rilascio della  sezione critica, che  provoca il
rescheduling ma in  questo caso il thread di TEST  si trova la sezione
occupata e cede  subito la CPU. La cosa strana  sarebbe, che stando al
Richter la  LeaveCriticalSection dovrebbe svegliare uno  dei thread in
attesa sulla  critical section  (leggi quello di  TEST). Ma  mi puzza,
leggendo un vecchio help del Win32 SDK
"The threads of a single process can use a critical section object to
provide mutually exclusive access to a shared resource. For similar
synchronization between the threads of different processes, use a
mutex object."
che il  risveglio avvenga  solo per thread  dello stesso  processo. Se
TEST è un processo diverso allora ecco che serve la Sleep(0).
Oppure usa un mutex come  suggerisce Microsoft. Loro sanno come si usa
Windows :)
\begin{echelon}
Ft. Meade NSA quiche CIA DES plutonium Kennedy Noriega
counter-intelligence fissionable Mossad Delta Force cryptographic
colonel Qaddafi
\end{echelon}
\begin{avviso}
 
Attenzione: Leggersi lo header riguardo al mio e-mail!
Warning: read header for infos about my e-mail.
\end{avviso}
+----------------------------------------------------------------+
| Gian Uberto Lauri * "So, are you working on fixing that bug    |
| 
sa...@eng.it
      *  *now* or leaving it until later ?" - YES  |
+----------------------------------------------------------------+

 ::LeaveCriticalSection (&cs);
Strano. Il consiglio che ti hanno dato gli altri di usare un mutex e`
senz'altro valido, ma non sono assolutamente d'accordo sul resto: il tuo
codice dovrebbe funzionare, con o senza la Sleep(). Prima di usare
queste funzioni hai chiamato InitializeCriticalSection()?
---
Bye! Lorenzo Lutti
http://antani.virtualave.net/

Ho questo problema:
ho una DLL che crea un thread1 con loop infinito di accesso alla seriale;
ho un programma di TEST della DLL che, occasionalmente, puo' accedere alla
seriale;
ho deciso di serializzare l'accesso alla seriale utilizzando le Sezioni
Critiche (API).
Ho notato che inserendo dei tempi di ritardo nel loop di controllo
all'interno del thread1, tutto funziona correttamente; eliminando questi
ritardi, l'applicazione di TEST si blocca sulla richiesta di entrare nella
sezione critica.
Thread1
    while (1)
    {
        ::EnterCriticalSection(&cs);
        Accesso alla seriale
        ::LeaveCriticalSection (&cs);
//      ::Sleep(0);
    }
TEST
        ::EnterCriticalSection(&cs);
        Accesso alla seriale
        ::LeaveCriticalSection (&cs);
Il programma di test si blocca sull'istruzione EnterCriticalSection.
Qualcuno ha una idea?????
Grazie comunque per l'attenzione
Elena

:

Questo potrebbe succedere se i thread hanno livelli di priorità e non 
vengono compiute operazioni tra la LeaveCriticalSection e la successiva 
Enter. Se il thread di controllo della seriale ha priorità più alta 
rispetto al thread di test riuscirà ad acquisire quasi sempre la critical 
section (praticamente sempre se la differenza di priorità è marcata) poichè 
verrà rischedulato prima del thread di test. La Sleep(0) costringe il 
thread che controlla la seriale a rilasciare il suo quanto di schedulazione  
agli altri thread e quindi al thread che è in attesa sulla stessa critical 
section.
Forse utilizzando un mutex (che, a differenza delle critical section, è 
gestito a livello kernel) potresti evitare di utilizzare Sleep().
Potresti anche alzare il livello di priorità del thread di test nel momento 
in cui cerca di accedere alla seriale (ma questo potrebbe creare altri 
problemi e complicarti la vita nel momento in cui dovessi cambiare la 
priorità di default del thread seriale).
Se hai bisogno che il thread di test della seriale acquisisca il controllo 
della porta appena possibile (terminata l'esecuzione di un ciclo del loop), 
potresti utilizzare due eventi autoreset ("sblocco seriale" e "fine test") 
e un flag (la variabile dovrebbe essere dichiarata "volatile" per evitare 
che, causa ottimizzazioni del compilatore, sia associata a un registro del 
processore e mai riletta dalla memoria).
Il thread di test setta il flag e si mette in attesa sull'evento "sblocco 
della seriale".
Il thread seriale completa un ciclo e controlla il flag, se il flag è 
settato, setta l'evento di "sblocco della seriale" e si mette in attesa 
sull'evento "fine test".
Il thread di test ("risvegliato" dal set dell'evento), può accedere alla 
seriale e, una volta completate le sue operazioni, deve settare l'evento di 
"fine test" per riattivare il thread di polling.
-- 
Valter Minute
min...@inwind.it
 (the reply address of this message is invalid)

 ha scritto nel messaggio
news:90o904$sae$1...@zamboni.dsnet.it...

In un mondo perfetto forse il tuo programma potrebbe funzionare.
In windows le cose vanno diversamente. Cosi' come e' strutturato
il loop e' evidente che il thread1 non rilascia mai la sezione critica
al sistema bloccando di conseguenza l'accesso al thread principale.
Dovresti avere una gran fortuna nel beccare il time slice ESATTO
che libera la sezione critica e passa il controllo allo scheduler.
Quante volte puo' realisticamente accadere? IMHO molte poche.
Il fatto che con Sleep(0) il tuo programma funzioni e dovuto alla
particolarita' di quella chiamata che avvisa lo scheduler che il
thread non ha piu' bisogno del time slice rimanente. Lo scheduler
obbedisce e passa al thread successivo. Condizione perfetta perche'
il thread principale possa entrare in critical section.
Ciao,
Il Michett@
--

 writes:
IM> Ho detto una scemata. 
Non  so,  la   documentazione  di  MS  dice  di   usare  i  mutex  per
sincronizzare più _processi_ (perché si passa per il kernel, come dice
Lorenzo).
IM> Per quanto riguarda InitializeCriticalSection() lo
IM> tenderei ad escluidere come causa del problema visto che il kernel ti
IM> caccia fuori subito se entri in una sezione critica non inizializzata
IM> (access violation exception).
Concordo.
IM> Pero'  non  spiegherebbe  perche'   con  Sleep(0)  tutto  torni  a
IM> funzionare....mistero.
Direi perché provochi un rescheduling generale e non uno che, a quanto
pare, è limitato al singolo processo...
\begin{echelon}
ammunition Ft. Bragg Treasury Clinton munitions Peking domestic
disruption SEAL Team 6 North Korea explosion Soviet terrorist Noriega
BATF Delta Force


 pare, è limitato al singolo processo...
Sleep(0) non provoca un rescheduling dei processi ma consente al running
thread di eliminare il riferimento del suo time slice consentendo allo
scheduler di communtare un qualsiasi altro thread di uguale priorita' che
e' pronto per essere eseguito. Se nessun altro thread di priorita' uguale
o maggiore e' pronto la funzione ritorna immediatamente. Quando parlavo di
mistero mi riferivo alla supposizione di una chiamata multipla di
EnterCriticalSection() che di fatto blocca qualunque altro thread che usa
quella sezione critica. Ma il fatto che Sleep(0) faceva rifunzionare il
tutto non avvalorava l'ipotesi (finche il contatore della sezione critica
riferito ad un determinato thread non va a zero non c'e funzione che tenga).
Senza codice e' difficile fare supposizioni... :-\
Ciao,
Il Michett@
--

> pare, è limitato al singolo processo...
IM> Sleep(0) non provoca un rescheduling dei processi ma consente al running
IM> thread di eliminare il riferimento del suo time slice consentendo allo
IM> scheduler di communtare un qualsiasi altro thread di uguale priorita' che
IM> e' pronto per essere eseguito.
Ovvero provoca un rescheduling, perché a casa mia si chiama così questo ambaradan che, guarda caso, è compito dello scheduler...
IM> Se nessun altro thread di priorita' uguale
IM> o maggiore e' pronto la funzione ritorna immediatamente. 
Ovvero la CPU viene  riassegnata immediatamente al processo che chiama
Sleep(0).
IM> Senza codice e' difficile fare supposizioni... :-\
Verissimo.
\begin{echelon}
terrorist NORAD Ft. Bragg domestic disruption Ft. Meade PLO
fissionable bomb FBI Legion of Doom jihad plutonium Delta Force radar
Noriega


 Sleep(0).
Giustamente, essendo running. Pero' qua' c'e' un altro thread nel medesimo
stato, quello che aspetta di entrare in sezione critica.
Ai notato che questo thread a preso la piega di un "debug (processo)
indiziario?". Chissa cosa dice "l'ingegneria" (vocatura) a proposito? :-)
Ciao,
Il Michett@
--

 writes:
IM> Ai notato che questo thread a preso la piega di un "debug (processo)
IM> indiziario?". Chissa cosa dice "l'ingegneria" (vocatura) a proposito? :-)
A me assomiglia di più alle indagini filosofiche di Platone :)
\begin{echelon}
CIA Waco, Texas North Korea Ft. Meade FBI Honduras Cocaine
supercomputer [Hello to all my fans in domestic surveillance] NORAD
arrangements NSA spy terrorist Ortega


 IM> Senza codice e' difficile fare supposizioni... :-\
perfettamente d'accordo.. aggiungerei che anche conoscere la piattaforma su
cui e' stato
provato aiuterebbe molto...
Saluti,
 Walker Boh

 resettato, cosa che puo' non accadere in caso si ponga in  waiting.. ne
Saluti,
 Walker Boh

 writes:
W> in nt/2k difatti questo non viene resettato,
Il questo a cui ti riferisci è contatore di uso del time slice ?
(nota : non mi pare che qualcuno abbia detto che la Sleep(0) mette
 il thread in wait...)
\begin{echelon}
Albanian Clinton cryptographic nuclear Ft. Bragg Khaddafi Noriega FBI
smuggle munitions Cocaine [Hello to all my fans in domestic
surveillance] Peking strategic spy


stato, quello che aspetta di entrare in sezione critica
mea culpa per aver estrapolato solo parte del discorso per il quoting.. cmq
il mio messaggio era indirizzato a precisare alcuni concetti contenuti nei
precedenti post e che contenevano alcune imprecisioni (o semplicemente
espressioni infelici.. dato che mi rendo conto che non e' facile tradurre in
parole concetti non banali..).
Saluti,
 Walker Boh