diff options
author | Evgeny Grin (Karlson2k) <k2k@narod.ru> | 2015-08-27 09:43:09 +0000 |
---|---|---|
committer | Evgeny Grin (Karlson2k) <k2k@narod.ru> | 2015-08-27 09:43:09 +0000 |
commit | 70f7ad46ebc58f18599be8356751edda162ff435 (patch) | |
tree | 14f578c741051bb3b0ca660bd2e7e0903a086128 /src | |
parent | 0d2688a98bfc4f32b393fc581ec04e97d9b11449 (diff) | |
download | libmicrohttpd-70f7ad46ebc58f18599be8356751edda162ff435.tar.gz libmicrohttpd-70f7ad46ebc58f18599be8356751edda162ff435.zip |
Reimplement monotonic clock with wide range of platforms support
Diffstat (limited to 'src')
-rw-r--r-- | src/include/microhttpd.h | 2 | ||||
-rw-r--r-- | src/microhttpd/Makefile.am | 1 | ||||
-rw-r--r-- | src/microhttpd/connection.c | 5 | ||||
-rw-r--r-- | src/microhttpd/connection_https.c | 5 | ||||
-rw-r--r-- | src/microhttpd/daemon.c | 9 | ||||
-rw-r--r-- | src/microhttpd/digestauth.c | 5 | ||||
-rw-r--r-- | src/microhttpd/internal.c | 21 | ||||
-rw-r--r-- | src/microhttpd/internal.h | 11 | ||||
-rw-r--r-- | src/microhttpd/mhd_mono_clock.c | 312 | ||||
-rw-r--r-- | src/microhttpd/mhd_mono_clock.h | 54 |
10 files changed, 383 insertions, 42 deletions
diff --git a/src/include/microhttpd.h b/src/include/microhttpd.h index 02939c1d..542c5f06 100644 --- a/src/include/microhttpd.h +++ b/src/include/microhttpd.h | |||
@@ -130,7 +130,7 @@ typedef intptr_t ssize_t; | |||
130 | * Current version of the library. | 130 | * Current version of the library. |
131 | * 0x01093001 = 1.9.30-1. | 131 | * 0x01093001 = 1.9.30-1. |
132 | */ | 132 | */ |
133 | #define MHD_VERSION 0x00094209 | 133 | #define MHD_VERSION 0x00094210 |
134 | 134 | ||
135 | /** | 135 | /** |
136 | * MHD-internal return code for "YES". | 136 | * MHD-internal return code for "YES". |
diff --git a/src/microhttpd/Makefile.am b/src/microhttpd/Makefile.am index 020579d6..ecd949b2 100644 --- a/src/microhttpd/Makefile.am +++ b/src/microhttpd/Makefile.am | |||
@@ -62,6 +62,7 @@ libmicrohttpd_la_SOURCES = \ | |||
62 | daemon.c \ | 62 | daemon.c \ |
63 | internal.c internal.h \ | 63 | internal.c internal.h \ |
64 | memorypool.c memorypool.h \ | 64 | memorypool.c memorypool.h \ |
65 | mhd_mono_clock.c mhd_mono_clock.h \ | ||
65 | mhd_limits.h mhd_byteorder.h \ | 66 | mhd_limits.h mhd_byteorder.h \ |
66 | response.c response.h | 67 | response.c response.h |
67 | libmicrohttpd_la_CPPFLAGS = \ | 68 | libmicrohttpd_la_CPPFLAGS = \ |
diff --git a/src/microhttpd/connection.c b/src/microhttpd/connection.c index 06823edb..f1bd80bf 100644 --- a/src/microhttpd/connection.c +++ b/src/microhttpd/connection.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include "connection.h" | 30 | #include "connection.h" |
31 | #include "memorypool.h" | 31 | #include "memorypool.h" |
32 | #include "response.h" | 32 | #include "response.h" |
33 | #include "mhd_mono_clock.h" | ||
33 | 34 | ||
34 | #if HAVE_NETINET_TCP_H | 35 | #if HAVE_NETINET_TCP_H |
35 | /* for TCP_CORK */ | 36 | /* for TCP_CORK */ |
@@ -1970,7 +1971,7 @@ update_last_activity (struct MHD_Connection *connection) | |||
1970 | { | 1971 | { |
1971 | struct MHD_Daemon *daemon = connection->daemon; | 1972 | struct MHD_Daemon *daemon = connection->daemon; |
1972 | 1973 | ||
1973 | connection->last_activity = MHD_monotonic_time(); | 1974 | connection->last_activity = MHD_monotonic_sec_counter(); |
1974 | if (connection->connection_timeout != daemon->connection_timeout) | 1975 | if (connection->connection_timeout != daemon->connection_timeout) |
1975 | return; /* custom timeout, no need to move it in "normal" DLL */ | 1976 | return; /* custom timeout, no need to move it in "normal" DLL */ |
1976 | 1977 | ||
@@ -2656,7 +2657,7 @@ MHD_connection_handle_idle (struct MHD_Connection *connection) | |||
2656 | } | 2657 | } |
2657 | timeout = connection->connection_timeout; | 2658 | timeout = connection->connection_timeout; |
2658 | if ( (0 != timeout) && | 2659 | if ( (0 != timeout) && |
2659 | (timeout <= (MHD_monotonic_time() - connection->last_activity)) ) | 2660 | (timeout <= (MHD_monotonic_sec_counter() - connection->last_activity)) ) |
2660 | { | 2661 | { |
2661 | MHD_connection_close (connection, | 2662 | MHD_connection_close (connection, |
2662 | MHD_REQUEST_TERMINATED_TIMEOUT_REACHED); | 2663 | MHD_REQUEST_TERMINATED_TIMEOUT_REACHED); |
diff --git a/src/microhttpd/connection_https.c b/src/microhttpd/connection_https.c index af359fac..433d2e43 100644 --- a/src/microhttpd/connection_https.c +++ b/src/microhttpd/connection_https.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include "connection.h" | 30 | #include "connection.h" |
31 | #include "memorypool.h" | 31 | #include "memorypool.h" |
32 | #include "response.h" | 32 | #include "response.h" |
33 | #include "mhd_mono_clock.h" | ||
33 | #include <gnutls/gnutls.h> | 34 | #include <gnutls/gnutls.h> |
34 | 35 | ||
35 | 36 | ||
@@ -46,7 +47,7 @@ run_tls_handshake (struct MHD_Connection *connection) | |||
46 | { | 47 | { |
47 | int ret; | 48 | int ret; |
48 | 49 | ||
49 | connection->last_activity = MHD_monotonic_time(); | 50 | connection->last_activity = MHD_monotonic_sec_counter(); |
50 | if (connection->state == MHD_TLS_CONNECTION_INIT) | 51 | if (connection->state == MHD_TLS_CONNECTION_INIT) |
51 | { | 52 | { |
52 | ret = gnutls_handshake (connection->tls_session); | 53 | ret = gnutls_handshake (connection->tls_session); |
@@ -139,7 +140,7 @@ MHD_tls_connection_handle_idle (struct MHD_Connection *connection) | |||
139 | MHD_state_to_string (connection->state)); | 140 | MHD_state_to_string (connection->state)); |
140 | #endif | 141 | #endif |
141 | timeout = connection->connection_timeout; | 142 | timeout = connection->connection_timeout; |
142 | if ( (timeout != 0) && (timeout <= (MHD_monotonic_time() - connection->last_activity))) | 143 | if ( (timeout != 0) && (timeout <= (MHD_monotonic_sec_counter() - connection->last_activity))) |
143 | MHD_connection_close (connection, | 144 | MHD_connection_close (connection, |
144 | MHD_REQUEST_TERMINATED_TIMEOUT_REACHED); | 145 | MHD_REQUEST_TERMINATED_TIMEOUT_REACHED); |
145 | switch (connection->state) | 146 | switch (connection->state) |
diff --git a/src/microhttpd/daemon.c b/src/microhttpd/daemon.c index d8540abe..f516aefb 100644 --- a/src/microhttpd/daemon.c +++ b/src/microhttpd/daemon.c | |||
@@ -38,6 +38,7 @@ | |||
38 | #include "memorypool.h" | 38 | #include "memorypool.h" |
39 | #include "mhd_limits.h" | 39 | #include "mhd_limits.h" |
40 | #include "autoinit_funcs.h" | 40 | #include "autoinit_funcs.h" |
41 | #include "mhd_mono_clock.h" | ||
41 | 42 | ||
42 | #if HAVE_SEARCH_H | 43 | #if HAVE_SEARCH_H |
43 | #include <search.h> | 44 | #include <search.h> |
@@ -822,7 +823,7 @@ MHD_handle_connection (void *data) | |||
822 | #endif | 823 | #endif |
823 | if (NULL == tvp && timeout > 0) | 824 | if (NULL == tvp && timeout > 0) |
824 | { | 825 | { |
825 | now = MHD_monotonic_time(); | 826 | now = MHD_monotonic_sec_counter(); |
826 | if (now - con->last_activity > timeout) | 827 | if (now - con->last_activity > timeout) |
827 | tv.tv_sec = 0; | 828 | tv.tv_sec = 0; |
828 | else | 829 | else |
@@ -1440,7 +1441,7 @@ internal_add_connection (struct MHD_Daemon *daemon, | |||
1440 | connection->addr_len = addrlen; | 1441 | connection->addr_len = addrlen; |
1441 | connection->socket_fd = client_socket; | 1442 | connection->socket_fd = client_socket; |
1442 | connection->daemon = daemon; | 1443 | connection->daemon = daemon; |
1443 | connection->last_activity = MHD_monotonic_time(); | 1444 | connection->last_activity = MHD_monotonic_sec_counter(); |
1444 | 1445 | ||
1445 | /* set default connection handlers */ | 1446 | /* set default connection handlers */ |
1446 | MHD_set_http_callbacks_ (connection); | 1447 | MHD_set_http_callbacks_ (connection); |
@@ -2175,7 +2176,7 @@ MHD_get_timeout (struct MHD_Daemon *daemon, | |||
2175 | 2176 | ||
2176 | if (MHD_NO == have_timeout) | 2177 | if (MHD_NO == have_timeout) |
2177 | return MHD_NO; | 2178 | return MHD_NO; |
2178 | now = MHD_monotonic_time(); | 2179 | now = MHD_monotonic_sec_counter(); |
2179 | if (earliest_deadline < now) | 2180 | if (earliest_deadline < now) |
2180 | *timeout = 0; | 2181 | *timeout = 0; |
2181 | else | 2182 | else |
@@ -4878,6 +4879,7 @@ void MHD_init(void) | |||
4878 | #endif | 4879 | #endif |
4879 | gnutls_global_init (); | 4880 | gnutls_global_init (); |
4880 | #endif | 4881 | #endif |
4882 | MHD_monotonic_sec_counter_init(); | ||
4881 | } | 4883 | } |
4882 | 4884 | ||
4883 | 4885 | ||
@@ -4890,6 +4892,7 @@ void MHD_fini(void) | |||
4890 | if (mhd_winsock_inited_) | 4892 | if (mhd_winsock_inited_) |
4891 | WSACleanup(); | 4893 | WSACleanup(); |
4892 | #endif | 4894 | #endif |
4895 | MHD_monotonic_sec_counter_finish(); | ||
4893 | } | 4896 | } |
4894 | 4897 | ||
4895 | _SET_INIT_AND_DEINIT_FUNCS(MHD_init, MHD_fini); | 4898 | _SET_INIT_AND_DEINIT_FUNCS(MHD_init, MHD_fini); |
diff --git a/src/microhttpd/digestauth.c b/src/microhttpd/digestauth.c index e69f58aa..32ef79ef 100644 --- a/src/microhttpd/digestauth.c +++ b/src/microhttpd/digestauth.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <limits.h> | 26 | #include <limits.h> |
27 | #include "internal.h" | 27 | #include "internal.h" |
28 | #include "md5.h" | 28 | #include "md5.h" |
29 | #include "mhd_mono_clock.h" | ||
29 | 30 | ||
30 | #if defined(_WIN32) && defined(MHD_W32_MUTEX_) | 31 | #if defined(_WIN32) && defined(MHD_W32_MUTEX_) |
31 | #ifndef WIN32_LEAN_AND_MEAN | 32 | #ifndef WIN32_LEAN_AND_MEAN |
@@ -643,7 +644,7 @@ MHD_digest_auth_check (struct MHD_Connection *connection, | |||
643 | } | 644 | } |
644 | /* 8 = 4 hexadecimal numbers for the timestamp */ | 645 | /* 8 = 4 hexadecimal numbers for the timestamp */ |
645 | nonce_time = strtoul (nonce + len - 8, (char **)NULL, 16); | 646 | nonce_time = strtoul (nonce + len - 8, (char **)NULL, 16); |
646 | t = (uint32_t) MHD_monotonic_time(); | 647 | t = (uint32_t) MHD_monotonic_sec_counter(); |
647 | /* | 648 | /* |
648 | * First level vetting for the nonce validity: if the timestamp | 649 | * First level vetting for the nonce validity: if the timestamp |
649 | * attached to the nonce exceeds `nonce_timeout', then the nonce is | 650 | * attached to the nonce exceeds `nonce_timeout', then the nonce is |
@@ -820,7 +821,7 @@ MHD_queue_auth_fail_response (struct MHD_Connection *connection, | |||
820 | char nonce[HASH_MD5_HEX_LEN + 9]; | 821 | char nonce[HASH_MD5_HEX_LEN + 9]; |
821 | 822 | ||
822 | /* Generating the server nonce */ | 823 | /* Generating the server nonce */ |
823 | calculate_nonce ((uint32_t) MHD_monotonic_time(), | 824 | calculate_nonce ((uint32_t) MHD_monotonic_sec_counter(), |
824 | connection->method, | 825 | connection->method, |
825 | connection->daemon->digest_auth_random, | 826 | connection->daemon->digest_auth_random, |
826 | connection->daemon->digest_auth_rand_size, | 827 | connection->daemon->digest_auth_rand_size, |
diff --git a/src/microhttpd/internal.c b/src/microhttpd/internal.c index 6a9188fd..b4f12521 100644 --- a/src/microhttpd/internal.c +++ b/src/microhttpd/internal.c | |||
@@ -171,25 +171,4 @@ MHD_http_unescape (char *val) | |||
171 | } | 171 | } |
172 | 172 | ||
173 | 173 | ||
174 | /** | ||
175 | * Equivalent to time(NULL) but tries to use some sort of monotonic | ||
176 | * clock that isn't affected by someone setting the system real time | ||
177 | * clock. | ||
178 | * | ||
179 | * @return 'current' time | ||
180 | */ | ||
181 | time_t | ||
182 | MHD_monotonic_time (void) | ||
183 | { | ||
184 | #ifdef HAVE_CLOCK_GETTIME | ||
185 | #ifdef CLOCK_MONOTONIC | ||
186 | struct timespec ts; | ||
187 | |||
188 | if (0 == clock_gettime (CLOCK_MONOTONIC, &ts)) | ||
189 | return ts.tv_sec; | ||
190 | #endif | ||
191 | #endif | ||
192 | return time (NULL); | ||
193 | } | ||
194 | |||
195 | /* end of internal.c */ | 174 | /* end of internal.c */ |
diff --git a/src/microhttpd/internal.h b/src/microhttpd/internal.h index fe487121..d2fdd925 100644 --- a/src/microhttpd/internal.h +++ b/src/microhttpd/internal.h | |||
@@ -1439,17 +1439,6 @@ struct MHD_Daemon | |||
1439 | 1439 | ||
1440 | 1440 | ||
1441 | /** | 1441 | /** |
1442 | * Equivalent to `time(NULL)` but tries to use some sort of monotonic | ||
1443 | * clock that isn't affected by someone setting the system real time | ||
1444 | * clock. | ||
1445 | * | ||
1446 | * @return 'current' time | ||
1447 | */ | ||
1448 | time_t | ||
1449 | MHD_monotonic_time(void); | ||
1450 | |||
1451 | |||
1452 | /** | ||
1453 | * Convert all occurences of '+' to ' '. | 1442 | * Convert all occurences of '+' to ' '. |
1454 | * | 1443 | * |
1455 | * @param arg string that is modified (in place), must be 0-terminated | 1444 | * @param arg string that is modified (in place), must be 0-terminated |
diff --git a/src/microhttpd/mhd_mono_clock.c b/src/microhttpd/mhd_mono_clock.c new file mode 100644 index 00000000..27591b46 --- /dev/null +++ b/src/microhttpd/mhd_mono_clock.c | |||
@@ -0,0 +1,312 @@ | |||
1 | /* | ||
2 | This file is part of libmicrohttpd | ||
3 | Copyright (C) 2015 Karlson2k (Evgeny Grin) | ||
4 | |||
5 | This library is free software; you can redistribute it and/or | ||
6 | modify it under the terms of the GNU Lesser General Public | ||
7 | License as published by the Free Software Foundation; either | ||
8 | version 2.1 of the License, or (at your option) any later version. | ||
9 | |||
10 | This library is distributed in the hope that it will be useful, | ||
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Lesser General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Lesser General Public | ||
16 | License along with this library; if not, write to the Free Software | ||
17 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||
18 | */ | ||
19 | |||
20 | /** | ||
21 | * @file microhttpd/mhd_mono_clock.h | ||
22 | * @brief internal monotonic clock functions implementations | ||
23 | * @author Karlson2k (Evgeny Grin) | ||
24 | */ | ||
25 | |||
26 | #include "mhd_mono_clock.h" | ||
27 | |||
28 | #ifdef HAVE_CLOCK_GET_TIME | ||
29 | #include <mach/mach.h> | ||
30 | /* for host_get_clock_service(), mach_host_self(), mach_task_self() */ | ||
31 | #include <mach/clock.h> | ||
32 | /* for clock_get_time() */ | ||
33 | |||
34 | #define _MHD_INVALID_CLOCK_SERV ((clock_serv_t) -2) | ||
35 | |||
36 | static clock_serv_t mono_clock_service = _MHD_INVALID_CLOCK_SERV; | ||
37 | #endif /* HAVE_CLOCK_GET_TIME */ | ||
38 | |||
39 | #ifdef HAVE_CLOCK_GETTIME | ||
40 | #ifdef CLOCK_REALTIME | ||
41 | #define _MHD_UNWANTED_CLOCK CLOCK_REALTIME | ||
42 | #else /* !CLOCK_REALTIME */ | ||
43 | #define _MHD_UNWANTED_CLOCK ((clockid_t) -2) | ||
44 | #endif /* !CLOCK_REALTIME */ | ||
45 | |||
46 | static clockid_t mono_clock_id = _MHD_UNWANTED_CLOCK; | ||
47 | #endif /* HAVE_CLOCK_GETTIME */ | ||
48 | |||
49 | /* sync clocks; reduce chance of value wrap */ | ||
50 | static time_t mono_clock_start = 0; | ||
51 | static time_t sys_clock_start = 0; | ||
52 | #ifdef HAVE_GETHRTIME | ||
53 | static hrtime_t hrtime_start = 0; | ||
54 | #endif /* HAVE_GETHRTIME */ | ||
55 | #ifdef _WIN32 | ||
56 | #if _WIN32_WINNT >= 0x0600 | ||
57 | static uint64_t tick_start = 0; | ||
58 | #else /* _WIN32_WINNT < 0x0600 */ | ||
59 | static int64_t perf_freq = 0; | ||
60 | static int64_t perf_start = 0; | ||
61 | #endif /* _WIN32_WINNT < 0x0600 */ | ||
62 | #endif /* _WIN32 */ | ||
63 | |||
64 | |||
65 | |||
66 | /** | ||
67 | * Type of monotonic clock source | ||
68 | */ | ||
69 | enum _MHD_mono_clock_source | ||
70 | { | ||
71 | /** | ||
72 | * No monotonic clock | ||
73 | */ | ||
74 | _MHD_CLOCK_NO_SOURCE = 0, | ||
75 | |||
76 | /** | ||
77 | * clock_gettime() with specific clock | ||
78 | */ | ||
79 | _MHD_CLOCK_GETTIME, | ||
80 | |||
81 | /** | ||
82 | * clock_get_time() with specific clock service | ||
83 | */ | ||
84 | _MHD_CLOCK_GET_TIME, | ||
85 | |||
86 | /** | ||
87 | * gethrtime() / 1000000000 | ||
88 | */ | ||
89 | _MHD_CLOCK_GETHRTIME, | ||
90 | |||
91 | /** | ||
92 | * GetTickCount64() / 1000 | ||
93 | */ | ||
94 | _MHD_CLOCK_GETTICKCOUNT64, | ||
95 | |||
96 | /** | ||
97 | * QueryPerformanceCounter() / QueryPerformanceFrequency() | ||
98 | */ | ||
99 | _MHD_CLOCK_PERFCOUNTER | ||
100 | }; | ||
101 | |||
102 | /** | ||
103 | * Initialise monotonic seconds counter. | ||
104 | */ | ||
105 | void | ||
106 | MHD_monotonic_sec_counter_init (void) | ||
107 | { | ||
108 | #ifdef HAVE_CLOCK_GET_TIME | ||
109 | mach_timespec_t cur_time; | ||
110 | #endif /* HAVE_CLOCK_GET_TIME */ | ||
111 | enum _MHD_mono_clock_source mono_clock_source = _MHD_CLOCK_NO_SOURCE; | ||
112 | #ifdef HAVE_CLOCK_GETTIME | ||
113 | struct timespec ts; | ||
114 | |||
115 | mono_clock_id = _MHD_UNWANTED_CLOCK; | ||
116 | #endif /* HAVE_CLOCK_GETTIME */ | ||
117 | #ifdef HAVE_CLOCK_GET_TIME | ||
118 | mono_clock_service = _MHD_INVALID_CLOCK_SERV; | ||
119 | #endif /* HAVE_CLOCK_GET_TIME */ | ||
120 | |||
121 | if (0) | ||
122 | { | ||
123 | } else | ||
124 | #ifdef HAVE_CLOCK_GETTIME | ||
125 | #ifdef CLOCK_MONOTONIC_COARSE | ||
126 | /* Linux-specific fast value-getting clock */ | ||
127 | /* Can be affected by frequency adjustment and don't count time in suspend, */ | ||
128 | /* but preferred since it's fast */ | ||
129 | if (0 == clock_gettime (CLOCK_MONOTONIC_COARSE, &ts)) | ||
130 | { | ||
131 | mono_clock_id = CLOCK_MONOTONIC_COARSE; | ||
132 | mono_clock_start = ts.tv_sec; | ||
133 | mono_clock_source = _MHD_CLOCK_GETTIME; | ||
134 | } else | ||
135 | #endif /* CLOCK_MONOTONIC_COARSE */ | ||
136 | #ifdef CLOCK_MONOTONIC_FAST | ||
137 | /* FreeBSD/DragonFly fast value-getting clock */ | ||
138 | /* Can be affected by frequency adjustment, but preferred since it's fast */ | ||
139 | if (0 == clock_gettime (CLOCK_MONOTONIC_FAST, &ts)) | ||
140 | { | ||
141 | mono_clock_id = CLOCK_MONOTONIC_FAST; | ||
142 | mono_clock_start = ts.tv_sec; | ||
143 | mono_clock_source = _MHD_CLOCK_GETTIME; | ||
144 | } else | ||
145 | #endif /* CLOCK_MONOTONIC_COARSE */ | ||
146 | #ifdef CLOCK_MONOTONIC_RAW | ||
147 | /* Linux-specific clock */ | ||
148 | /* Not affected by frequency adjustment, but don't count time in suspend */ | ||
149 | if (0 == clock_gettime (CLOCK_MONOTONIC_RAW , &ts)) | ||
150 | { | ||
151 | mono_clock_id = CLOCK_MONOTONIC_RAW; | ||
152 | mono_clock_start = ts.tv_sec; | ||
153 | mono_clock_source = _MHD_CLOCK_GETTIME; | ||
154 | } else | ||
155 | #endif /* CLOCK_MONOTONIC_RAW */ | ||
156 | #ifdef CLOCK_BOOTTIME | ||
157 | /* Linux-specific clock */ | ||
158 | /* Count time in suspend so it's real monotonic on Linux, */ | ||
159 | /* but can be slower value-getting than other clocks */ | ||
160 | if (0 == clock_gettime(CLOCK_BOOTTIME, &ts)) | ||
161 | { | ||
162 | mono_clock_id = CLOCK_BOOTTIME; | ||
163 | mono_clock_start = ts.tv_sec; | ||
164 | mono_clock_source = _MHD_CLOCK_GETTIME; | ||
165 | } else | ||
166 | #endif /* CLOCK_BOOTTIME */ | ||
167 | #ifdef CLOCK_MONOTONIC | ||
168 | /* Monotonic clock */ | ||
169 | /* Widely supported, may be affected by frequency adjustment */ | ||
170 | /* On Linux it's not truly monotonic as it doesn't count time in suspend */ | ||
171 | if (0 == clock_gettime(CLOCK_MONOTONIC, &ts)) | ||
172 | { | ||
173 | mono_clock_id = CLOCK_MONOTONIC; | ||
174 | mono_clock_start = ts.tv_sec; | ||
175 | mono_clock_source = _MHD_CLOCK_GETTIME; | ||
176 | } else | ||
177 | #endif /* CLOCK_BOOTTIME */ | ||
178 | #endif /* HAVE_CLOCK_GETTIME */ | ||
179 | #ifdef HAVE_CLOCK_GET_TIME | ||
180 | /* Darwin-specific monotonic clock */ | ||
181 | /* Should be monotonic as clock_set_time function always unconditionally */ | ||
182 | /* failed on latest kernels */ | ||
183 | if (KERN_SUCCESS == host_get_clock_service(mach_host_self(), SYSTEM_CLOCK, &mono_clock_service) && | ||
184 | KERN_SUCCESS == clock_get_time(mono_clock_service, &cur_time)) | ||
185 | { | ||
186 | mono_clock_start = cur_time.tv_sec; | ||
187 | mono_clock_source = _MHD_CLOCK_GET_TIME; | ||
188 | } else | ||
189 | #endif /* HAVE_CLOCK_GET_TIME */ | ||
190 | #ifdef _WIN32 | ||
191 | #if _WIN32_WINNT >= 0x0600 | ||
192 | /* W32 Vista or later specific monotonic clock */ | ||
193 | /* Available since Vista, ~15ms accuracy */ | ||
194 | if (1) | ||
195 | { | ||
196 | tick_start = GetTickCount64(); | ||
197 | mono_clock_source = _MHD_CLOCK_GETTICKCOUNT64; | ||
198 | } else | ||
199 | #else /* _WIN32_WINNT < 0x0600 */ | ||
200 | /* W32 specific monotonic clock */ | ||
201 | /* Available on Windows 2000 and later */ | ||
202 | if (1) | ||
203 | { | ||
204 | LARGE_INTEGER freq, perf_counter; | ||
205 | QueryPerformanceFrequency(&freq); /* never fail on XP and later */ | ||
206 | QueryPerformanceCounter(&perf_counter); /* never fail on XP and later */ | ||
207 | perf_freq = freq.QuadPart; | ||
208 | perf_start = perf_counter.QuadPart; | ||
209 | mono_clock_source = _MHD_CLOCK_PERFCOUNTER; | ||
210 | } else | ||
211 | #endif /* _WIN32_WINNT < 0x0600 */ | ||
212 | #endif /* _WIN32 */ | ||
213 | #ifdef HAVE_CLOCK_GETTIME | ||
214 | #ifdef CLOCK_HIGHRES | ||
215 | /* Solaris-specific monotonic high-resolution clock */ | ||
216 | /* Not preferred due to be potentially resource-hungry */ | ||
217 | if (0 == clock_gettime(CLOCK_HIGHRES, &ts)) | ||
218 | { | ||
219 | mono_clock_id = CLOCK_HIGHRES; | ||
220 | mono_clock_start = ts.tv_sec; | ||
221 | mono_clock_source = _MHD_CLOCK_GETTIME; | ||
222 | } else | ||
223 | #endif /* CLOCK_HIGHRES */ | ||
224 | #endif /* HAVE_CLOCK_GETTIME */ | ||
225 | #ifdef HAVE_GETHRTIME | ||
226 | /* HP-UX and Solaris monotonic clock */ | ||
227 | /* Not preferred due to be potentially resource-hungry */ | ||
228 | if (1) | ||
229 | { | ||
230 | hrtime_start = gethrtime(); | ||
231 | mono_clock_source = _MHD_CLOCK_GETHRTIME; | ||
232 | } else | ||
233 | #endif /* HAVE_GETHRTIME */ | ||
234 | { | ||
235 | /* no suitable clock source was found */ | ||
236 | mono_clock_source = _MHD_CLOCK_NO_SOURCE; | ||
237 | } | ||
238 | |||
239 | #ifdef HAVE_CLOCK_GET_TIME | ||
240 | if (_MHD_CLOCK_GET_TIME != mono_clock_source && | ||
241 | _MHD_INVALID_CLOCK_SERV != mono_clock_service) | ||
242 | { | ||
243 | /* clock service was initialised but clock_get_time failed */ | ||
244 | mach_port_deallocate(mach_task_self(), mono_clock_service); | ||
245 | mono_clock_service = _MHD_INVALID_CLOCK_SERV; | ||
246 | } | ||
247 | #endif /* HAVE_CLOCK_GET_TIME */ | ||
248 | |||
249 | sys_clock_start = time(NULL); | ||
250 | } | ||
251 | |||
252 | |||
253 | /** | ||
254 | * Deinitialise monotonic seconds counter by freeing any allocated resources | ||
255 | */ | ||
256 | void | ||
257 | MHD_monotonic_sec_counter_finish(void) | ||
258 | { | ||
259 | #ifdef HAVE_CLOCK_GET_TIME | ||
260 | if (_MHD_INVALID_CLOCK_SERV != mono_clock_service) | ||
261 | { | ||
262 | mach_port_deallocate(mach_task_self(), mono_clock_service); | ||
263 | mono_clock_service = _MHD_INVALID_CLOCK_SERV; | ||
264 | } | ||
265 | #endif /* HAVE_CLOCK_GET_TIME */ | ||
266 | } | ||
267 | |||
268 | /** | ||
269 | * Monotonic seconds counter, useful for timeout calculation. | ||
270 | * Tries to be not affected by manually setting the system real time | ||
271 | * clock or adjustments by NTP synchronization. | ||
272 | * | ||
273 | * @return number of seconds from some fixed moment | ||
274 | */ | ||
275 | time_t | ||
276 | MHD_monotonic_sec_counter (void) | ||
277 | { | ||
278 | #ifdef HAVE_CLOCK_GETTIME | ||
279 | struct timespec ts; | ||
280 | |||
281 | if (_MHD_UNWANTED_CLOCK != mono_clock_id && | ||
282 | 0 == clock_gettime (mono_clock_id , &ts)) | ||
283 | return ts.tv_sec - mono_clock_start; | ||
284 | #endif /* HAVE_CLOCK_GETTIME */ | ||
285 | #ifdef HAVE_CLOCK_GET_TIME | ||
286 | if (_MHD_INVALID_CLOCK_SERV != mono_clock_service) | ||
287 | { | ||
288 | mach_timespec_t cur_time; | ||
289 | if (KERN_SUCCESS == clock_get_time(mono_clock_service, &cur_time)) | ||
290 | return cur_time.tv_sec - mono_clock_start; | ||
291 | } | ||
292 | #endif /* HAVE_CLOCK_GET_TIME */ | ||
293 | #if defined(_WIN32) | ||
294 | #if _WIN32_WINNT >= 0x0600 | ||
295 | if (1) | ||
296 | return (time_t)(((uint64_t)(GetTickCount64() - tick_start)) / 1000); | ||
297 | #else /* _WIN32_WINNT < 0x0600 */ | ||
298 | if (0 != perf_freq) | ||
299 | { | ||
300 | LARGE_INTEGER perf_counter; | ||
301 | QueryPerformanceCounter(&perf_counter); /* never fail on XP and later */ | ||
302 | return (time_t)(((uint64_t)(perf_counter.QuadPart - perf_start)) / perf_freq); | ||
303 | } | ||
304 | #endif /* _WIN32_WINNT < 0x0600 */ | ||
305 | #endif /* _WIN32 */ | ||
306 | #ifdef HAVE_GETHRTIME | ||
307 | if (1) | ||
308 | return (time_t)(((uint64_t)(gethrtime() - hrtime_start)) / 1000000000); | ||
309 | #endif /* HAVE_GETHRTIME */ | ||
310 | |||
311 | return time(NULL) - sys_clock_start; | ||
312 | } | ||
diff --git a/src/microhttpd/mhd_mono_clock.h b/src/microhttpd/mhd_mono_clock.h new file mode 100644 index 00000000..2c515d63 --- /dev/null +++ b/src/microhttpd/mhd_mono_clock.h | |||
@@ -0,0 +1,54 @@ | |||
1 | /* | ||
2 | This file is part of libmicrohttpd | ||
3 | Copyright (C) 2015 Karlson2k (Evgeny Grin) | ||
4 | |||
5 | This library is free software; you can redistribute it and/or | ||
6 | modify it under the terms of the GNU Lesser General Public | ||
7 | License as published by the Free Software Foundation; either | ||
8 | version 2.1 of the License, or (at your option) any later version. | ||
9 | |||
10 | This library is distributed in the hope that it will be useful, | ||
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Lesser General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Lesser General Public | ||
16 | License along with this library; if not, write to the Free Software | ||
17 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||
18 | */ | ||
19 | |||
20 | /** | ||
21 | * @file microhttpd/mhd_mono_clock.h | ||
22 | * @brief internal monotonic clock functions declarations | ||
23 | * @author Karlson2k (Evgeny Grin) | ||
24 | */ | ||
25 | |||
26 | #ifndef MHD_MONO_CLOCK_H | ||
27 | #define MHD_MONO_CLOCK_H 1 | ||
28 | #include "platform.h" | ||
29 | |||
30 | /** | ||
31 | * Initialise monotonic seconds counter. | ||
32 | */ | ||
33 | void | ||
34 | MHD_monotonic_sec_counter_init(void); | ||
35 | |||
36 | |||
37 | /** | ||
38 | * Deinitialise monotonic seconds counter by freeing any allocated resources | ||
39 | */ | ||
40 | void | ||
41 | MHD_monotonic_sec_counter_finish(void); | ||
42 | |||
43 | |||
44 | /** | ||
45 | * Monotonic seconds counter, useful for timeout calculation. | ||
46 | * Tries to be not affected by manually setting the system real time | ||
47 | * clock or adjustments by NTP synchronization. | ||
48 | * | ||
49 | * @return number of seconds from some fixed moment | ||
50 | */ | ||
51 | time_t | ||
52 | MHD_monotonic_sec_counter(void); | ||
53 | |||
54 | #endif /* MHD_MONO_CLOCK_H */ | ||