Changeset 2560 for pjproject/trunk/pjlib/src/pj/os_time_win32.c
- Timestamp:
- Mar 30, 2009 6:22:16 PM (16 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
pjproject/trunk/pjlib/src/pj/os_time_win32.c
r2394 r2560 20 20 #include <pj/os.h> 21 21 #include <pj/string.h> 22 #include <pj/log.h> 22 23 #include <windows.h> 23 24 … … 28 29 static LARGE_INTEGER base_time; 29 30 31 #if defined(PJ_WIN32_WINCE) && PJ_WIN32_WINCE 32 # define WINCE_TIME 33 #endif 34 35 #ifdef WINCE_TIME 36 /* Note: 37 * In Windows CE/Windows Mobile platforms, the availability of milliseconds 38 * time resolution in SYSTEMTIME.wMilliseconds depends on the OEM, and most 39 * likely it won't be available. When it's not available, the 40 * SYSTEMTIME.wMilliseconds will contain a constant arbitrary value. 41 * 42 * Because of that, we need to emulate the milliseconds time resolution 43 * using QueryPerformanceCounter() (via pj_get_timestamp() API). However 44 * there is limitation on using this, i.e. the time returned by 45 * pj_gettimeofday() may be off by up to plus/minus 999 msec (the second 46 * part will be correct, however the msec part may be off), because we're 47 * not synchronizing the msec field with the change of value of the "second" 48 * field of the system time. 49 * 50 * Also there is other caveat which need to be handled (and they are 51 * handled by this implementation): 52 * - user may change system time, so pj_gettimeofday() needs to periodically 53 * checks if system time has changed. The period on which system time is 54 * checked is controlled by PJ_WINCE_TIME_CHECK_INTERVAL macro. 55 */ 56 static LARGE_INTEGER g_start_time; /* Time gettimeofday() is first called */ 57 static pj_timestamp g_start_tick; /* TS gettimeofday() is first called */ 58 static pj_timestamp g_last_update; /* Last time check_system_time() is 59 called, to periodically synchronize 60 with up-to-date system time (in case 61 user changes system time). */ 62 static pj_uint64_t g_update_period; /* Period (in TS) check_system_time() 63 should be called. */ 64 65 /* Period on which check_system_time() is called, in seconds */ 66 #ifndef PJ_WINCE_TIME_CHECK_INTERVAL 67 # define PJ_WINCE_TIME_CHECK_INTERVAL (10) 68 #endif 69 70 #endif 71 72 #ifdef WINCE_TIME 73 static pj_status_t init_start_time(void) 74 { 75 SYSTEMTIME st; 76 FILETIME ft; 77 pj_timestamp freq; 78 pj_status_t status; 79 80 GetLocalTime(&st); 81 SystemTimeToFileTime(&st, &ft); 82 83 g_start_time.LowPart = ft.dwLowDateTime; 84 g_start_time.HighPart = ft.dwHighDateTime; 85 g_start_time.QuadPart /= SECS_TO_FT_MULT; 86 g_start_time.QuadPart -= base_time.QuadPart; 87 88 status = pj_get_timestamp(&g_start_tick); 89 if (status != PJ_SUCCESS) 90 return status; 91 92 g_last_update.u64 = g_start_tick.u64; 93 94 status = pj_get_timestamp_freq(&freq); 95 if (status != PJ_SUCCESS) 96 return status; 97 98 g_update_period = PJ_WINCE_TIME_CHECK_INTERVAL * freq.u64; 99 100 PJ_LOG(4,("os_time_win32.c", "WinCE time (re)started")); 101 102 return PJ_SUCCESS; 103 } 104 105 static pj_status_t check_system_time(pj_uint64_t ts_elapsed) 106 { 107 enum { MIS = 5 }; 108 SYSTEMTIME st; 109 FILETIME ft; 110 LARGE_INTEGER cur, calc; 111 DWORD diff; 112 pj_timestamp freq; 113 pj_status_t status; 114 115 /* Get system's current time */ 116 GetLocalTime(&st); 117 SystemTimeToFileTime(&st, &ft); 118 119 cur.LowPart = ft.dwLowDateTime; 120 cur.HighPart = ft.dwHighDateTime; 121 cur.QuadPart /= SECS_TO_FT_MULT; 122 cur.QuadPart -= base_time.QuadPart; 123 124 /* Get our calculated system time */ 125 status = pj_get_timestamp_freq(&freq); 126 if (status != PJ_SUCCESS) 127 return status; 128 129 calc.QuadPart = g_start_time.QuadPart + ts_elapsed / freq.u64; 130 131 /* See the difference between calculated and actual system time */ 132 if (calc.QuadPart >= cur.QuadPart) { 133 diff = (DWORD)(calc.QuadPart - cur.QuadPart); 134 } else { 135 diff = (DWORD)(cur.QuadPart - calc.QuadPart); 136 } 137 138 if (diff > MIS) { 139 /* System time has changed */ 140 PJ_LOG(3,("os_time_win32.c", "WinCE system time changed detected " 141 "(diff=%u)", diff)); 142 status = init_start_time(); 143 } else { 144 status = PJ_SUCCESS; 145 } 146 147 return status; 148 } 149 150 #endif 151 30 152 // Find 1st Jan 1970 as a FILETIME 31 static void get_base_time(void) 32 { 33 SYSTEMTIME st; 34 FILETIME ft; 153 static pj_status_t get_base_time(void) 154 { 155 SYSTEMTIME st; 156 FILETIME ft; 157 pj_status_t status = PJ_SUCCESS; 35 158 36 159 memset(&st,0,sizeof(st)); … … 43 166 base_time.HighPart = ft.dwHighDateTime; 44 167 base_time.QuadPart /= SECS_TO_FT_MULT; 168 169 #ifdef WINCE_TIME 170 pj_enter_critical_section(); 171 status = init_start_time(); 172 pj_leave_critical_section(); 173 #endif 174 175 return status; 45 176 } 46 177 47 178 PJ_DEF(pj_status_t) pj_gettimeofday(pj_time_val *tv) 48 179 { 180 #ifdef WINCE_TIME 181 pj_timestamp tick; 182 pj_uint64_t msec_elapsed; 183 #else 49 184 SYSTEMTIME st; 50 185 FILETIME ft; 51 186 LARGE_INTEGER li; 52 53 if (base_time.QuadPart == 0) 54 get_base_time(); 55 187 #endif 188 pj_status_t status; 189 190 if (base_time.QuadPart == 0) { 191 status = get_base_time(); 192 if (status != PJ_SUCCESS) 193 return status; 194 } 195 196 #ifdef WINCE_TIME 197 do { 198 status = pj_get_timestamp(&tick); 199 if (status != PJ_SUCCESS) 200 return status; 201 202 if (tick.u64 - g_last_update.u64 >= g_update_period) { 203 pj_enter_critical_section(); 204 if (tick.u64 - g_last_update.u64 >= g_update_period) { 205 g_last_update.u64 = tick.u64; 206 check_system_time(tick.u64 - g_start_tick.u64); 207 } 208 pj_leave_critical_section(); 209 } else { 210 break; 211 } 212 } while (1); 213 214 msec_elapsed = pj_elapsed_msec64(&g_start_tick, &tick); 215 216 tv->sec = (long)(g_start_time.QuadPart + msec_elapsed/1000); 217 tv->msec = (long)(msec_elapsed % 1000); 218 #else 219 /* Standard Win32 GetLocalTime */ 56 220 GetLocalTime(&st); 57 221 SystemTimeToFileTime(&st, &ft); … … 64 228 tv->sec = li.LowPart; 65 229 tv->msec = st.wMilliseconds; 230 #endif /* WINCE_TIME */ 66 231 67 232 return PJ_SUCCESS;
Note: See TracChangeset
for help on using the changeset viewer.