annotate extern/jansson/src/hashtable_seed.c @ 0:8991989c4708

Initial import
author David Demelier <markand@malikania.fr>
date Tue, 22 Mar 2016 18:26:05 +0100
parents
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
1 /* Generate sizeof(uint32_t) bytes of as random data as possible to seed
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
2 the hash function.
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
3 */
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
4
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
5 #ifdef HAVE_CONFIG_H
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
6 #include <jansson_private_config.h>
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
7 #endif
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
8
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
9 #include <stdio.h>
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
10 #include <time.h>
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
11
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
12 #ifdef HAVE_STDINT_H
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
13 #include <stdint.h>
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
14 #endif
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
15
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
16 #ifdef HAVE_FCNTL_H
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
17 #include <fcntl.h>
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
18 #endif
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
19
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
20 #ifdef HAVE_SCHED_H
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
21 #include <sched.h>
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
22 #endif
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
23
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
24 #ifdef HAVE_UNISTD_H
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
25 #include <unistd.h>
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
26 #endif
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
27
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
28 #ifdef HAVE_SYS_STAT_H
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
29 #include <sys/stat.h>
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
30 #endif
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
31
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
32 #ifdef HAVE_SYS_TIME_H
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
33 #include <sys/time.h>
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
34 #endif
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
35
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
36 #ifdef HAVE_SYS_TYPES_H
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
37 #include <sys/types.h>
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
38 #endif
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
39
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
40 #if defined(_WIN32)
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
41 /* For GetModuleHandle(), GetProcAddress() and GetCurrentProcessId() */
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
42 #include <windows.h>
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
43 #endif
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
44
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
45 #include "jansson.h"
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
46
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
47
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
48 static uint32_t buf_to_uint32(char *data) {
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
49 size_t i;
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
50 uint32_t result = 0;
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
51
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
52 for (i = 0; i < sizeof(uint32_t); i++)
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
53 result = (result << 8) | (unsigned char)data[i];
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
54
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
55 return result;
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
56 }
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
57
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
58
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
59
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
60 /* /dev/urandom */
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
61 #if !defined(_WIN32) && defined(USE_URANDOM)
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
62 static int seed_from_urandom(uint32_t *seed) {
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
63 /* Use unbuffered I/O if we have open(), close() and read(). Otherwise
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
64 fall back to fopen() */
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
65
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
66 char data[sizeof(uint32_t)];
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
67 int ok;
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
68
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
69 #if defined(HAVE_OPEN) && defined(HAVE_CLOSE) && defined(HAVE_READ)
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
70 int urandom;
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
71 urandom = open("/dev/urandom", O_RDONLY);
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
72 if (urandom == -1)
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
73 return 1;
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
74
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
75 ok = read(urandom, data, sizeof(uint32_t)) == sizeof(uint32_t);
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
76 close(urandom);
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
77 #else
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
78 FILE *urandom;
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
79
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
80 urandom = fopen("/dev/urandom", "rb");
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
81 if (!urandom)
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
82 return 1;
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
83
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
84 ok = fread(data, 1, sizeof(uint32_t), urandom) == sizeof(uint32_t);
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
85 fclose(urandom);
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
86 #endif
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
87
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
88 if (!ok)
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
89 return 1;
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
90
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
91 *seed = buf_to_uint32(data);
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
92 return 0;
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
93 }
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
94 #endif
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
95
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
96 /* Windows Crypto API */
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
97 #if defined(_WIN32) && defined(USE_WINDOWS_CRYPTOAPI)
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
98 #include <wincrypt.h>
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
99
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
100 typedef BOOL (WINAPI *CRYPTACQUIRECONTEXTA)(HCRYPTPROV *phProv, LPCSTR pszContainer, LPCSTR pszProvider, DWORD dwProvType, DWORD dwFlags);
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
101 typedef BOOL (WINAPI *CRYPTGENRANDOM)(HCRYPTPROV hProv, DWORD dwLen, BYTE *pbBuffer);
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
102 typedef BOOL (WINAPI *CRYPTRELEASECONTEXT)(HCRYPTPROV hProv, DWORD dwFlags);
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
103
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
104 static int seed_from_windows_cryptoapi(uint32_t *seed)
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
105 {
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
106 HINSTANCE hAdvAPI32 = NULL;
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
107 CRYPTACQUIRECONTEXTA pCryptAcquireContext = NULL;
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
108 CRYPTGENRANDOM pCryptGenRandom = NULL;
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
109 CRYPTRELEASECONTEXT pCryptReleaseContext = NULL;
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
110 HCRYPTPROV hCryptProv = 0;
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
111 BYTE data[sizeof(uint32_t)];
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
112 int ok;
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
113
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
114 hAdvAPI32 = GetModuleHandle(TEXT("advapi32.dll"));
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
115 if(hAdvAPI32 == NULL)
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
116 return 1;
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
117
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
118 pCryptAcquireContext = (CRYPTACQUIRECONTEXTA)GetProcAddress(hAdvAPI32, "CryptAcquireContextA");
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
119 if (!pCryptAcquireContext)
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
120 return 1;
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
121
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
122 pCryptGenRandom = (CRYPTGENRANDOM)GetProcAddress(hAdvAPI32, "CryptGenRandom");
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
123 if (!pCryptGenRandom)
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
124 return 1;
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
125
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
126 pCryptReleaseContext = (CRYPTRELEASECONTEXT)GetProcAddress(hAdvAPI32, "CryptReleaseContext");
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
127 if (!pCryptReleaseContext)
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
128 return 1;
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
129
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
130 if (!pCryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
131 return 1;
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
132
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
133 ok = pCryptGenRandom(hCryptProv, sizeof(uint32_t), data);
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
134 pCryptReleaseContext(hCryptProv, 0);
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
135
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
136 if (!ok)
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
137 return 1;
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
138
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
139 *seed = buf_to_uint32((char *)data);
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
140 return 0;
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
141 }
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
142 #endif
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
143
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
144 /* gettimeofday() and getpid() */
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
145 static int seed_from_timestamp_and_pid(uint32_t *seed) {
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
146 #ifdef HAVE_GETTIMEOFDAY
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
147 /* XOR of seconds and microseconds */
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
148 struct timeval tv;
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
149 gettimeofday(&tv, NULL);
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
150 *seed = (uint32_t)tv.tv_sec ^ (uint32_t)tv.tv_usec;
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
151 #else
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
152 /* Seconds only */
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
153 *seed = (uint32_t)time(NULL);
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
154 #endif
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
155
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
156 /* XOR with PID for more randomness */
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
157 #if defined(_WIN32)
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
158 *seed ^= (uint32_t)GetCurrentProcessId();
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
159 #elif defined(HAVE_GETPID)
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
160 *seed ^= (uint32_t)getpid();
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
161 #endif
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
162
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
163 return 0;
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
164 }
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
165
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
166 static uint32_t generate_seed() {
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
167 uint32_t seed;
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
168 int done = 0;
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
169
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
170 #if !defined(_WIN32) && defined(USE_URANDOM)
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
171 if (!done && seed_from_urandom(&seed) == 0)
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
172 done = 1;
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
173 #endif
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
174
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
175 #if defined(_WIN32) && defined(USE_WINDOWS_CRYPTOAPI)
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
176 if (!done && seed_from_windows_cryptoapi(&seed) == 0)
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
177 done = 1;
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
178 #endif
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
179
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
180 if (!done) {
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
181 /* Fall back to timestamp and PID if no better randomness is
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
182 available */
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
183 seed_from_timestamp_and_pid(&seed);
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
184 }
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
185
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
186 /* Make sure the seed is never zero */
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
187 if (seed == 0)
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
188 seed = 1;
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
189
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
190 return seed;
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
191 }
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
192
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
193
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
194 volatile uint32_t hashtable_seed = 0;
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
195
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
196 #if defined(HAVE_ATOMIC_BUILTINS) && (defined(HAVE_SCHED_YIELD) || !defined(_WIN32))
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
197 static volatile char seed_initialized = 0;
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
198
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
199 void json_object_seed(size_t seed) {
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
200 uint32_t new_seed = (uint32_t)seed;
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
201
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
202 if (hashtable_seed == 0) {
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
203 if (__atomic_test_and_set(&seed_initialized, __ATOMIC_RELAXED) == 0) {
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
204 /* Do the seeding ourselves */
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
205 if (new_seed == 0)
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
206 new_seed = generate_seed();
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
207
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
208 __atomic_store_n(&hashtable_seed, new_seed, __ATOMIC_RELEASE);
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
209 } else {
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
210 /* Wait for another thread to do the seeding */
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
211 do {
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
212 #ifdef HAVE_SCHED_YIELD
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
213 sched_yield();
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
214 #endif
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
215 } while(__atomic_load_n(&hashtable_seed, __ATOMIC_ACQUIRE) == 0);
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
216 }
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
217 }
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
218 }
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
219 #elif defined(HAVE_SYNC_BUILTINS) && (defined(HAVE_SCHED_YIELD) || !defined(_WIN32))
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
220 void json_object_seed(size_t seed) {
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
221 uint32_t new_seed = (uint32_t)seed;
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
222
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
223 if (hashtable_seed == 0) {
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
224 if (new_seed == 0) {
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
225 /* Explicit synchronization fences are not supported by the
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
226 __sync builtins, so every thread getting here has to
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
227 generate the seed value.
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
228 */
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
229 new_seed = generate_seed();
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
230 }
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
231
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
232 do {
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
233 if (__sync_bool_compare_and_swap(&hashtable_seed, 0, new_seed)) {
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
234 /* We were the first to seed */
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
235 break;
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
236 } else {
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
237 /* Wait for another thread to do the seeding */
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
238 #ifdef HAVE_SCHED_YIELD
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
239 sched_yield();
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
240 #endif
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
241 }
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
242 } while(hashtable_seed == 0);
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
243 }
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
244 }
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
245 #elif defined(_WIN32)
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
246 static long seed_initialized = 0;
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
247 void json_object_seed(size_t seed) {
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
248 uint32_t new_seed = (uint32_t)seed;
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
249
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
250 if (hashtable_seed == 0) {
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
251 if (InterlockedIncrement(&seed_initialized) == 1) {
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
252 /* Do the seeding ourselves */
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
253 if (new_seed == 0)
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
254 new_seed = generate_seed();
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
255
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
256 hashtable_seed = new_seed;
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
257 } else {
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
258 /* Wait for another thread to do the seeding */
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
259 do {
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
260 SwitchToThread();
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
261 } while (hashtable_seed == 0);
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
262 }
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
263 }
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
264 }
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
265 #else
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
266 /* Fall back to a thread-unsafe version */
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
267 void json_object_seed(size_t seed) {
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
268 uint32_t new_seed = (uint32_t)seed;
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
269
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
270 if (hashtable_seed == 0) {
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
271 if (new_seed == 0)
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
272 new_seed = generate_seed();
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
273
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
274 hashtable_seed = new_seed;
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
275 }
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
276 }
8991989c4708 Initial import
David Demelier <markand@malikania.fr>
parents:
diff changeset
277 #endif