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