Windows Embedded et le bug de l'an 2038 - year 2038 bug and Windows Embedded

English version at the end...

_____

POSIX définit l'heure comme étant le nombre de secondes écoulées depuis le 1er janvier 1970. Sur la plupart des systèmes 32 bits, le type de la variable stockant cette information est un entier de 32 bits signé. Avec ce format, la dernière date représentable est le mardi 19 janvier 2038, 03:14:07. A la seconde suivante, la valeur décimale deviendra négative et les applications verront une date en 1901... Qu'en est-il pour les systèmes embarqués Microsoft ?

Windows CE

La gestion du temps dans une application native se fera à l'aide des fonctions de la Win32 GetLocalTime, GetSystemTime, GetFileTime s'appuyant sur les structures FILETIME et SYSTEMTIME:

typedef struct _FILETIME {   DWORD dwLowDateTime;   DWORD dwHighDateTime;} FILETIME; FILETIME compte les 100aines de nanosecondes depuis le 1er janvier 1601 sur 64 bits, ce qui nous renvoie à peut près en l'an 58800 et quelques... autant dire que pour l'instant c'est acceptable :-).
typedef struct _SYSTEMTIME {   WORD wYear;   WORD wMonth;   WORD wDayOfWeek;   WORD wDay;   WORD wHour;   WORD wMinute;   WORD wSecond;   WORD wMilliseconds;} SYSTEMTIME; SYSTEMTIME représente la date/heure absolue à la milliseconde.

Les applications .Net s'appuyant sur le Compact Framework feront de l'interop pour accéder aux APIs Win32 citées ci-dessus ou bien utiliseront DateTime. DateTime s'appuie sur FILETIME, ce qui est donc cité ci-dessus s'applique à cette API.

Enfin, dans Windows CE, on peut s'interfacer directement avec le scheduler et utiliser l'API GetTickCount qui renvoie le nombre de millisecondes depuis le boot de la machine sous la forme d'un DWORD. Ce compteur étant sur 32 bits, il boucle après 49,7 jours, à prendre en considération lorsque l'on utilise cette API.

On peut aussi utiliser les API QueryPerformanceCounter et QueryPerformanceFrequency qui permettent d'accéder à un compteur à haute fréquence si celui-ci est présent dans le hardware et si l'OEM a implémenté ces API dans son BSP. Ce compteur utilise des entiers sur 64 bits. On l'utilise en général pour effectuer des mesures de performance en calculant des différentes entre diverses valeurs.

Windows XP Embedded/WEPOS

Windows XPe et WEPOS sont des systèmes ayant le même coeur que Windows XP. Depuis une application native, on pourra utiliser l'API Win32 et les fonctions GetSystemTime, GetLocalTime et GetFileTime. Ce sont les mêmes que celles de Windows CE et elles s'appuient sur les mêmes structures FILETIME et SYSTEMTIME. Si en revanche une application utilise la fonction time() du runtime C, les dates au delà du 19 janvier 2038 à 03:14:07 seront fausses.

Pour les applications .Net, on est dans le même cas que pour les applications .Net pour Windows CE, soit interop pour utiliser les fonctions de la Win32, soit utilisation de DateTime. Donc pas de problème avant l'an 58800 et quelques.

Conclusion

Seules les applications natives utilisant la fonction time() du Runtime C subiront le "bug de l'an 2038". Les applications utilisant cette fonction se font rares dans le monde de l'applicatif classique, mais elles sont moins rares sur les systèmes embarqués ceux-ci ayant une durée de vie plus importante que les systèmes classiques. A étudier pour les bouts de code qui sont censés tourner dans 30 ans (je pense par exemple à l'informatique embarqué dans des modules spatiaux de type sondes destinés à voyager très loin et très longtemps...).

____________

POSIX defines time as the number of seconds elapsed since January 1st, 1970. On most 32 bits systems, the variable storing the time value is a signed 32 bits integer. Using this type of variable, we can reach the date of Tuesday, January 19th, 2038, 03:14:07 AM. When switching to the next second, the decimal value will become negative and all applications will read a date in year 1901... What about Microsoft Embedded Systems?

Windows CE

Time reading in a native application will be made using Win32 APIs GetLocalTime, GetSystemTime, GetFileTime based on the structures FILETIME and SYSTEMTIME:

typedef struct _FILETIME { DWORD dwLowDateTime; DWORD dwHighDateTime;} FILETIME; FILETIME counts hundreds of nanoseconds since January 1st, 1601 using 64 bits, which allows to count until over year 58800... let's say that's acceptable :-).
typedef struct _SYSTEMTIME { WORD wYear; WORD wMonth; WORD wDayOfWeek; WORD wDay; WORD wHour; WORD wMinute; WORD wSecond; WORD wMilliseconds;} SYSTEMTIME; SYSTEMTIME represents absolute Date and Time with a millisecond resolution.

Managed applications running on Compact Framework will use interop to acess Win32 APIs we just talked about or use DateTime. DateTime relies on the FILETIME structure underneath, so what has just been explained applys here too.

In Windows CE, you can also interface with the scheduler using the API GetTickCount, giving back the number of milliseconds elapsed since the system has booted, into a DWORD value. This counter will turn over after 49,7 days. This has to be taken into account when using this API.

You can also use the APIs QueryPerformanceCounter and WueryPerformanceFreuquency that allows to access to a high frequency counter if this one is available in the hardware and if the OEM implements the APIs in its BSP. This counter uses 64 bits integers. This counter is usualy used to make performance measures by calculating differences between several values.

Windows XP Embedded/WEPOS

Windows XPe and WEPOS are based on Windows XP, so in a native application, you can use Win32 APIs GetSystemTime, GetLocalTime,and GetFileTime. These are the same as the ones of Windows CE WIN32 and they are based on the same structures FILETIME and SYSTEMTIME. On the other hand, if an application uses the old C runtime function time(), dates will be wrong after January 19th, 2038 @ 03:14:07.

For managed applications, the conditions are the same as for the Compact Framework ones: wether using interop to access Win32 functions or using DateTime. So, no problem until year 58800 and something.

Conclusion

Only native applications using old C runtime time() function will suffer the "year 2038 bug". The applications using this function are rare in the standard software area, but they are present in the embedded area as embedded software has a longer lifecycle. This has to be checked out in source code that is supposed to run the next 30 years and more (I'm thinking about spatial probes designed to travel far away and for a long time for example).