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__
113typedef SSIZE_T ssize_t;
114typedef int pid_t;
115typedef 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
122typedef 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
142typedef 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
153typedef char int_least8_t;
154# endif /* INT_LEAST8_MAX */
155# ifndef UINT_LEAST8_MAX
156typedef unsigned char uint_least8_t;
157# endif /* UINT_LEAST8_MAX */
158typedef 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>
210typedef pthread_t grn_thread;
211typedef 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))
216typedef 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
233typedef 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
239typedef 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
256typedef 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 */
297typedef 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
304typedef uintptr_t grn_thread;
305typedef 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)
311typedef 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)
317typedef 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
323typedef 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 */
397typedef 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
587typedef uint8_t byte;
588
589#define GRN_ID_WIDTH 30
590
591#ifdef __GNUC__
592inline static int
593grn_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
756GRN_API void grn_sleep(uint32_t seconds);
757GRN_API void grn_nanosleep(uint64_t nanoseconds);
758
759#include <groonga.h>
760