OVH Cloud OVH Cloud

Un Timer en dessous de la microseconde: comment faire?

18 réponses
Avatar
chipolatof
Bonjour,

Dans le cadre d'une application qui doit lire l'état du port parallèle
à une fréquence fixe (~10µs), je suis à la recherche d'un moyen
d'obtenir un timer plus "granuleux" que tous les timers standard
disponibles dans Windows (qui sont pour les plus fins à la ms près!).
La seule chose que j'ai trouvé pour l'instant, c'est de faire une
boucle (tant que le temps écoulé depuis la dernière action est < ...),
en prenant directement un calcul sur le nombre de "ticks" processeurs
écoulés depuis la dernière lecture Pour cela j'utilise les routines
QueryPerformanceCounter et QueryPerformanceFrequency.

N'y a-t-il pas d'autre moyen de faire cela? L'idéal serait d'avoir un
handler déclenché toutes les 10µs, et de réaliser la lecture à ce
moment là.
Sinon, y-a-t-il possibilité d'utiliser des routines propres au port
parallèle directement?
J'en suis à essayer avec des morceaux d'assembleur!!!

Précision: sous Win2k & XP!

Merci d'avance pour des pistes!
Christophe

10 réponses

1 2
Avatar
Vincent Burel
"Christophe" wrote in message
news:
Bonjour,

Dans le cadre d'une application qui doit lire l'état du port parallèle
à une fréquence fixe (~10µs), je suis à la recherche d'un moyen
d'obtenir un timer plus "granuleux" que tous les timers standard
disponibles dans Windows (qui sont pour les plus fins à la ms près!).



Peut-être y'a til un moyen de gérer ceci en mode évènementiel (demander à
l'OS d'être prévenu dès que qqc se passe). Mais peut-être avez vous des
contraintes temporelles qui l'interdisent...

La seule chose que j'ai trouvé pour l'instant, c'est de faire une
boucle (tant que le temps écoulé depuis la dernière action est < ...),
en prenant directement un calcul sur le nombre de "ticks" processeurs
écoulés depuis la dernière lecture Pour cela j'utilise les routines
QueryPerformanceCounter et QueryPerformanceFrequency.



En dessous du Time-Slice (environ 5-20 ms pour W95/W98 - 1 à 5ms pour
Win2000 / XP) il n'y a pas de possibilités simple de garantir un timer
véloce, stable et fiable. De plus le TimeSlice constitue une partie du taux
d'erreur temporelle impondérable. Je rappelle que le timeslice est la
granularité temporelle du multitache, il indique la durée minimum pendant
laquelle une tache ne sera pas interrompu par préemption. (si je me gourre,
AMcD me corrigera)... d'où le secret de la vélocité sous windows, faire des
taches (ou partie de tache) qui se finissent avant le timeslice.

N'y a-t-il pas d'autre moyen de faire cela? L'idéal serait d'avoir un
handler déclenché toutes les 10µs, et de réaliser la lecture à ce
moment là.
Sinon, y-a-t-il possibilité d'utiliser des routines propres au port
parallèle directement?
J'en suis à essayer avec des morceaux d'assembleur!!!



Pour descendre en dessous de la ms, il faut faire un driver qui positionne
la callback timer dans un thread de bonne priorité. Sous XP, à mon grand
étonnement, on arrive à gérer des flux temps-réel par tranche de 1 ms ,
alors même que des taches longue sont éxécutées... il semble donc que par le
biais de driver on puisse maintenant priorisé un événement...

ceci dit, malgré tous les efforts qui sont fait pour dôter Windows de
vertues temp-réel, je doute fortement que vous arriviez à controler une base
de temps de 0.01 ms avec un taux d'erreur acceptable. On est typiquement
hors des limites de Windows, qui rappelons le, n'est pas un O/S temps réel.

Techniquement je dirais que la méthode que vous voulez utiliser : un
pooling 10 micro-seconde sur port parallele est une méthode plutot pour du
hardware - au sens carte électronique - . Sous PC, l'idée même de mettre en
place une interruption à 100 Khz (c'est finalement ce que vous voulez faire)
me semble pas très réaliste, même si tout reste possible, ca ne se fera pas
sous windows à mon sens.

VB
Avatar
Pierre Maurette
> Bonjour,

Dans le cadre d'une application qui doit lire l'état du port parallèle
à une fréquence fixe (~10µs), je suis à la recherche d'un moyen
d'obtenir un timer plus "granuleux" que tous les timers standard
disponibles dans Windows (qui sont pour les plus fins à la ms près!).
La seule chose que j'ai trouvé pour l'instant, c'est de faire une
boucle (tant que le temps écoulé depuis la dernière action est < ...),
en prenant directement un calcul sur le nombre de "ticks" processeurs
écoulés depuis la dernière lecture Pour cela j'utilise les routines
QueryPerformanceCounter et QueryPerformanceFrequency.

N'y a-t-il pas d'autre moyen de faire cela? L'idéal serait d'avoir un
handler déclenché toutes les 10µs, et de réaliser la lecture à ce
moment là.
Sinon, y-a-t-il possibilité d'utiliser des routines propres au port
parallèle directement?
J'en suis à essayer avec des morceaux d'assembleur!!!

Précision: sous Win2k & XP!


Sous ces deux OS, particulièrement XP, avec ces contraintes, si elles
sont impératives, je pense que c'est rigoureusement impossible sans
l'écriture d'un pilote de périphérique. Oublions les ruses immondes à
base de passage sauvage en ring0.
L'écriture d'un pilote est certainement possible, il faut quand même
savoir la quantité de code nécessaire à chaque lecture du port. Mais ce
pilote risque d'être contraignant pour le reste du système.
S'il s'agit d'installer l'application sur des postes standards, en
continuant à utiliser 2K/XP normalement, en toute sécurité, il y aurait
une autre voie: un peu de hard.
Selon vous ressources humaines et techniques, le fait qu'il s'agit d'un
produit distribué ou d'une appli one-shot, etc., je vois trois (deux et
demi, en fait)approches ressemblantes:
- Affecter un PC (ce peut être un vieux PC) sous DOS à la surveillance
du port et au prétraitement des informations.
- Même chose en programmant un microcontrôleur genre PIC en dongle sur
le port//.
- Même chose avec une carte dédiée. Certainement inutilement complexe
et demande des moyens.

--
Pierre
Avatar
Bertrand Lenoir-Welter
Il y a des furieux qui s'amusent à créer un noyau système qui détient
toutes les clefs pour faire du temps-réel, et NT devient une tâche à
moindre priorité de ce noyau. Leur appli dialogue directement avec leur
noyau ; le but est de piloter des pulses pour moteurs pas-à-pas via le
port parallèle, et apparemment ça monterait à plus de 20 KHz les doigts
dans le nez, y compris sous 2000/XP. Mais ça me semble un montage assez
osé - faut installer et booter sur leur bidule - et sans aucune garantie
de compatibilité avec les versions futures de Windows. En plus, ça doit
flanquer la pagaille pour les autres applis.

Au demeurant, le port parallèle est sorti des specs Intel/Microsoft
depuis 2002, autant dire qu'on en voit de moins en moins et qu'il faut
pas trop se prendre la tête avec aujourd'hui. J'ai été confronté à ce
problème, et la solution la plus évidente était un générateur de pulses
externe piloté via USB/COM/LPT/Ethernet/etc. Pas cher, pas prioritaire,
pas compliqué, et facilement portable.
Avatar
T.P.
Christophe a écrit :
Bonjour,

Dans le cadre d'une application qui doit lire l'état du port parallèle
à une fréquence fixe (~10µs), je suis à la recherche d'un moyen
d'obtenir un timer plus "granuleux" que tous les timers standard
disponibles dans Windows (qui sont pour les plus fins à la ms près!).
La seule chose que j'ai trouvé pour l'instant, c'est de faire une
boucle (tant que le temps écoulé depuis la dernière action est < ...),
en prenant directement un calcul sur le nombre de "ticks" processeurs
écoulés depuis la dernière lecture Pour cela j'utilise les routines
QueryPerformanceCounter et QueryPerformanceFrequency.

N'y a-t-il pas d'autre moyen de faire cela? L'idéal serait d'avoir un
handler déclenché toutes les 10µs, et de réaliser la lecture à ce
moment là.
Sinon, y-a-t-il possibilité d'utiliser des routines propres au port
parallèle directement?
J'en suis à essayer avec des morceaux d'assembleur!!!

Précision: sous Win2k & XP!

Merci d'avance pour des pistes!
Christophe



J'ai trouvé une page qui évoque le portage de nanosleep sous ms windows
http://mkssoftware.com/docs/man3/nanosleep.3.asp
Avatar
AMcD®
Vincent Burel wrote:

(si je me gourre, AMcD me corrigera)...



Tout ceci est assez compliqué, faut bien le dire. Aujourd'hui, on appelle
cela un quantum (quanta en french je suppose). C'est donc le temps qu'un
thread a pour s'exécuter avant que le kernel vérifie s'il doit passer la
main à un autre thread ou laisser celui en cours continuer.

Sur les Windows moderne, c'est à dire 2K et XP, la valeur par défaut est de
deux intervalles d'horloges. Evidemment, cette valeur dépend de la
plate-forme matérielle. clockres, un programme du site sysinternals permet
de déterminer cette valeur.

http://www.sysinternals.com/ntw2k/source/misc.shtml#clockres

Chez moi, ça donne 10.014400 ms. La même valeur que celle fournie dans le
bouquin Microsoft Windows Internals dont je me sers pour écrire ces lignes.
Apres, c'est simple, à chaque clic d'horloge, le quantum du thread est
décrémenté, quand il vaut 0, soit ça switche (par exemple s'il y a un autre
thread de même priorité -faut bien que tout le monde tourne :-) ), soit il
continue. On parlera des interruptions une autre fois...

En fait, le quanta est stocké sous un multiple de 3. Par exemple 2x3 = 6
pour 2K/XP. La raison en est, simplifions, que ça simplifie les diminutions
de quanta lors des boucles d'attente et évite à un thread de ne jamais être
décrémenté.

On peut modifier la valeur du quantum, 2 intervalles ou 12 intervalles.
Donc, pour ceux qui suivent, de 6 à 36. Sous XP :

Clic droit sur Poste de
travail/Propriétés/Avancé/Performances/Paramètres/Avancé et c'est dans le
cadre "Performance des applications".

Les plus courageux fouilleront ici :
HKLMSYSTEMCurrentControlSetControlPriorityControl et examineront la
variable Win32PrioritySeparation. 6 bits servent à déterminer la valeur du
quantum. Leur valeur n'est pas évidente, vu que c'est séparé en 3 groupes de
2 bits. Je conseille la p. 344 du livre précédent aux fans, parce que c'est
imbitable.

Il faudrait parler de la préemption, de la sauvegarde de contexte, des
thread "idle", des completion I/O, des priorités, des attentes (events,
semaphore, etc.), etc. Mais ça prendrait des heures. C'est quand même des
dizaines de pages sur le bouquin de Solomon/Russinovich.

d'où le secret de
la vélocité sous windows, faire des taches (ou partie de tache) qui
se finissent avant le timeslice.



Clair. On se dit que 10 ms c'est lent, mais en 10 ms un processeur peut
faire des milleirs de trucs. Donc c'est beaucoup. Mais en même temps, des
que tu fait du client/serveur ou du multithread sur des objets partagés, 10
ms c'est pas beaucoup. D'ailleurs, sur les OS Server de Kro, le quanta est
bien plus long, 12 ticks.

--
AMcD®

http://arnold.mcdonald.free.fr/
Avatar
Michel Leunen
AMcD® wrote:

Tout ceci est assez compliqué, faut bien le dire. Aujourd'hui, on appelle
cela un quantum (quanta en french je suppose). C'est donc le temps qu'un
thread a pour s'exécuter avant que le kernel vérifie s'il doit passer la
main à un autre thread ou laisser celui en cours continuer.



[...]

Chez moi, ça donne 10.014400 ms.



Veux-tu dire qu'un thread tourne au maximun 10 ms (sauf s'il se termine
avant) et que ce n'est qu'au bout de ces 10 ms que l'OS switche sur un
autre thread?
Dans mon gestionnaire des tâches, il est renseigné que j'ai pour le
moment 646 threads qui tournent. Ca voudrait dire qu'il faut 6.5 s pour
que tous les threads aient eu le temps de tourner une seule fois. Mon
système devrait être complètement 'unresponsive', non?

Je ne me suis jamais très intéressé à ce truc mais je devrais, je le sens.

Michel
--
Michel Leunen
Avatar
Pierre Maurette
AMcD® a écrit :
Vincent Burel wrote:

(si je me gourre, AMcD me corrigera)...



Tout ceci est assez compliqué, faut bien le dire. Aujourd'hui, on appelle
cela un quantum (quanta en french je suppose).


En latin, en français et en anglais, quantum au singulier et quanta au
pluriel. C'est en général respecté. Contrairement au ravioli, pour
lequel on préfèrera un ravioli / des raviolis à un raviolo / des
ravioli. Mais ça ne change rien à l'intérêt de l'exposé. Ni a celui des
bons raviolis d'Angelo, à Sète ...

[...]
Il faudrait parler de la préemption, de la sauvegarde de contexte, des thread
"idle", des completion I/O, des priorités, des attentes (events, semaphore,
etc.), etc.


J'imagine qu'il existe des processus interruptifs du système dont il
est impossible de se prémunir dans un programme utilisateur, non ?

--
Pierre
Avatar
AMcD®
Michel Leunen wrote:

Chez moi, ça donne 10.014400 ms.





Veux-tu dire qu'un thread tourne au maximun 10 ms (sauf s'il se
termine avant) et que ce n'est qu'au bout de ces 10 ms que l'OS
switche sur un autre thread?



C'est pas moi qui le dis, c'est la doc :-). Ce lien est un peu vieux, mais
sympa à lire :

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dndllpro/html/msdn_scalabil.asp

Cela peut être aussi marrant de lire ce qu'il en est sur CE :

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wcedsn40/html/cgcontimingscheduling.asp
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wcecoreos5/html/wce50conSettingtheThreadQuantum.asp

Dans mon gestionnaire des tâches, il est renseigné que j'ai pour le
moment 646 threads qui tournent. Ca voudrait dire qu'il faut 6.5 s
pour que tous les threads aient eu le temps de tourner une seule
fois. Mon système devrait être complètement 'unresponsive', non?



Non. Regarde bien ton gestionnaire de tâche, il y a des centaines de threads
qui ne font rien qu'attendre. Ils sont donc jamais préemptés si, par
exemple, aucun message ne leur est destiné. Qui plus est, en 10 ms tu peux
en faire des choses sur un processeur ! Mais il est évident que si tu as des
centaines et des centaines de threads qui tournent activement, ça prendra du
temps pour tout exécuter. Lance 100 timers si tu veux t'amuser tiens...

Je ne me suis jamais très intéressé à ce truc mais je devrais, je le
sens.



Dès que tu evux finasser un peu, c'est vite imbitable. Entre les priorités,
les quantas, les interruptions, etc. Un seul bouquin, celui de Russinovich.
Et quelques rares articles.

Si t'aimes le temps réel, ce peut être utile de lire ça...

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnxpesp1/html/tchReal-TimeOperatingSystemsINtimeArchitecture.asp

"but Windows XP Embedded and Windows XP alone cannot manage the strict
determinism required of such systems and it is necessary to enhance the
platform with real-time capabilities"

:-)

--
AMcD®

http://arnold.mcdonald.free.fr/
Avatar
Michel Leunen
AMcD® wrote:

Non. Regarde bien ton gestionnaire de tâche, il y a des centaines de threads
qui ne font rien qu'attendre. Ils sont donc jamais préemptés si, par
exemple, aucun message ne leur est destiné.



Ca doit être le cas puisque effectivement, mon système répond bien et ne
semble pas lent. Du coup, je suis allé relire ce qu'en disait
(brièvement) J.Richter dans son bouquin 'Programming applications for
Windows' et ça semble bien être comme ça que ça se passe.

Merci pour les liens, je vais creuser un peu le sujet.

Michel
--
Michel Leunen
mailto: see my homepage.
C++Builder, BCC5.5.1 Web site:
http://www.leunen.com/
----------------------------------------
Avatar
Vincent Burel
"Michel Leunen" wrote in message
news:425ecf8b$0$20668$
AMcD® wrote:

> Non. Regarde bien ton gestionnaire de tâche, il y a des centaines de


threads
> qui ne font rien qu'attendre. Ils sont donc jamais préemptés si, par
> exemple, aucun message ne leur est destiné.

Ca doit être le cas puisque effectivement, mon système répond bien et ne
semble pas lent. Du coup, je suis allé relire ce qu'en disait
(brièvement) J.Richter dans son bouquin 'Programming applications for
Windows' et ça semble bien être comme ça que ça se passe.



oui, d'ailleurs il suffit de mettre en place 3 ou 4 thread plein pour tout
de suite constater un ralentissement sur les thread de priorité plus basse .
(e.g. economiseur d'écran). Et sur les THREAD plein eux même, puisque 4
THREAD Plein de même priorité se partagerons les ressources processeurs , et
donc feront moins de chose par seconde chacun...

Mais si le THREAD ne fait rien, alors l'OS a le temps de passer le jeton à
2000 Thread à chaque préemption, ca se sent même pas (sur un P4 3Ghz... j'ai
installer un XP sur P200 , ca se sent un peu quand même :-)

VB
1 2