diff --git a/src/ca/windows_depen.c b/src/ca/windows_depen.c index 8ba3c258d..23ac6c393 100644 --- a/src/ca/windows_depen.c +++ b/src/ca/windows_depen.c @@ -32,6 +32,9 @@ * Modification Log: * ----------------- * $Log$ + * Revision 1.40 1998/06/22 22:32:03 jhill + * EPICS_DLL => EPICS_DLL_NO (so we are backwards compatible + * * Revision 1.39 1998/06/16 00:41:22 jhill * consolodated code here into libCom * @@ -73,6 +76,9 @@ * * Revision 1.19 1995/11/29 19:15:42 jhill * added $Log$ + * added Revision 1.40 1998/06/22 22:32:03 jhill + * added EPICS_DLL => EPICS_DLL_NO (so we are backwards compatible + * added * added Revision 1.39 1998/06/16 00:41:22 jhill * added consolodated code here into libCom * added @@ -115,26 +121,25 @@ * */ +#include + +#ifndef _WIN32 +#error This source is specific to WIN32 +#endif + /* * Windows includes */ #include #include #include -#include #include "epicsVersion.h" #include "bsdSocketResource.h" #include "iocinf.h" -#ifndef _WIN32 -#error This source is specific to WIN32 -#endif - -long offset_time; /* time diff (sec) between 1970 and when windows started */ -DWORD prev_time; -static UINT wTimerRes; -static void init_timers(); +static long offset_time; /* time diff (sec) between 1970 and when windows started */ +static LARGE_INTEGER time_prev, time_freq; /* @@ -142,25 +147,52 @@ static void init_timers(); */ void cac_gettimeval(struct timeval *pt) { - /** - The multi-media timers used here should be good to a millisecond - resolution. However, since the timer rolls back to 0 every 49.7 - days (2^32 ms, 4,294,967.296 sec), it's not very good for - time stamping over long periods (if Windows is restarted more - often than 49 days, it wont be a problem). An attempt is made - to keep the time returned increasing, but there is no guarantee - the UTC time is right after 49 days. - **/ + LARGE_INTEGER time_cur, time_sec, time_remainder; - DWORD win_sys_time; /* time (ms) since windows started */ - - win_sys_time = timeGetTime(); - if (prev_time > win_sys_time) { /* must have been a timer roll-over */ - offset_time += 4294967; /* add number of seconds in 49.7 days */ + /* + * dont need to check status since it was checked once + * during initialization to see if the CPU has HR + * counters (Intel and Mips processors do) + */ + QueryPerformanceCounter (&time_cur); + if (time_prev.QuadPart > time_cur.QuadPart) { /* must have been a timer roll-over */ + double offset; + /* + * must have been a timer roll-over + * It takes 9.223372036855e+18/time_freq sec + * to roll over this counter (time_freq is 1193182 + * sec on my system). This is currently about 245118 years. + * + * attempt to add number of seconds in a 64 bit integer + * in case the timer resolution improves + */ + offset = pow(2.0, 63.0)-1.0/time_freq.QuadPart; + if (offset<=LONG_MAX) { + offset_time += (long) offset; + } + else { + /* + * this problem cant be fixed, but hopefully will never occurr + */ + fprintf (stderr, "%s.%d Timer overflowed\n", __FILE__, __LINE__); + } } - pt->tv_sec = (long)win_sys_time/1000 + offset_time; /* time (sec) since 1970 */ - pt->tv_usec = (long)((win_sys_time % 1000) * 1000); - prev_time = win_sys_time; + time_sec.QuadPart = time_cur.QuadPart / time_freq.QuadPart; + time_remainder.QuadPart = time_cur.QuadPart % time_freq.QuadPart; + if (time_sec.QuadPart > LONG_MAX-offset_time) { + /* + * this problem cant be fixed, but hopefully will never occurr + */ + fprintf (stderr, "%s.%d Timer value larger than storage\n", __FILE__, __LINE__); + pt->tv_sec = 0; + pt->tv_usec = 0; + } + else { + /* add time (sec) since 1970 */ + pt->tv_sec = offset_time + (long)time_sec.QuadPart; + pt->tv_usec = (long)((time_remainder.QuadPart*1000000)/time_freq.QuadPart); + } + time_prev = time_cur; } @@ -204,7 +236,6 @@ void cac_block_for_sg_completion(CASG *pcasg, struct timeval *pTV) int epicsShareAPI ca_task_initialize(void) { int status; - TIMECAPS tc; if (ca_static) { return ECA_NORMAL; @@ -216,6 +247,20 @@ int epicsShareAPI ca_task_initialize(void) return ECA_ALLOCMEM; } + /* + * initialize elapsed time counters + * + * All CPUs running win32 currently have HR + * counters (Intel and Mips processors do) + */ + if (QueryPerformanceCounter (&time_prev)==0) { + return ECA_INTERNAL; + } + if (QueryPerformanceFrequency (&time_freq)==0) { + return ECA_INTERNAL; + } + offset_time = (long)time(NULL) - (long)(time_prev.QuadPart/time_freq.QuadPart); + /* * this code moved here from dllMain() so that the code will also run * in object libraries @@ -225,26 +270,9 @@ int epicsShareAPI ca_task_initialize(void) ca_static = NULL; return ECA_INTERNAL; } - - /* setup multi-media timer */ - if (timeGetDevCaps(&tc, sizeof(TIMECAPS)) != TIMERR_NOERROR) { - fprintf(stderr,"cant get timer info \n"); - bsdSockRelease (); - free (ca_static); - ca_static = NULL; - return ECA_INTERNAL; - } - /* set for 1 ms resoulution */ - wTimerRes = min(max(tc.wPeriodMin, 1), tc.wPeriodMax); - status = timeBeginPeriod(wTimerRes); - if (status != TIMERR_NOERROR) - fprintf(stderr,"timer setup failed\n"); - offset_time = (long)time(NULL) - (long)timeGetTime()/1000; - prev_time = timeGetTime(); status = ca_os_independent_init (); if (status != ECA_NORMAL) { - timeEndPeriod (wTimerRes); bsdSockRelease (); free (ca_static); ca_static = NULL; @@ -274,8 +302,6 @@ int epicsShareAPI ca_task_exit (void) * this code moved here from dllMain() so that the code will also run * in object libraries */ - timeEndPeriod (wTimerRes); - bsdSockRelease (); return ECA_NORMAL; @@ -284,30 +310,26 @@ int epicsShareAPI ca_task_exit (void) /* * - * This should work on any POSIX compliant OS + * obtain the local user name * * o Indicates failure by setting ptr to nill */ char *localUserName() { - int length; - char *pName; - char *pTmp; - char Uname[] = ""; + TCHAR tmpStr[256]; + DWORD bufsize = sizeof(tmpStr); + char *pTmp; - pName = getenv("USERNAME"); - if (!pName) { - pName = Uname; + if (!GetUserName(tmpStr, &bufsize)) { + tmpStr[0] = '\0'; + bufsize = 1; } - length = strlen(pName)+1; - pTmp = malloc(length); - if(!pTmp){ - return pTmp; + pTmp = malloc (bufsize); + if (pTmp!=NULL) { + strncpy(pTmp, tmpStr, bufsize-1); + pTmp[bufsize-1] = '\0'; } - strncpy(pTmp, pName, length-1); - pTmp[length-1] = '\0'; - return pTmp; } @@ -319,16 +341,10 @@ char *localUserName() void ca_spawn_repeater() { BOOL status; - char *pImageName; + char *pImageName = "caRepeater.exe"; STARTUPINFO startupInfo; PROCESS_INFORMATION processInfo; - /* - * running in the repeater process - * if here - */ - pImageName = "caRepeater.exe"; - // // This is not called if the repeater is known to be // already running. (in the event of a race condition @@ -373,12 +389,18 @@ void ca_spawn_repeater() "Failed to start the EPICS CA Repeater -", pImageName, errStrMsgBuf, - "Changes may be required in your \"path\" environement variable."}; + "Changes may be required in your \"path\" environment variable.", + "PATH = ", + getenv ("path")}; + + if (pFmtArgs[5]==NULL) { + pFmtArgs[5] = ""; + } W32status = FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ARGUMENT_ARRAY | 80, - "%1 \"%2\". %3 %4", + "%1 \"%2\". %3 %4 %5 \"%6\"", 0, MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language (LPTSTR) &complteMsgBuf, @@ -697,13 +719,29 @@ void epicsShareAPI caDiscoverInterfaces(ELLLIST *pList, SOCKET socket, * most of the code here was moved to ca_task_initialize and ca_task_exit() * so that the code will also run in object libraries */ -BOOL epicsShareAPI DllMain(HANDLE hModule, DWORD dwReason, LPVOID lpReserved) +BOOL epicsShareAPI DllMain (HANDLE hModule, DWORD dwReason, LPVOID lpReserved) { int status; switch (dwReason) { case DLL_PROCESS_ATTACH: +# if defined(_DEBUG) && 0 + { + char name[256]; + char mname[80]; + DWORD nchars; + + nchars = GetModuleFileName (hModule, mname, 80); + if (!nchars) { + strcpy (mname,"Unknown"); + } + sprintf(name,"Process Attach\n\nBuild Date: %s\nBuild Time: %s\n" + "Module Name: %s", __DATE__, __TIME__, mname); + MessageBox (NULL, name, "CA.DLL Version", MB_OK); + } +# endif + status = ca_task_initialize(); if (status!=ECA_NORMAL) { return FALSE;