1 | /* -*- c-basic-offset: 2 -*- */ |
2 | /* |
3 | Copyright(C) 2009-2017 Brazil |
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 | #pragma once |
21 | |
22 | #ifdef HAVE_CONFIG_H |
23 | # include <config.h> |
24 | #endif /* HAVE_CONFIG_H */ |
25 | |
26 | #ifdef WIN32 |
27 | # ifdef __GNUC__ |
28 | # define __MINGW_MSVC_COMPAT_WARNINGS |
29 | # endif /* __GNUC__ */ |
30 | |
31 | # ifdef __GNUC__ |
32 | # include <w32api.h> |
33 | # define GRN_MINIMUM_WINDOWS_VERSION WindowsVista |
34 | # else /* __GNUC__ */ |
35 | # define GRN_MINIMUM_WINDOWS_VERSION 0x0600 /* Vista */ |
36 | # endif /* __GNUC__ */ |
37 | |
38 | # ifdef WINVER |
39 | # undef WINVER |
40 | # endif /* WINVER */ |
41 | # define WINVER GRN_MINIMUM_WINDOWS_VERSION |
42 | # ifdef _WIN32_WINNT |
43 | # undef _WIN32_WINNT |
44 | # endif /* _WIN32_WINNT */ |
45 | # define _WIN32_WINNT GRN_MINIMUM_WINDOWS_VERSION |
46 | # ifdef NTDDI_VERSION |
47 | # undef NTDDI_VERSION |
48 | # endif /* NTDDI_VERSION */ |
49 | # define NTDDI_VERSION GRN_MINIMUM_WINDOWS_VERSION |
50 | |
51 | # ifdef WIN32_LEAN_AND_MEAN |
52 | # undef WIN32_LEAN_AND_MEAN |
53 | # endif /* WIN32_LEAN_AND_MEAN */ |
54 | #endif /* WIN32 */ |
55 | |
56 | #ifdef __cplusplus |
57 | # define __STDC_LIMIT_MACROS |
58 | #endif |
59 | |
60 | #include <stdlib.h> |
61 | #include <stdint.h> |
62 | |
63 | #include <sys/types.h> |
64 | |
65 | #ifdef HAVE_SYS_PARAM_H |
66 | # include <sys/param.h> |
67 | #endif /* HAVE_SYS_PARAM_H */ |
68 | |
69 | #ifdef HAVE_SYS_MMAN_H |
70 | # include <sys/mman.h> |
71 | #endif /* HAVE_SYS_MMAN_H */ |
72 | |
73 | #ifdef HAVE_SYS_TIME_H |
74 | # include <sys/time.h> |
75 | #endif /* HAVE_SYS_TIME_H */ |
76 | |
77 | #ifdef HAVE_SYS_RESOURCE_H |
78 | # include <sys/resource.h> |
79 | #endif /* HAVE_SYS_RESOURCE_H */ |
80 | |
81 | #ifdef WIN32 |
82 | # define GRN_API __declspec(dllexport) |
83 | # ifdef GROONGA_MAIN |
84 | # define GRN_VAR __declspec(dllimport) |
85 | # else |
86 | # define GRN_VAR __declspec(dllexport) extern |
87 | # endif /* GROONGA_MAIN */ |
88 | #else |
89 | # define GRN_API |
90 | # define GRN_VAR extern |
91 | #endif |
92 | |
93 | #ifdef WIN32 |
94 | # include <basetsd.h> |
95 | # include <process.h> |
96 | # include <winsock2.h> |
97 | # include <ws2tcpip.h> |
98 | # include <windows.h> |
99 | # include <stddef.h> |
100 | # include <windef.h> |
101 | # include <float.h> |
102 | # include <time.h> |
103 | # include <sys/types.h> |
104 | |
105 | # ifndef __GNUC__ |
106 | # define PATH_MAX (MAX_PATH - 1) |
107 | # ifndef __cplusplus |
108 | # define inline _inline |
109 | # endif |
110 | # endif |
111 | |
112 | # ifndef __GNUC__ |
113 | typedef SSIZE_T ssize_t; |
114 | typedef int pid_t; |
115 | typedef int64_t off64_t; |
116 | # endif |
117 | |
118 | # undef MSG_WAITALL |
119 | # define MSG_WAITALL 0 /* before Vista, not supported... */ |
120 | # define SHUT_RDWR SD_BOTH |
121 | |
122 | typedef SOCKET grn_sock; |
123 | # define grn_sock_close(sock) closesocket(sock) |
124 | |
125 | # define CALLBACK __stdcall |
126 | |
127 | # ifndef __GNUC__ |
128 | # include <intrin.h> |
129 | # include <sys/timeb.h> |
130 | # include <errno.h> |
131 | # endif |
132 | |
133 | #else /* WIN32 */ |
134 | |
135 | # define GROONGA_API |
136 | |
137 | # ifdef HAVE_UNISTD_H |
138 | # include <unistd.h> |
139 | # endif /* HAVE_UNISTD_H */ |
140 | |
141 | # ifndef __off64_t_defined |
142 | typedef off_t off64_t; |
143 | # endif |
144 | |
145 | # ifndef PATH_MAX |
146 | # if defined(MAXPATHLEN) |
147 | # define PATH_MAX MAXPATHLEN |
148 | # else /* MAXPATHLEN */ |
149 | # define PATH_MAX 1024 |
150 | # endif /* MAXPATHLEN */ |
151 | # endif /* PATH_MAX */ |
152 | # ifndef INT_LEAST8_MAX |
153 | typedef char int_least8_t; |
154 | # endif /* INT_LEAST8_MAX */ |
155 | # ifndef UINT_LEAST8_MAX |
156 | typedef unsigned char uint_least8_t; |
157 | # endif /* UINT_LEAST8_MAX */ |
158 | typedef int grn_sock; |
159 | # define grn_sock_close(sock) close(sock) |
160 | # define CALLBACK |
161 | |
162 | #endif /* WIN32 */ |
163 | |
164 | #ifndef INT8_MAX |
165 | # define INT8_MAX (127) |
166 | #endif /* INT8_MAX */ |
167 | |
168 | #ifndef INT8_MIN |
169 | # define INT8_MIN (-128) |
170 | #endif /* INT8_MIN */ |
171 | |
172 | #ifndef INT16_MAX |
173 | # define INT16_MAX (32767) |
174 | #endif /* INT16_MAX */ |
175 | |
176 | #ifndef INT16_MIN |
177 | # define INT16_MIN (-32768) |
178 | #endif /* INT16_MIN */ |
179 | |
180 | #ifndef INT32_MAX |
181 | # define INT32_MAX (2147483647) |
182 | #endif /* INT32_MAX */ |
183 | |
184 | #ifndef INT32_MIN |
185 | # define INT32_MIN (-2147483648) |
186 | #endif /* INT32_MIN */ |
187 | |
188 | #ifndef UINT32_MAX |
189 | # define UINT32_MAX (4294967295) |
190 | #endif /* UINT32_MAX */ |
191 | |
192 | #ifndef INT64_MAX |
193 | # define INT64_MAX (9223372036854775807) |
194 | #endif /* INT64_MAX */ |
195 | |
196 | #ifndef INT64_MIN |
197 | # define INT64_MIN (-9223372036854775808) |
198 | #endif /* INT64_MIN */ |
199 | |
200 | |
201 | #ifdef WIN32 |
202 | # define grn_lseek(fd, offset, whence) _lseeki64(fd, offset, whence) |
203 | #else /* WIN32 */ |
204 | # define grn_lseek(fd, offset, whence) lseek(fd, offset, whence) |
205 | #endif /* WIN32 */ |
206 | |
207 | |
208 | #ifdef HAVE_PTHREAD_H |
209 | # include <pthread.h> |
210 | typedef pthread_t grn_thread; |
211 | typedef void * grn_thread_func_result; |
212 | # define GRN_THREAD_FUNC_RETURN_VALUE NULL |
213 | # define THREAD_CREATE(thread,func,arg) \ |
214 | (pthread_create(&(thread), NULL, (func), (arg))) |
215 | # define THREAD_JOIN(thread) (pthread_join(thread, NULL)) |
216 | typedef pthread_mutex_t grn_mutex; |
217 | # define MUTEX_INIT(m) pthread_mutex_init(&m, NULL) |
218 | # define MUTEX_LOCK(m) pthread_mutex_lock(&m) |
219 | # define MUTEX_LOCK_CHECK(m) (MUTEX_LOCK(m) == 0) |
220 | # define MUTEX_UNLOCK(m) pthread_mutex_unlock(&m) |
221 | # define MUTEX_FIN(m) pthread_mutex_destroy(&m) |
222 | # ifdef HAVE_PTHREAD_MUTEXATTR_SETPSHARED |
223 | # define MUTEX_INIT_SHARED(m) do {\ |
224 | pthread_mutexattr_t mutexattr;\ |
225 | pthread_mutexattr_init(&mutexattr);\ |
226 | pthread_mutexattr_setpshared(&mutexattr, PTHREAD_PROCESS_SHARED);\ |
227 | pthread_mutex_init(&m, &mutexattr);\ |
228 | } while (0) |
229 | # else |
230 | # define MUTEX_INIT_SHARED MUTEX_INIT |
231 | # endif /* HAVE_PTHREAD_MUTEXATTR_SETPSHARED */ |
232 | |
233 | typedef pthread_mutex_t grn_critical_section; |
234 | # define CRITICAL_SECTION_INIT(cs) pthread_mutex_init(&(cs), NULL) |
235 | # define CRITICAL_SECTION_ENTER(cs) pthread_mutex_lock(&(cs)) |
236 | # define CRITICAL_SECTION_LEAVE(cs) pthread_mutex_unlock(&(cs)) |
237 | # define CRITICAL_SECTION_FIN(cs) |
238 | |
239 | typedef pthread_cond_t grn_cond; |
240 | # define COND_INIT(c) pthread_cond_init(&c, NULL) |
241 | # define COND_SIGNAL(c) pthread_cond_signal(&c) |
242 | # define COND_WAIT(c,m) pthread_cond_wait(&c, &m) |
243 | # define COND_BROADCAST(c) pthread_cond_broadcast(&c) |
244 | # ifdef HAVE_PTHREAD_CONDATTR_SETPSHARED |
245 | # define COND_INIT_SHARED(c) do {\ |
246 | pthread_condattr_t condattr;\ |
247 | pthread_condattr_init(&condattr);\ |
248 | pthread_condattr_setpshared(&condattr, PTHREAD_PROCESS_SHARED);\ |
249 | pthread_cond_init(&c, &condattr);\ |
250 | } while (0) |
251 | # else |
252 | # define COND_INIT_SHARED COND_INIT |
253 | # endif /* HAVE_PTHREAD_CONDATTR_SETPSHARE */ |
254 | # define COND_FIN(c) pthread_cond_destroy(&c) |
255 | |
256 | typedef pthread_key_t grn_thread_key; |
257 | # define THREAD_KEY_CREATE(key, destr) pthread_key_create(key, destr) |
258 | # define THREAD_KEY_DELETE(key) pthread_key_delete(key) |
259 | # define THREAD_SETSPECIFIC(key, value) pthread_setspecific(key, value) |
260 | # define THREAD_GETSPECIFIC(key) pthread_getspecific(key) |
261 | |
262 | #if defined(USE_UYIELD) |
263 | extern int grn_uyield_count; |
264 | #define GRN_TEST_YIELD() do {\ |
265 | if (((++grn_uyield_count) & (0x20 - 1)) == 0) {\ |
266 | sched_yield();\ |
267 | if (grn_uyield_count > 0x1000) {\ |
268 | grn_uyield_count = (uint32_t)time(NULL) % 0x1000;\ |
269 | }\ |
270 | }\ |
271 | } while (0) |
272 | |
273 | #undef assert |
274 | #define assert(assert_expr) do {\ |
275 | if (!(assert_expr)){\ |
276 | fprintf(stderr, "assertion failed: %s\n", #assert_expr);\ |
277 | abort();\ |
278 | }\ |
279 | GRN_TEST_YIELD();\ |
280 | } while (0) |
281 | |
282 | #define if (if_cond) \ |
283 | if ((((++grn_uyield_count) & (0x100 - 1)) != 0 || (sched_yield() * 0) == 0) && (if_cond)) |
284 | #define while(while_cond) \ |
285 | while ((((++grn_uyield_count) & (0x100 - 1)) != 0 || (sched_yield() * 0) == 0) && (while_cond)) |
286 | |
287 | #if !defined(_POSIX_PRIORITY_SCHEDULING) |
288 | #define sched_yield() grn_nanosleep(1000000 * 20) |
289 | #endif |
290 | # else /* USE_UYIELD */ |
291 | #define GRN_TEST_YIELD() do {} while (0) |
292 | # endif /* USE_UYIELD */ |
293 | |
294 | #else /* HAVE_PTHREAD_H */ |
295 | |
296 | /* todo */ |
297 | typedef int grn_thread_key; |
298 | # define THREAD_KEY_CREATE(key,destr) |
299 | # define THREAD_KEY_DELETE(key) |
300 | # define THREAD_SETSPECIFIC(key) |
301 | # define THREAD_GETSPECIFIC(key,value) |
302 | |
303 | # ifdef WIN32 |
304 | typedef uintptr_t grn_thread; |
305 | typedef unsigned int grn_thread_func_result; |
306 | # define GRN_THREAD_FUNC_RETURN_VALUE 0 |
307 | # define THREAD_CREATE(thread,func,arg) \ |
308 | (((thread)=_beginthreadex(NULL, 0, (func), (arg), 0, NULL)) == (grn_thread)0) |
309 | # define THREAD_JOIN(thread) \ |
310 | (WaitForSingleObject((HANDLE)(thread), INFINITE) == WAIT_FAILED) |
311 | typedef HANDLE grn_mutex; |
312 | # define MUTEX_INIT(m) ((m) = CreateMutex(0, FALSE, NULL)) |
313 | # define MUTEX_LOCK(m) WaitForSingleObject((m), INFINITE) |
314 | # define MUTEX_LOCK_CHECK(m) (MUTEX_LOCK(m) == WAIT_OBJECT_0) |
315 | # define MUTEX_UNLOCK(m) ReleaseMutex(m) |
316 | # define MUTEX_FIN(m) CloseHandle(m) |
317 | typedef CRITICAL_SECTION grn_critical_section; |
318 | # define CRITICAL_SECTION_INIT(cs) InitializeCriticalSection(&(cs)) |
319 | # define CRITICAL_SECTION_ENTER(cs) EnterCriticalSection(&(cs)) |
320 | # define CRITICAL_SECTION_LEAVE(cs) LeaveCriticalSection(&(cs)) |
321 | # define CRITICAL_SECTION_FIN(cs) DeleteCriticalSection(&(cs)) |
322 | |
323 | typedef struct |
324 | { |
325 | int waiters_count_; |
326 | HANDLE waiters_count_lock_; |
327 | HANDLE sema_; |
328 | HANDLE waiters_done_; |
329 | size_t was_broadcast_; |
330 | } grn_cond; |
331 | |
332 | # define COND_INIT(c) do { \ |
333 | (c).waiters_count_ = 0; \ |
334 | (c).sema_ = CreateSemaphore(NULL, 0, 0x7fffffff, NULL); \ |
335 | MUTEX_INIT((c).waiters_count_lock_); \ |
336 | (c).waiters_done_ = CreateEvent(NULL, FALSE, FALSE, NULL); \ |
337 | } while (0) |
338 | |
339 | # define COND_SIGNAL(c) do { \ |
340 | MUTEX_LOCK((c).waiters_count_lock_); \ |
341 | { \ |
342 | int have_waiters = (c).waiters_count_ > 0; \ |
343 | MUTEX_UNLOCK((c).waiters_count_lock_); \ |
344 | if (have_waiters) { \ |
345 | ReleaseSemaphore((c).sema_, 1, 0); \ |
346 | } \ |
347 | } \ |
348 | } while (0) |
349 | |
350 | # define COND_BROADCAST(c) do { \ |
351 | MUTEX_LOCK((c).waiters_count_lock_); \ |
352 | { \ |
353 | int have_waiters = (c).waiters_count_ > 0; \ |
354 | if ((c).waiters_count_ > 0) { \ |
355 | (c).was_broadcast_ = 1; \ |
356 | have_waiters = 1; \ |
357 | } \ |
358 | if (have_waiters) { \ |
359 | ReleaseSemaphore((c).sema_, (c).waiters_count_, 0); \ |
360 | MUTEX_UNLOCK((c).waiters_count_lock_); \ |
361 | WaitForSingleObject((c).waiters_done_, INFINITE); \ |
362 | (c).was_broadcast_ = 0; \ |
363 | } \ |
364 | else { \ |
365 | MUTEX_UNLOCK((c).waiters_count_lock_); \ |
366 | } \ |
367 | } \ |
368 | } while (0) |
369 | |
370 | # define COND_WAIT(c,m) do { \ |
371 | MUTEX_LOCK((c).waiters_count_lock_); \ |
372 | (c).waiters_count_++; \ |
373 | MUTEX_UNLOCK((c).waiters_count_lock_); \ |
374 | SignalObjectAndWait((m), (c).sema_, INFINITE, FALSE); \ |
375 | MUTEX_LOCK((c).waiters_count_lock_); \ |
376 | (c).waiters_count_--; \ |
377 | { \ |
378 | int last_waiter = (c).was_broadcast_ && (c).waiters_count_ == 0; \ |
379 | MUTEX_UNLOCK((c).waiters_count_lock_); \ |
380 | if (last_waiter) { \ |
381 | SignalObjectAndWait((c).waiters_done_, (m), INFINITE, FALSE); \ |
382 | } \ |
383 | else { \ |
384 | WaitForSingleObject((m), FALSE); \ |
385 | } \ |
386 | } \ |
387 | } while (0) |
388 | |
389 | # define COND_FIN(c) do { \ |
390 | CloseHandle((c).waiters_done_); \ |
391 | MUTEX_FIN((c).waiters_count_lock_); \ |
392 | CloseHandle((c).sema_); \ |
393 | } while (0) |
394 | |
395 | # else /* WIN32 */ |
396 | /* todo */ |
397 | typedef int grn_cond; |
398 | # define COND_INIT(c) ((c) = 0) |
399 | # define COND_SIGNAL(c) |
400 | # define COND_WAIT(c,m) do { \ |
401 | MUTEX_UNLOCK(m); \ |
402 | grn_nanosleep(1000000); \ |
403 | MUTEX_LOCK(m); \ |
404 | } while (0) |
405 | # define COND_FIN(c) |
406 | /* todo : must be enhanced! */ |
407 | |
408 | # endif /* WIN32 */ |
409 | |
410 | # define MUTEX_INIT_SHARED MUTEX_INIT |
411 | # define COND_INIT_SHARED COND_INIT |
412 | |
413 | # define GRN_TEST_YIELD() do {} while (0) |
414 | |
415 | #endif /* HAVE_PTHREAD_H */ |
416 | |
417 | #define MUTEX_LOCK_ENSURE(ctx_, mutex) do { \ |
418 | grn_ctx *ctx__ = (ctx_); \ |
419 | do { \ |
420 | grn_ctx *ctx = ctx__; \ |
421 | if (MUTEX_LOCK_CHECK(mutex)) { \ |
422 | break; \ |
423 | } \ |
424 | if (ctx) { \ |
425 | SERR("MUTEX_LOCK"); \ |
426 | } \ |
427 | grn_nanosleep(1000000); \ |
428 | } while (GRN_TRUE); \ |
429 | } while (GRN_FALSE) |
430 | |
431 | /* format string for printf */ |
432 | #ifdef HAVE_INTTYPES_H |
433 | # include <inttypes.h> |
434 | # define GRN_FMT_INT32D PRId32 |
435 | # define GRN_FMT_INT32U PRIu32 |
436 | # define GRN_FMT_INT64D PRId64 |
437 | # define GRN_FMT_INT64U PRIu64 |
438 | #else /* HAVE_INTTYPES_H */ |
439 | # ifdef WIN32 |
440 | # define GRN_FMT_INT32D "I32d" |
441 | # define GRN_FMT_INT32U "I32u" |
442 | # define GRN_FMT_INT64D "I64d" |
443 | # define GRN_FMT_INT64U "I64u" |
444 | # else /* WIN32 */ |
445 | # define GRN_FMT_INT32D "d" |
446 | # define GRN_FMT_INT32U "u" |
447 | # ifdef __x86_64__ |
448 | # define GRN_FMT_INT64D "ld" |
449 | # define GRN_FMT_INT64U "lu" |
450 | # else /* __x86_64__ */ |
451 | # define GRN_FMT_INT64D "lld" |
452 | # define GRN_FMT_INT64U "llu" |
453 | # endif /* __x86_64__ */ |
454 | # endif /* WIN32 */ |
455 | #endif /* HAVE_INTTYPES_H */ |
456 | |
457 | #ifdef WIN32 |
458 | # define GRN_FMT_LLD "I64d" |
459 | # define GRN_FMT_LLU "I64u" |
460 | # define GRN_FMT_SIZE "Iu" |
461 | # define GRN_FMT_SSIZE "Id" |
462 | # ifdef WIN64 |
463 | # define GRN_FMT_SOCKET GRN_FMT_INT64U |
464 | # define GRN_FMT_DWORD "lu" |
465 | # else /* WIN64 */ |
466 | # define GRN_FMT_SOCKET GRN_FMT_INT32U |
467 | # define GRN_FMT_DWORD "u" |
468 | # endif /* WIN64 */ |
469 | # define GRN_FMT_OFF64_T GRN_FMT_LLD |
470 | #else /* WIN32 */ |
471 | # define GRN_FMT_LLD "lld" |
472 | # define GRN_FMT_LLU "llu" |
473 | # define GRN_FMT_SIZE "zu" |
474 | # define GRN_FMT_SSIZE "zd" |
475 | # define GRN_FMT_SOCKET "d" |
476 | # define GRN_FMT_OFF64_T "jd" |
477 | #endif /* WIN32 */ |
478 | |
479 | #ifdef __GNUC__ |
480 | # if (defined(__i386__) || defined(__x86_64__)) /* ATOMIC ADD */ |
481 | /* |
482 | * GRN_ATOMIC_ADD_EX() performs { r = *p; *p += i; } atomically. |
483 | */ |
484 | # define GRN_ATOMIC_ADD_EX(p, i, r) \ |
485 | __asm__ __volatile__ ("lock xaddl %0, %1" : "=r"(r), "+m"(*p) : "0"(i)) |
486 | /* |
487 | * GRN_BIT_SCAN_REV() finds the most significant 1 bit of `v'. Then, `r' is set |
488 | * to the index of the found bit. Note that `v' must not be 0. |
489 | */ |
490 | # define GRN_BIT_SCAN_REV(v, r) \ |
491 | __asm__ __volatile__ ("bsrl %1, %%eax; movl %%eax, %0" : "=r"(r) : "r"(v) : "%eax") |
492 | /* |
493 | * GRN_BIT_SCAN_REV0() is similar to GRN_BIT_SCAN_REV() but if `v' is 0, `r' is |
494 | * set to 0. |
495 | */ |
496 | # define GRN_BIT_SCAN_REV0(v, r) \ |
497 | __asm__ __volatile__ ("bsrl %1, %%eax; cmovzl %1, %%eax; movl %%eax, %0" : "=r"(r) : "r"(v) : "%eax", "cc") |
498 | # elif (defined(__PPC__) || defined(__ppc__)) /* ATOMIC ADD */ |
499 | # define GRN_ATOMIC_ADD_EX(p,i,r) \ |
500 | __asm__ __volatile__ ("\n1:\n\tlwarx %0, 0, %1\n\tadd %0, %0, %2\n\tstwcx. %0, 0, %1\n\tbne- 1b\n\tsub %0, %0, %2" : "=&r" (r) : "r" (p), "r" (i) : "cc", "memory") |
501 | /* todo */ |
502 | # define GRN_BIT_SCAN_REV(v,r) for (r = 31; r && !((1 << r) & v); r--) |
503 | # define GRN_BIT_SCAN_REV0(v,r) GRN_BIT_SCAN_REV(v,r) |
504 | # elif (defined(__sun) && defined(__SVR4)) /* ATOMIC ADD */ |
505 | # include <atomic.h> |
506 | # define GRN_ATOMIC_ADD_EX(p,i,r) \ |
507 | (r = atomic_add_32_nv(p, i) - i) |
508 | /* todo */ |
509 | # define GRN_BIT_SCAN_REV(v,r) for (r = 31; r && !((1 << r) & v); r--) |
510 | # define GRN_BIT_SCAN_REV0(v,r) GRN_BIT_SCAN_REV(v,r) |
511 | # elif defined(__ATOMIC_SEQ_CST) /* GCC atomic builtins */ |
512 | # define GRN_ATOMIC_ADD_EX(p,i,r) \ |
513 | (r = __atomic_fetch_add(p, i, __ATOMIC_SEQ_CST)) |
514 | # define GRN_BIT_SCAN_REV(v,r) for (r = 31; r && !((1 << r) & v); r--) |
515 | # define GRN_BIT_SCAN_REV0(v,r) GRN_BIT_SCAN_REV(v,r) |
516 | # else /* ATOMIC ADD */ |
517 | /* todo */ |
518 | # define GRN_BIT_SCAN_REV(v,r) for (r = 31; r && !((1 << r) & v); r--) |
519 | # define GRN_BIT_SCAN_REV0(v,r) GRN_BIT_SCAN_REV(v,r) |
520 | # endif /* ATOMIC ADD */ |
521 | |
522 | # ifdef __i386__ /* ATOMIC 64BIT SET */ |
523 | # define GRN_SET_64BIT(p,v) \ |
524 | __asm__ __volatile__ ("\txchgl %%esi, %%ebx\n1:\n\tmovl (%0), %%eax\n\tmovl 4(%0), %%edx\n\tlock; cmpxchg8b (%0)\n\tjnz 1b\n\txchgl %%ebx, %%esi" : : "D"(p), "S"(*(((uint32_t *)&(v))+0)), "c"(*(((uint32_t *)&(v))+1)) : "ax", "dx", "memory") |
525 | # elif defined(__x86_64__) /* ATOMIC 64BIT SET */ |
526 | # define GRN_SET_64BIT(p,v) \ |
527 | (*(p) = (v)) |
528 | # elif (defined(__sun) && defined(__SVR4)) /* ATOMIC 64BIT SET */ |
529 | /* todo */ |
530 | # define GRN_SET_64BIT(p,v) \ |
531 | (void)atomic_swap_64(p, v) |
532 | # elif defined(__ATOMIC_SEQ_CST) /* GCC atomic builtins */ |
533 | # define GRN_SET_64BIT(p,v) \ |
534 | __atomic_store_n(p, v, __ATOMIC_SEQ_CST) |
535 | # else |
536 | # warning Need atomic 64bit operation support. The current implementation may break data. |
537 | # define GRN_SET_64BIT(p,v) \ |
538 | (*(p) = (v)) |
539 | # endif /* ATOMIC 64BIT SET */ |
540 | |
541 | #elif (defined(WIN32) || defined (_WIN64)) /* __GNUC__ */ |
542 | |
543 | # define GRN_ATOMIC_ADD_EX(p,i,r) \ |
544 | ((r) = InterlockedExchangeAdd((p), (i))) |
545 | # if defined(_WIN64) /* ATOMIC 64BIT SET */ |
546 | # define GRN_SET_64BIT(p,v) \ |
547 | (*(p) = (v)) |
548 | # else /* ATOMIC 64BIT SET */ |
549 | # define GRN_SET_64BIT(p,v) do {\ |
550 | uint32_t v1, v2; \ |
551 | uint64_t *p2= (p); \ |
552 | v1 = *(((uint32_t *)&(v))+0);\ |
553 | v2 = *(((uint32_t *)&(v))+1);\ |
554 | __asm _set_loop: \ |
555 | __asm mov esi, p2 \ |
556 | __asm mov ebx, v1 \ |
557 | __asm mov ecx, v2 \ |
558 | __asm mov eax, dword ptr [esi] \ |
559 | __asm mov edx, dword ptr [esi + 4] \ |
560 | __asm lock cmpxchg8b qword ptr [esi] \ |
561 | __asm jnz _set_loop \ |
562 | } while (0) |
563 | /* TODO: use _InterlockedCompareExchange64 or inline asm */ |
564 | # endif /* ATOMIC 64BIT SET */ |
565 | |
566 | /* todo */ |
567 | # define GRN_BIT_SCAN_REV(v,r) for (r = 31; r && !((1 << r) & v); r--) |
568 | # define GRN_BIT_SCAN_REV0(v,r) GRN_BIT_SCAN_REV(v,r) |
569 | |
570 | #else /* __GNUC__ */ |
571 | |
572 | # if (defined(__sun) && defined(__SVR4)) /* ATOMIC ADD */ |
573 | # define __FUNCTION__ "" |
574 | # include <atomic.h> |
575 | # define GRN_ATOMIC_ADD_EX(p,i,r) \ |
576 | (r = atomic_add_32_nv(p, i) - i) |
577 | /* todo */ |
578 | # define GRN_SET_64BIT(p,v) \ |
579 | (void)atomic_swap_64(p, v) |
580 | # endif /* ATOMIC ADD */ |
581 | /* todo */ |
582 | # define GRN_BIT_SCAN_REV(v,r) for (r = 31; r && !((1 << r) & v); r--) |
583 | # define GRN_BIT_SCAN_REV0(v,r) GRN_BIT_SCAN_REV(v,r) |
584 | |
585 | #endif /* __GNUC__ */ |
586 | |
587 | typedef uint8_t byte; |
588 | |
589 | #define GRN_ID_WIDTH 30 |
590 | |
591 | #ifdef __GNUC__ |
592 | inline static int |
593 | grn_str_greater(const uint8_t *ap, uint32_t as, const uint8_t *bp, uint32_t bs) |
594 | { |
595 | for (;; ap++, bp++, as--, bs--) { |
596 | if (!as) { return 0; } |
597 | if (!bs) { return 1; } |
598 | if (*ap < *bp) { return 0; } |
599 | if (*ap > *bp) { return 1; } |
600 | } |
601 | } |
602 | #else /* __GNUC__ */ |
603 | # define grn_str_greater(ap,as,bp,bs)\ |
604 | (((as) > (bs)) ? (memcmp((ap), (bp), (bs)) >= 0) : (memcmp((ap), (bp), (as)) > 0)) |
605 | #endif /* __GNUC__ */ |
606 | |
607 | #ifdef WORDS_BIGENDIAN |
608 | # define grn_hton(buf,key,size) do {\ |
609 | uint32_t size_ = (uint32_t)size;\ |
610 | uint8_t *buf_ = (uint8_t *)buf;\ |
611 | uint8_t *key_ = (uint8_t *)key;\ |
612 | while (size_--) { *buf_++ = *key_++; }\ |
613 | } while (0) |
614 | # define grn_ntohi(buf,key,size) do {\ |
615 | uint32_t size_ = (uint32_t)size;\ |
616 | uint8_t *buf_ = (uint8_t *)buf;\ |
617 | uint8_t *key_ = (uint8_t *)key;\ |
618 | if (size_) { *buf_++ = 0x80 ^ *key_++; size_--; }\ |
619 | while (size_) { *buf_++ = *key_++; size_--; }\ |
620 | } while (0) |
621 | #else /* WORDS_BIGENDIAN */ |
622 | # define grn_hton(buf,key,size) do {\ |
623 | uint32_t size_ = (uint32_t)size;\ |
624 | uint8_t *buf_ = (uint8_t *)buf;\ |
625 | uint8_t *key_ = (uint8_t *)key + size;\ |
626 | while (size_--) { *buf_++ = *(--key_); }\ |
627 | } while (0) |
628 | # define grn_ntohi(buf,key,size) do {\ |
629 | uint32_t size_ = (uint32_t)size;\ |
630 | uint8_t *buf_ = (uint8_t *)buf;\ |
631 | uint8_t *key_ = (uint8_t *)key + size;\ |
632 | while (size_ > 1) { *buf_++ = *(--key_); size_--; }\ |
633 | if (size_) { *buf_ = 0x80 ^ *(--key_); } \ |
634 | } while (0) |
635 | #endif /* WORDS_BIGENDIAN */ |
636 | #define grn_ntoh(buf,key,size) grn_hton(buf,key,size) |
637 | |
638 | #ifndef __GNUC_PREREQ |
639 | # if defined(__GNUC__) && defined(__GNUC_MINOR__) |
640 | # define __GNUC_PREREQ(maj, min) \ |
641 | ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min)) |
642 | # else |
643 | # define __GNUC_PREREQ(maj, min) 0 |
644 | # endif /* defined(__GNUC__) && defined(__GNUC_MINOR__) */ |
645 | #endif /* __GNUC_PREREQ */ |
646 | |
647 | #ifdef _MSC_VER |
648 | # define grn_bswap_uint64(in, out) ((out) = _byteswap_uint64(in)) |
649 | #else /* _MSC_VER */ |
650 | # if defined(__GNUC__) && __GNUC_PREREQ(4, 3) |
651 | # define grn_bswap_uint64(in, out) ((out) = __builtin_bswap64(in)) |
652 | # else /* defined(__GNUC__) && __GNUC_PREREQ(4, 3) */ |
653 | # define grn_bswap_uint64(in, out) do {\ |
654 | uint64_t temp_ = (in);\ |
655 | (out) = (temp_ << 56) |\ |
656 | ((temp_ & (0xFFULL << 8)) << 40) |\ |
657 | ((temp_ & (0xFFULL << 16)) << 24) |\ |
658 | ((temp_ & (0xFFULL << 24)) << 8) |\ |
659 | ((temp_ & (0xFFULL << 32)) >> 8) |\ |
660 | ((temp_ & (0xFFULL << 40)) >> 24) |\ |
661 | ((temp_ & (0xFFULL << 48)) >> 40) |\ |
662 | (temp_ >> 56);\ |
663 | } while (0) |
664 | # endif /* __GNUC__ */ |
665 | #endif /* _MSC_VER */ |
666 | |
667 | #ifdef WORDS_BIGENDIAN |
668 | # define grn_hton_uint64(in, out) ((out) = (in)) |
669 | #else /* WORDS_BIGENDIAN */ |
670 | # define grn_hton_uint64(in, out) grn_bswap_uint64(in, out) |
671 | #endif /* WORDS_BIGENDIAN */ |
672 | #define grn_ntoh_uint64(in, out) grn_hton_uint64(in, out) |
673 | |
674 | #define grn_gton(keybuf,key,size) do {\ |
675 | const grn_geo_point *point_ = (const grn_geo_point *)key;\ |
676 | uint64_t la_ = (uint32_t)point_->latitude;\ |
677 | uint64_t lo_ = (uint32_t)point_->longitude;\ |
678 | uint64_t result_;\ |
679 | la_ = (la_ | (la_ << 16)) & 0x0000FFFF0000FFFFULL;\ |
680 | la_ = (la_ | (la_ << 8)) & 0x00FF00FF00FF00FFULL;\ |
681 | la_ = (la_ | (la_ << 4)) & 0x0F0F0F0F0F0F0F0FULL;\ |
682 | la_ = (la_ | (la_ << 2)) & 0x3333333333333333ULL;\ |
683 | la_ = (la_ | (la_ << 1)) & 0x5555555555555555ULL;\ |
684 | lo_ = (lo_ | (lo_ << 16)) & 0x0000FFFF0000FFFFULL;\ |
685 | lo_ = (lo_ | (lo_ << 8)) & 0x00FF00FF00FF00FFULL;\ |
686 | lo_ = (lo_ | (lo_ << 4)) & 0x0F0F0F0F0F0F0F0FULL;\ |
687 | lo_ = (lo_ | (lo_ << 2)) & 0x3333333333333333ULL;\ |
688 | lo_ = (lo_ | (lo_ << 1)) & 0x5555555555555555ULL;\ |
689 | result_ = (la_ << 1) | lo_;\ |
690 | grn_hton_uint64(result_, result_);\ |
691 | grn_memcpy(keybuf, &result_, sizeof(result_));\ |
692 | } while (0) |
693 | |
694 | #define grn_ntog(keybuf,key,size) do {\ |
695 | grn_geo_point *point_ = (grn_geo_point *)keybuf;\ |
696 | uint64_t key_ = *(const uint64_t *)key;\ |
697 | uint64_t la_, lo_;\ |
698 | grn_ntoh_uint64(key_, key_);\ |
699 | la_ = (key_ >> 1) & 0x5555555555555555ULL;\ |
700 | lo_ = key_ & 0x5555555555555555ULL;\ |
701 | la_ = (la_ | (la_ >> 1)) & 0x3333333333333333ULL;\ |
702 | la_ = (la_ | (la_ >> 2)) & 0x0F0F0F0F0F0F0F0FULL;\ |
703 | la_ = (la_ | (la_ >> 4)) & 0x00FF00FF00FF00FFULL;\ |
704 | la_ = (la_ | (la_ >> 8)) & 0x0000FFFF0000FFFFULL;\ |
705 | la_ = (la_ | (la_ >> 16)) & 0x00000000FFFFFFFFULL;\ |
706 | lo_ = (lo_ | (lo_ >> 1)) & 0x3333333333333333ULL;\ |
707 | lo_ = (lo_ | (lo_ >> 2)) & 0x0F0F0F0F0F0F0F0FULL;\ |
708 | lo_ = (lo_ | (lo_ >> 4)) & 0x00FF00FF00FF00FFULL;\ |
709 | lo_ = (lo_ | (lo_ >> 8)) & 0x0000FFFF0000FFFFULL;\ |
710 | lo_ = (lo_ | (lo_ >> 16)) & 0x00000000FFFFFFFFULL;\ |
711 | point_->latitude = la_;\ |
712 | point_->longitude = lo_;\ |
713 | } while (0) |
714 | |
715 | #ifdef HAVE__STRTOUI64 |
716 | # define strtoull(nptr,endptr,base) _strtoui64(nptr,endptr,base) |
717 | #endif /* HAVE__STRTOUI64 */ |
718 | |
719 | #ifdef USE_FUTEX |
720 | # include <linux/futex.h> |
721 | # include <sys/syscall.h> |
722 | |
723 | # define GRN_FUTEX_WAIT(p) do {\ |
724 | int err;\ |
725 | struct timespec timeout = {1, 0};\ |
726 | while (1) {\ |
727 | if (!(err = syscall(SYS_futex, p, FUTEX_WAIT, *p, &timeout))) {\ |
728 | break;\ |
729 | }\ |
730 | if (err == ETIMEDOUT) {\ |
731 | GRN_LOG(ctx, GRN_LOG_CRIT, "timeout in GRN_FUTEX_WAIT(%p)", p);\ |
732 | break;\ |
733 | } else if (err != EWOULDBLOCK) {\ |
734 | GRN_LOG(ctx, GRN_LOG_CRIT, "error %d in GRN_FUTEX_WAIT(%p)", err);\ |
735 | break;\ |
736 | }\ |
737 | }\ |
738 | } while(0) |
739 | |
740 | # define GRN_FUTEX_WAKE(p) syscall(SYS_futex, p, FUTEX_WAKE, 1) |
741 | #else /* USE_FUTEX */ |
742 | # define GRN_FUTEX_WAIT(p) grn_nanosleep(1000000) |
743 | # define GRN_FUTEX_WAKE(p) |
744 | #endif /* USE_FUTEX */ |
745 | |
746 | #ifndef HOST_NAME_MAX |
747 | # ifdef _POSIX_HOST_NAME_MAX |
748 | # define HOST_NAME_MAX _POSIX_HOST_NAME_MAX |
749 | # else /* POSIX_HOST_NAME_MAX */ |
750 | # define HOST_NAME_MAX 128 |
751 | # endif /* POSIX_HOST_NAME_MAX */ |
752 | #endif /* HOST_NAME_MAX */ |
753 | |
754 | #define GRN_NEXT_ADDR(p) (((byte *)(p)) + sizeof(*(p))) |
755 | |
756 | GRN_API void grn_sleep(uint32_t seconds); |
757 | GRN_API void grn_nanosleep(uint64_t nanoseconds); |
758 | |
759 | #include <groonga.h> |
760 | |