Newsgroup: it.comp.lang.c++
Titolo: Interrupt Service Routine

Vorrei riuscire in C++ a installare un mio vettore di interrupt come facevo
in C.
In quest'ultimo linguaggio mi bastava dichiare un funzione come
void interrupt miafunc() { ... };
e utilizzare la funzione setvect (molto probabilmente non standard, presente
nei compilatori della Borland) per impostare la mia ISR.
Ora vorrei (anzi devo necessariamente) fare la stessa cosa utilizzando al
posto di una funzione il metodo di una classe ma finora non sono riuscito
nel mio intento. Qualcuno saprebbe dirmi come fare (sempre che si possa
fare)?
Ringazio in anticipo chi si interesserà.
Ciao, Giuseppe
---------------------------------------------------------------------------
_Guybrush su IRCNet canale #programmazione
ICQ: 42227764
---------------------------------------------------------------------------

 fare)?
Io non credo, però puoi usarla come funzione C e poi incapsularla nella
classe.
Io avevo incapsulato il gestore della porta parallela bidirezionale (ai
tempi non c'era nè il supporto BIOS nè DOS).
E' un po' quello che fanno le MFC, no?
Comunque una funzione dichiarata come interrupt è un po' particolare, e mi
sembra di ricordare che il manuale Borland specificava che in nessun caso
può essere un metodo di una classe.
Ma ha davvero senso usare un metodo di una classe come gestore di interrupt?
Come lo combini con l'ottica OO di C++? Gli interrrupt sono routine
asincrone, mentre le classi di C++ sono sempre (o con pochissime eccezioni)
sincrone.
Anche se fosse possibile, pensa a come farebbe la povera CPU a risolvere la
chiamata ad un metodo virtuale del tuo gestore di interrupt! Queste sono
cose HW, non SW. Logico che il supporto del C++ sia minimo e
implementation-dependant.
Ciao
--
Alessandro Monti

fare)?
Con le funzioni membro hai alcuni problemi da risolvere, il primo e` che
una normale member function ha un parametro nascosto (this) mentre se
non ricordo male una funzione per interrupt parametri non ne deve avere.
Questo implica che la member function deve essere static.
Inoltre un altro vincolo e` generalmente la rientranza del codice di
gestione dell'interrupt, ma questo da quanto leggo e` un problema di
cui sei sicuramente a conoscenza.
Le restanti operazioni sono legate al s.o. su cui operi e questo non 
l'hai citato, suppongo non si tratti del dos vero?
Se sei sotto windows guarda l'api InterruptRegister
Paolo
-----------------------------------------------------------------
  Paolo Marotta
  Computer Science, University of Pisa
  home:   
http://www.cli.di.unipi.it/~marotta
-----------------------------------------------------------------

implementation-dependant.
Tanto logico non č. In fin dei conti una funzione membro C++ (non virtuale)
equivale in tutto e per tutto ad una funzione C, cioč ad un indirizzo di
memoria. Quindi per quale motivo non permettere di installarla cone ISR?
Mah, so solo che non posso certo per un problema come questo riconvertire
tutta la mia libreria in C (orrore!!!) :-(


Se sei sotto windows guarda l'api InterruptRegister
Gli darò un'occhiata.
Grazie per l'interessamento.


 tutta la mia libreria in C (orrore!!!) :-(
Perchè non tutte le architetture hanno gli interrupt, per esempio :-)
(o comunque non sono accessibili ai programmi utente)
Sarebbe difficile standardizzare qualcosa che su alcune piattaforme non può
funzionare.
--
Alessandro Monti

 funzionare.
Davvero? Allora perché mai hanno standardizzato le funzioni per l'i/o su
console e su file? Non mi dire che tutte le piattaforme dispongono di
dischi, monitor o tastiera!
EMG

fare)?
L'help del Borland C++ 5.02 dice apertamente:
----------
Note:	In C++, only static member functions or non-member functions
can be declared to be an interrupt routine. If you use the prototypes
declared in  dos.h, simply pass the address of an interrupt function
to setvect in any memory model.
----------
Onestamente non capisco il senso di tale frase, visto che comunque
anche una funzione membro di una classe puo' essere dichiarata come
statica. Ad esempio tempo fa per enumerare tutti i font presenti nello
screen device ho usato la funzione EnumFontFamilies passando come
procedura di callback una funzione membro statica della stessa classe.
Eventualmente il problema e' cercare di passare un puntatore
all'oggetto corrente, che in EnumFontFamilies si poteva fare mettendo
il puntatore dell'oggetto corrente nel terzo parametro.
P.S. Se ti serve l'esempio su SetVect te lo posso postare.
Bye.

funzionare.
Uffa, non cominciamo a parlare di standard e portabilità che mi stanno sullo
stomaco :-(


 dischi, monitor o tastiera!
Ma esistevano stampanti, schede perforate, nastri.
E su questo HW le funzioni standard del C mi risultano funzionare.
Certo se hai in mente HW particolare (controllo di un tostapane), allora si
potrebbe solo concludere che non è possibile avere uno standard.
Il C è un linguaggio che si rivolge (con le librerie soprattutto) ad un
sistema che abbia almeno un sistema operativo, pertanto si suppone che
qualcosa esista, e tastiera, monitor, RAM e HD mi sembrano davvero il
minimo.
Se proprio non hai niente di tutto ciò, puoi sempre non includere le
librerie che non ti sarebbero utili (stdio se non hai i/o standard, per
esempio).
Che sia per questo che da sempre anche le librerie standard devi includerle
esplicitamente?
Molte altre cose invece NON sono standard, nel senso che esistono sistemi
completi ed equivalenti in cui alcune cose hanno senso su un'architettura e
non su un altra. Un esempio sono gli interrupt. Un altro le system calls,
altri te li elenco così come mi vengono in mente: nome e numero dei
registri, loro utilizzo, quantità di memoria, modalità di allocazione in
memoria, gestione della memoria, disposizione fisica dei files sulla
periferica di memorizzazione di massa, tipo di memorizzazione sulla
periferica di massa, disposizione dei tasti sulla tastiera, codici dei
caratteri, rappresentazione dei caratteri, dimensione del byte, dimensione
della word, dimensione dell'indirizzo dei puntatori, ...
Come vedi, sono tantissime le cose che non potevano essere standardizzate, e
le funzioni che invece sono andate a far parte dello standard, presuppongono
proprio una minima quantità di "funzionalità standard" che si suppone siano
implementate su qualunque sistema programmabile.
Anche così, nessuno ha mai garantito che un programma C standard sia
compilabile ed eseguibile su TUTTI i sistemi, solo sulla maggior parte.
Credo comunque che queste cose non ti siano nuove, e allora mi spieghi il
senso della tua domanda?
--
Alessandro Monti

 };
Pensi possa andare bene? Non ha variabili globali, e i puntatori puoi stare
tranquillo che saranno trattati come tali.
Devi comunque fare attenzione, perchè la tua funzione ISR, essendo eseguita
in maniera asincrona, *DEVE* lasciare inalterati tutti i registri, pena
crash da paura! Forse sarebbe meglio usare l'assembler.
Come dice Joseph probabilmente devi anche dichiararla static, nel qual caso
*forse* non servono i puntatori.
Però almeno le variabili dovrebbero essere volatile!!!!!
--
Alessandro Monti

 senso della tua domanda?
Il fatto è che non sono d'accordo su una standardizzazione che si ostina
a tener conto di concetti obsoleti. Come ho già detto altre volte, avrei
voluto vedere uno standard più vicino alla realtà e più elastico.
EMG

Però almeno le variabili dovrebbero essere volatile!!!!!
Hai ragione, me l'ero scordato.


P.S. Se ti serve l'esempio su SetVect te lo posso postare.
Grazie ma ce l'ho e poi la so usare ;-)
Grazie per l'interessamento.


 (che non riceve il puntatore this) come fa ad accedervi?
Ehm, forse static? In effetti non ero molto convinto funzionasse cosě come
l'ho scritta.
E fare una classe apposta per x e y e usare puntatori ad essa? Stesso
problema suppongo, ma almeno le classi potrebbero essere globali, no? (non č
differente da avere variabili globali, ma forse *sembra* piů OO) :-)
--
Alessandro Monti

quindi......
Secondo me stai sbagliando...
Ogni metodo non static deve riferire ad una istanza; tale istanza viene
passata al metodo tramite this. Come fa il sistema a sapere a quale
istanza legare il metodo? E` come se tu per gestire un interrupt
volessi che fosse invocata una funzione tipo void Int(Data&)..
Come fa il sistema a calcolare il parametro da passare alla funzione?
O viene chiamata una normale funzione che fa il forward, oppure
il metodo della classe e` dichiarato static (cosi` come tutti i membri
cui deve accedere). In entrambi i casi la funzione direttamente invocata
dall'interrupt non deve ricevere parametri.


Scusa l'ignoranza informatica, ma cos'è la rientranza del codice?
Non e` facile da spiegare, una ISR puo` essere eseguita in qualsiasi
momento, in taluni casi puo` essere invocata anche nel bel mezzo
dell'esecuzione di una istanza della stessa ISR. Un pezzo di codice e`
rientrante se e` capace di gestire una tale situazione.
Un esempio di codice non rientrante e` quello di una routine che 
memorizza le variabili locali in mezzo al codice. Al contrario un
banale esempio di codice rientrante puo` essere quello di una
routine che accede solo a costanti.
Si tratta di una proprieta` non sempre necessaria...e` richiesta quando
piu` invocazioni della stessa ISR possono avvenire concorrentemente.
In molti casi tale proprieta` non e` necessaria, ad esempio gli int dos
non sono rientranti e per questo i TSR non possono invocarle.


La mia libreria è TUTTA ad oggetti :-(
Non e` un problema di OOP, ma di design... infatti le int del mouse
lasciano le loro risposte nei registri della cpu e non in una locazione
di memoria predeterminata.


Ehm, forse static?
Bingo! Esatto! static è l'ideale :-)


Come fa il sistema a calcolare il parametro da passare alla funzione?
Non può farlo e ne sono consapevole. All'inizio (stupidamente) non avevo
considerato il parametro this e non mi capacitavo perchè il compilatore non
mi accettasse il metodo come ISR. Ora ho capito (grazie a voi).


piu` invocazioni della stessa ISR possono avvenire concorrentemente.
Vedi sopra.


di memoria predeterminata.
Noooo, io non sto scrivendo una classe wrapper attorno al driver del mouse,
io sto scrivendo un software che si interfacia direttamente con l'hardware.
Decido io dove andare a mettere i risultati e in questo caso mi interessa
registrarli nelle varibili membro della classe CMouse. Comunque sono
riuscito, tramite dei trucchetti più o meno sporchi, a far funzionare
(teoricamente) il tutto.


 >piu` invocazioni della stessa ISR possono avvenire concorrentemente.
(rispondo qui invece che nel messaggio giusto)
Sotto DOS nessun ISR è garantito essere rientrante.
Ciò vuole dire che un crash è perfettamente legittimo, anche se penso
andrebbe evitato finchè possibile.
Ciò comunque in pratica avviene solo se viene chiamato lo stesso interrupt
prima che il primo abbia finito il lavoro, ovvero mai. (in votis)
--
Alessandro Monti

Sicuramente è necessario per quelli SW.
Nei miei reference della Intel (x CPU 8086 e 386) dice che l'interrupt flag
viene modificato automaticamente, sia in modalità reale che protetta.


rientrante.
Costanti nel senso di dati a sola lettura!


prima che il primo abbia finito il lavoro, ovvero mai. (in votis)
Sotto dos...


 viene modificato automaticamente, sia in modalità reale che protetta.
Cosa significano allora queste frasi ?
Ref:
CD Developers' Insight, file 24319001.pdf, Intel Architecture Software
Developer's Manual, Volume 1: Basic Architecture
-------
The Intel Architecture defines 16 predefined interrupts and exceptions and
224 user defined interrupts, [...] vectors 32 to 255 are the user-defined
interrupts, called MASKABLE INTERRUPTS.
[...]
the difference between an interrupt gate and a trap gate is as follows. If
an interrupt or exception handler is called through an interrupt gate, the
processor clears the interrupt enable (IF) flag [...] to prevent subsequent
interrupts from interfering with the execution of the handler. When a
handler is called through a trap gate, the state of the IF flag is not
changed.
Ref:
CD Developers' Insight, file 24319201.pdf, Intel Architecture Software
Developer's Manual, Volume 3: System programming Guide
-------------
Any external interrupt that is delivered to the processor by means on the
INTR# pin or through the local APIC is called a MASKABLE HARDWARE INTERRUPT.
[...]
All maskable hardware interrupt as a group can be masked by the IF flag
[...]
------
Comunque negli esempi di codice che ho trovato per la scrittura di ISR
c'erano sempre CLI e STI.
--
Alessandro Monti

c'erano sempre CLI e STI.
Strano, non ne capisco il motivo...


Costanti nel senso di dati a sola lettura!
Ah, OK. Mi era venuto il dubbio, per questo ho chiesto.


 Strano, non ne capisco il motivo...
In effetti si riferivano all'intercettazione di interrupt hardware, come la
tastiera. Bho.
Speravo di dare una mano, ma mi sa che sono riuscito a incasinare le idee...
--
Alessandro Monti

 --------------------------------------------------------------------------


ok, spero che quanto da me esposto possa essere di aiuto a qualcuno
Ti ringrazio molto per la risposta e spero anch'io che ciò che hai detto
possa essere d'aiuto a qualcuno altro oltre a me. Devo inoltre dire che
(IMHO) il metodo da te utilizzato per gestire gli interrupt è ottimo.
Ciao, Giuseppe
---------------------------------------------------------------------------
