erlug
[Top] [All Lists]

Re: [Erlug] [jas@xxxxxxxxxxxxxxxxxxx: [IB-Architect] Fine Granuality Thr

To: erlug@xxxxxxxxxxxxxx
Subject: Re: [Erlug] [jas@xxxxxxxxxxxxxxxxxxx: [IB-Architect] Fine Granuality Threading on Linux]
From: Davide Bolcioni <w7dmotu6hjru1001@xxxxxxxxxxxxxx>
Date: Wed, 27 Mar 2002 22:19:52 +0100
Matteo Sgalaberni sgala@xxxxxxxxx [mlerlug/erlug list] wrote:

Cosa ne dite di quello che dice Jim in questa email? Essendo
completamente ignorante in materia vorrei avere un parere su queste cose
anche da altri.


Questa è una faccenda con cui ho litigato anche io.


The first problem is that gdb (and presumably any other debugger)
can't be used on a multi-threaded system under load.  The problem
is an unfortunate interaction between ptrace (the Unix debugging
mechanism) and the Linux implementation of pthreads.  The basic
ptrace mechanism works this way: a signal intended for the target
process causes the target process to stall while the signal
is delivered to the debugging process, which figures out what to
do, then restarts the target process.  The Linux threading
mechanism uses a separate OS process for each thread.  Synchronization
is performed by the pthread mutex calls.  When one thread (process)
fails to acquire a mutex, it goes to sleep.  When another thread
releases the mutex, it sends a signal to all sleeping threads
(in fact, all threads) to wake up and look around.  Unfortunately,
when the target process/threads are under control of the debugger,
there is a very complex multi-process dance involving (apparently)
multiple debugger interactions per wake up.  Kinda like the
guys who designed the threads didn't talk to the guys who designed
ptrace or one or the other didn't care.


Concordo in pieno. L'implementazione del multithreading POSIX su

Linux ha i difetti appena esposti; il kernel non offre alcuni
meccanismi che sarebbero necessari per uno schema davvero
funzionante. Un tempo pensavo che presto la comunità Linux
avrebbe trovato uno schema di multithreading più evoluto
dei pthreads (per le pagine di pubblicazioni che si sono fatte
sul multithreading sono state abbattute foreste intere) ma dopo
aver letto vari articoli sul design che sta dietro a POSIX sto
cominciando a ricredermi.

Ad esempio: il meccanismo di "cancellation" di pthread consente
di avere un thread che viene "ucciso" dall'esterno in un momento
arbitrario dando modo ai distruttori delle istanze C++ di essere
eseguiti correttamente, cosa che sotto Win32 non si riesce a fare
perchè non c'è l'equivalente della cancellation: TerminateThread()
è immediato e i distruttori non hanno chance.


A second problem is implementing a use-count mechanism to
control object lifetimes in a multi-threaded environment.
The two alternatives are to use mutexes or other synchronization
mechanisms to protect all addRef/release calls (very, very
expensive) or to use interlocked increment/decrement mechanisms.
Unfortunately, while Microsoft provides intrinsic
InterlockedIncrement/InterlockedDecrement functions that perform
atomic multiprocessor interlocked operations that correctly
return the result of the operation.  Unfortunately, there
are no such functions available on Linux.  Atomic.h provides
interlocked increment/decrement, but they don't return values.
Interestingly enough, Google couldn't find any example of
the Intel instruction sequences required to implement the
necessary atomic operations using the GNU assembler dialect.


Qui Jim mi delude. Usare reference counting tra thread di

esecuzione distinti è *sbagliato* punto e basta: l'overhead
del reference counting è già discutibile nel contesto di un
singolo thread, figuriamoci se devo anche fare della
sincronizzazione comunque implementata.

Un modo semplice di gestire la vita di un oggetto condiviso
è il seguente: un thread è il proprietario, di solito chi
lo ha creato. Se un thread vuole usarlo deve chiamare il
proprietario, usando una funzione implementata in mutua
esclusione: il proprietario registra *il thread* come cliente
e basta, va bene anche una lista se sono "pochi". In seguito
il cliente chiamerà metodi dell'oggetto così ottenuto, di
solito ancora in mutua esclusione visto che condivido un
oggetto solo se mi interessa condividere il suo stato e di
solito non riesco a fare a meno della mutua esclusione (comunque
dato che l'oggetto è l'unico conoscitore di se stesso spazio
per ottimizzare ne avrebbe) *ma* di norma non modificherà
più la propria situazione di cliente dell'oggetto. Solo a fine
thread ci sarà bisogno di deregistrare il cliente; in caso di
crash è facile controllare che il thread è morto e deregistrarlo
d'autorità, e in caso di loop il thread in loop non sarebbe
comunque in grado di decrementare il reference count e liberare
la risorsa.

Lo schema appena descritto si basa su questo assunto: per un

thread che ha bisogno di un oggetto condiviso, tale oggetto

condiviso è "importante" e di solito tale oggetto è singolo
oppure è una struttura di oggetti significativa nel suo
insieme (un array, un albero). C'è un'importante eccezione: in
un linguaggio interpretato, il thread può anche rientrare in
tale schema ma il runtime non ha un modo semplice di notarlo e
quindi occorre usare il reference counting per oggetto, non per
relazione tra thread. COM era obbligato a scegliere la soluzione
che facesse funzionare meglio Visual Basic.


Davide Bolcioni

--
There is no place like /home.




<Prev in Thread] Current Thread [Next in Thread>