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-1335 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
grn_str_greater(const uint8_t * ap,uint32_t as,const uint8_t * bp,uint32_t bs)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