Quelques remarques en attendant que tes algos soit spécifiés et que l'on puisse te donner une réponse précise.
si ton interruption ne se fait pas interrompre, un volatile dans le code de l'interruption ne sert effectivement à rien.
un volatile dans le code "main" peut-être utile mais certainement pas suffisante (enfin faut voir ton algo toujours). Je conjecture que tu auras quand même besoin d'implémenter un mécanisme de type mutex pour te prémunir des problèmes de TOCTOU.
inspecte le code assembleur pour être sûr de savoir ce que ton compilo a produit.
mettre volatile est souvent une fausse bonne idée. Je te laisse rechercher les références de Linus sur la LKML ;-) La démonstration suit...
Admettons que ton main ressemble à cela:
// pseudocode, addresse du buffer assimilée à zéro,,,
if (tail < head)
sz = tail + (bufsz - head); // le buffer a "wrappé"
else
sz = tail - head;
if (sz >= MIN_COPY) {
copy(head, copy_size); // gère le wrapping
move_head(&head, copy_size); // idem
}
// loop...
Au niveu de l'interruption:
//calculer sz comme au dessus, puis calculer l'espace libre
freesz = bufsz - sz;
if (freesz >= neededsz) {
while (neededsz--) {
*tail = data; // ??
if (tail == bufz - 1) // wrap ?
tail = 0;
else
tail++;
}
} else {
*overrun = 1;
}
NB: c'est une implémentation naïve d'un buffer circulaire. Je n'ai jamais fait ce genre de chose, je te conseille quand même de consulter wikipedia avant ;-)
Donc nous avons ton interruption qui modifie tail et ton main qui modifie head.
Il y a-t-il un risque que l'interruption utilise une mauvaise valeur pour head ? C'est-à-dire entre le momen où tu calcules freesz et le moment où tu modifie tail.
-> Non je ne crois pas, au pire tu as un overrun du à un freesz sous-estimé.
Il y a-t-il un risque que main utilise une mauvaise valeur de tail ? Idem, non je ne crois pas.
Le problème se situe au moment où l'on calcule sz et freesz !! En fait là tu ne veux surtout pas de volatile : que se passerait-il si tail est accèdée en volatile et qu'une interruption fait wrapper tail et survient juste après que tu aies testé qu'il n'y a pas de wrap ? Oops un freesz < 0... ça sent pas bon hein... ;-)
Donc bref: tu copies tes volatiles dans des variables locales au début de ta routine pour être certain que tu n'accède pas à tes variables en ram directement. Ton algo doit être conçu pour fonctionner sur des valeurs qui ne reflètent peut-être plus la réalité mais qui son cohérentes entre elles, pas pour fonctionner avec des valeurs certes actuelles mais qui changent au gré du vent/des lignes!!!
(Ma) conclusion : pas besoin de mutex, surtout pas besoin de volatile, sous réserve que le code "main" soit dans une fonction séparée.
Maintenant si tu passes à plusieurs producteurs/consommateurs, ben ça se complique : ne le fais pas, utilise plusieurs buffers :p
PS: je viens de me rendre compte que c'est l'inverse que tu veux faire, soit vider un buffer par une interruption. Cela revient au même.
[^] # E_NOENOUGH_INFO | E_UNNEEDED
Posté par benja . En réponse au message Volatile, struct et interruptions.. Évalué à 2. Dernière modification le 14 janvier 2016 à 22:28.
Quelques remarques en attendant que tes algos soit spécifiés et que l'on puisse te donner une réponse précise.
si ton interruption ne se fait pas interrompre, un volatile dans le code de l'interruption ne sert effectivement à rien.
un volatile dans le code "main" peut-être utile mais certainement pas suffisante (enfin faut voir ton algo toujours). Je conjecture que tu auras quand même besoin d'implémenter un mécanisme de type mutex pour te prémunir des problèmes de TOCTOU.
inspecte le code assembleur pour être sûr de savoir ce que ton compilo a produit.
mettre volatile est souvent une fausse bonne idée. Je te laisse rechercher les références de Linus sur la LKML ;-) La démonstration suit...
Admettons que ton main ressemble à cela:
Au niveu de l'interruption:
NB: c'est une implémentation naïve d'un buffer circulaire. Je n'ai jamais fait ce genre de chose, je te conseille quand même de consulter wikipedia avant ;-)
Donc nous avons ton interruption qui modifie tail et ton main qui modifie head.
Il y a-t-il un risque que l'interruption utilise une mauvaise valeur pour head ? C'est-à-dire entre le momen où tu calcules freesz et le moment où tu modifie tail.
-> Non je ne crois pas, au pire tu as un overrun du à un freesz sous-estimé.
Il y a-t-il un risque que main utilise une mauvaise valeur de tail ? Idem, non je ne crois pas.
Le problème se situe au moment où l'on calcule sz et freesz !! En fait là tu ne veux surtout pas de volatile : que se passerait-il si tail est accèdée en volatile et qu'une interruption fait wrapper tail et survient juste après que tu aies testé qu'il n'y a pas de wrap ? Oops un freesz < 0... ça sent pas bon hein... ;-)
Donc bref: tu copies tes volatiles dans des variables locales au début de ta routine pour être certain que tu n'accède pas à tes variables en ram directement. Ton algo doit être conçu pour fonctionner sur des valeurs qui ne reflètent peut-être plus la réalité mais qui son cohérentes entre elles, pas pour fonctionner avec des valeurs certes actuelles mais qui changent au gré du vent/des lignes!!!
(Ma) conclusion : pas besoin de mutex, surtout pas besoin de volatile, sous réserve que le code "main" soit dans une fonction séparée.
Maintenant si tu passes à plusieurs producteurs/consommateurs, ben ça se complique : ne le fais pas, utilise plusieurs buffers :p
PS: je viens de me rendre compte que c'est l'inverse que tu veux faire, soit vider un buffer par une interruption. Cela revient au même.