/* -*- c-basic-offset: 2 -*- */ /* Copyright(C) 2009-2017 Brazil This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ #pragma once #ifdef HAVE_CONFIG_H # include #endif /* HAVE_CONFIG_H */ #ifdef WIN32 # ifdef __GNUC__ # define __MINGW_MSVC_COMPAT_WARNINGS # endif /* __GNUC__ */ # ifdef __GNUC__ # include # define GRN_MINIMUM_WINDOWS_VERSION WindowsVista # else /* __GNUC__ */ # define GRN_MINIMUM_WINDOWS_VERSION 0x0600 /* Vista */ # endif /* __GNUC__ */ # ifdef WINVER # undef WINVER # endif /* WINVER */ # define WINVER GRN_MINIMUM_WINDOWS_VERSION # ifdef _WIN32_WINNT # undef _WIN32_WINNT # endif /* _WIN32_WINNT */ # define _WIN32_WINNT GRN_MINIMUM_WINDOWS_VERSION # ifdef NTDDI_VERSION # undef NTDDI_VERSION # endif /* NTDDI_VERSION */ # define NTDDI_VERSION GRN_MINIMUM_WINDOWS_VERSION # ifdef WIN32_LEAN_AND_MEAN # undef WIN32_LEAN_AND_MEAN # endif /* WIN32_LEAN_AND_MEAN */ #endif /* WIN32 */ #ifdef __cplusplus # define __STDC_LIMIT_MACROS #endif #include #include #include #ifdef HAVE_SYS_PARAM_H # include #endif /* HAVE_SYS_PARAM_H */ #ifdef HAVE_SYS_MMAN_H # include #endif /* HAVE_SYS_MMAN_H */ #ifdef HAVE_SYS_TIME_H # include #endif /* HAVE_SYS_TIME_H */ #ifdef HAVE_SYS_RESOURCE_H # include #endif /* HAVE_SYS_RESOURCE_H */ #ifdef WIN32 # define GRN_API __declspec(dllexport) # ifdef GROONGA_MAIN # define GRN_VAR __declspec(dllimport) # else # define GRN_VAR __declspec(dllexport) extern # endif /* GROONGA_MAIN */ #else # define GRN_API # define GRN_VAR extern #endif #ifdef WIN32 # include # include # include # include # include # include # include # include # include # include # ifndef __GNUC__ # define PATH_MAX (MAX_PATH - 1) # ifndef __cplusplus # define inline _inline # endif # endif # ifndef __GNUC__ typedef SSIZE_T ssize_t; typedef int pid_t; typedef int64_t off64_t; # endif # undef MSG_WAITALL # define MSG_WAITALL 0 /* before Vista, not supported... */ # define SHUT_RDWR SD_BOTH typedef SOCKET grn_sock; # define grn_sock_close(sock) closesocket(sock) # define CALLBACK __stdcall # ifndef __GNUC__ # include # include # include # endif #else /* WIN32 */ # define GROONGA_API # ifdef HAVE_UNISTD_H # include # endif /* HAVE_UNISTD_H */ # ifndef __off64_t_defined typedef off_t off64_t; # endif # ifndef PATH_MAX # if defined(MAXPATHLEN) # define PATH_MAX MAXPATHLEN # else /* MAXPATHLEN */ # define PATH_MAX 1024 # endif /* MAXPATHLEN */ # endif /* PATH_MAX */ # ifndef INT_LEAST8_MAX typedef char int_least8_t; # endif /* INT_LEAST8_MAX */ # ifndef UINT_LEAST8_MAX typedef unsigned char uint_least8_t; # endif /* UINT_LEAST8_MAX */ typedef int grn_sock; # define grn_sock_close(sock) close(sock) # define CALLBACK #endif /* WIN32 */ #ifndef INT8_MAX # define INT8_MAX (127) #endif /* INT8_MAX */ #ifndef INT8_MIN # define INT8_MIN (-128) #endif /* INT8_MIN */ #ifndef INT16_MAX # define INT16_MAX (32767) #endif /* INT16_MAX */ #ifndef INT16_MIN # define INT16_MIN (-32768) #endif /* INT16_MIN */ #ifndef INT32_MAX # define INT32_MAX (2147483647) #endif /* INT32_MAX */ #ifndef INT32_MIN # define INT32_MIN (-2147483648) #endif /* INT32_MIN */ #ifndef UINT32_MAX # define UINT32_MAX (4294967295) #endif /* UINT32_MAX */ #ifndef INT64_MAX # define INT64_MAX (9223372036854775807) #endif /* INT64_MAX */ #ifndef INT64_MIN # define INT64_MIN (-9223372036854775808) #endif /* INT64_MIN */ #ifdef WIN32 # define grn_lseek(fd, offset, whence) _lseeki64(fd, offset, whence) #else /* WIN32 */ # define grn_lseek(fd, offset, whence) lseek(fd, offset, whence) #endif /* WIN32 */ #ifdef HAVE_PTHREAD_H # include typedef pthread_t grn_thread; typedef void * grn_thread_func_result; # define GRN_THREAD_FUNC_RETURN_VALUE NULL # define THREAD_CREATE(thread,func,arg) \ (pthread_create(&(thread), NULL, (func), (arg))) # define THREAD_JOIN(thread) (pthread_join(thread, NULL)) typedef pthread_mutex_t grn_mutex; # define MUTEX_INIT(m) pthread_mutex_init(&m, NULL) # define MUTEX_LOCK(m) pthread_mutex_lock(&m) # define MUTEX_LOCK_CHECK(m) (MUTEX_LOCK(m) == 0) # define MUTEX_UNLOCK(m) pthread_mutex_unlock(&m) # define MUTEX_FIN(m) pthread_mutex_destroy(&m) # ifdef HAVE_PTHREAD_MUTEXATTR_SETPSHARED # define MUTEX_INIT_SHARED(m) do {\ pthread_mutexattr_t mutexattr;\ pthread_mutexattr_init(&mutexattr);\ pthread_mutexattr_setpshared(&mutexattr, PTHREAD_PROCESS_SHARED);\ pthread_mutex_init(&m, &mutexattr);\ } while (0) # else # define MUTEX_INIT_SHARED MUTEX_INIT # endif /* HAVE_PTHREAD_MUTEXATTR_SETPSHARED */ typedef pthread_mutex_t grn_critical_section; # define CRITICAL_SECTION_INIT(cs) pthread_mutex_init(&(cs), NULL) # define CRITICAL_SECTION_ENTER(cs) pthread_mutex_lock(&(cs)) # define CRITICAL_SECTION_LEAVE(cs) pthread_mutex_unlock(&(cs)) # define CRITICAL_SECTION_FIN(cs) typedef pthread_cond_t grn_cond; # define COND_INIT(c) pthread_cond_init(&c, NULL) # define COND_SIGNAL(c) pthread_cond_signal(&c) # define COND_WAIT(c,m) pthread_cond_wait(&c, &m) # define COND_BROADCAST(c) pthread_cond_broadcast(&c) # ifdef HAVE_PTHREAD_CONDATTR_SETPSHARED # define COND_INIT_SHARED(c) do {\ pthread_condattr_t condattr;\ pthread_condattr_init(&condattr);\ pthread_condattr_setpshared(&condattr, PTHREAD_PROCESS_SHARED);\ pthread_cond_init(&c, &condattr);\ } while (0) # else # define COND_INIT_SHARED COND_INIT # endif /* HAVE_PTHREAD_CONDATTR_SETPSHARE */ # define COND_FIN(c) pthread_cond_destroy(&c) typedef pthread_key_t grn_thread_key; # define THREAD_KEY_CREATE(key, destr) pthread_key_create(key, destr) # define THREAD_KEY_DELETE(key) pthread_key_delete(key) # define THREAD_SETSPECIFIC(key, value) pthread_setspecific(key, value) # define THREAD_GETSPECIFIC(key) pthread_getspecific(key) #if defined(USE_UYIELD) extern int grn_uyield_count; #define GRN_TEST_YIELD() do {\ if (((++grn_uyield_count) & (0x20 - 1)) == 0) {\ sched_yield();\ if (grn_uyield_count > 0x1000) {\ grn_uyield_count = (uint32_t)time(NULL) % 0x1000;\ }\ }\ } while (0) #undef assert #define assert(assert_expr) do {\ if (!(assert_expr)){\ fprintf(stderr, "assertion failed: %s\n", #assert_expr);\ abort();\ }\ GRN_TEST_YIELD();\ } while (0) #define if (if_cond) \ if ((((++grn_uyield_count) & (0x100 - 1)) != 0 || (sched_yield() * 0) == 0) && (if_cond)) #define while(while_cond) \ while ((((++grn_uyield_count) & (0x100 - 1)) != 0 || (sched_yield() * 0) == 0) && (while_cond)) #if !defined(_POSIX_PRIORITY_SCHEDULING) #define sched_yield() grn_nanosleep(1000000 * 20) #endif # else /* USE_UYIELD */ #define GRN_TEST_YIELD() do {} while (0) # endif /* USE_UYIELD */ #else /* HAVE_PTHREAD_H */ /* todo */ typedef int grn_thread_key; # define THREAD_KEY_CREATE(key,destr) # define THREAD_KEY_DELETE(key) # define THREAD_SETSPECIFIC(key) # define THREAD_GETSPECIFIC(key,value) # ifdef WIN32 typedef uintptr_t grn_thread; typedef unsigned int grn_thread_func_result; # define GRN_THREAD_FUNC_RETURN_VALUE 0 # define THREAD_CREATE(thread,func,arg) \ (((thread)=_beginthreadex(NULL, 0, (func), (arg), 0, NULL)) == (grn_thread)0) # define THREAD_JOIN(thread) \ (WaitForSingleObject((HANDLE)(thread), INFINITE) == WAIT_FAILED) typedef HANDLE grn_mutex; # define MUTEX_INIT(m) ((m) = CreateMutex(0, FALSE, NULL)) # define MUTEX_LOCK(m) WaitForSingleObject((m), INFINITE) # define MUTEX_LOCK_CHECK(m) (MUTEX_LOCK(m) == WAIT_OBJECT_0) # define MUTEX_UNLOCK(m) ReleaseMutex(m) # define MUTEX_FIN(m) CloseHandle(m) typedef CRITICAL_SECTION grn_critical_section; # define CRITICAL_SECTION_INIT(cs) InitializeCriticalSection(&(cs)) # define CRITICAL_SECTION_ENTER(cs) EnterCriticalSection(&(cs)) # define CRITICAL_SECTION_LEAVE(cs) LeaveCriticalSection(&(cs)) # define CRITICAL_SECTION_FIN(cs) DeleteCriticalSection(&(cs)) typedef struct { int waiters_count_; HANDLE waiters_count_lock_; HANDLE sema_; HANDLE waiters_done_; size_t was_broadcast_; } grn_cond; # define COND_INIT(c) do { \ (c).waiters_count_ = 0; \ (c).sema_ = CreateSemaphore(NULL, 0, 0x7fffffff, NULL); \ MUTEX_INIT((c).waiters_count_lock_); \ (c).waiters_done_ = CreateEvent(NULL, FALSE, FALSE, NULL); \ } while (0) # define COND_SIGNAL(c) do { \ MUTEX_LOCK((c).waiters_count_lock_); \ { \ int have_waiters = (c).waiters_count_ > 0; \ MUTEX_UNLOCK((c).waiters_count_lock_); \ if (have_waiters) { \ ReleaseSemaphore((c).sema_, 1, 0); \ } \ } \ } while (0) # define COND_BROADCAST(c) do { \ MUTEX_LOCK((c).waiters_count_lock_); \ { \ int have_waiters = (c).waiters_count_ > 0; \ if ((c).waiters_count_ > 0) { \ (c).was_broadcast_ = 1; \ have_waiters = 1; \ } \ if (have_waiters) { \ ReleaseSemaphore((c).sema_, (c).waiters_count_, 0); \ MUTEX_UNLOCK((c).waiters_count_lock_); \ WaitForSingleObject((c).waiters_done_, INFINITE); \ (c).was_broadcast_ = 0; \ } \ else { \ MUTEX_UNLOCK((c).waiters_count_lock_); \ } \ } \ } while (0) # define COND_WAIT(c,m) do { \ MUTEX_LOCK((c).waiters_count_lock_); \ (c).waiters_count_++; \ MUTEX_UNLOCK((c).waiters_count_lock_); \ SignalObjectAndWait((m), (c).sema_, INFINITE, FALSE); \ MUTEX_LOCK((c).waiters_count_lock_); \ (c).waiters_count_--; \ { \ int last_waiter = (c).was_broadcast_ && (c).waiters_count_ == 0; \ MUTEX_UNLOCK((c).waiters_count_lock_); \ if (last_waiter) { \ SignalObjectAndWait((c).waiters_done_, (m), INFINITE, FALSE); \ } \ else { \ WaitForSingleObject((m), FALSE); \ } \ } \ } while (0) # define COND_FIN(c) do { \ CloseHandle((c).waiters_done_); \ MUTEX_FIN((c).waiters_count_lock_); \ CloseHandle((c).sema_); \ } while (0) # else /* WIN32 */ /* todo */ typedef int grn_cond; # define COND_INIT(c) ((c) = 0) # define COND_SIGNAL(c) # define COND_WAIT(c,m) do { \ MUTEX_UNLOCK(m); \ grn_nanosleep(1000000); \ MUTEX_LOCK(m); \ } while (0) # define COND_FIN(c) /* todo : must be enhanced! */ # endif /* WIN32 */ # define MUTEX_INIT_SHARED MUTEX_INIT # define COND_INIT_SHARED COND_INIT # define GRN_TEST_YIELD() do {} while (0) #endif /* HAVE_PTHREAD_H */ #define MUTEX_LOCK_ENSURE(ctx_, mutex) do { \ grn_ctx *ctx__ = (ctx_); \ do { \ grn_ctx *ctx = ctx__; \ if (MUTEX_LOCK_CHECK(mutex)) { \ break; \ } \ if (ctx) { \ SERR("MUTEX_LOCK"); \ } \ grn_nanosleep(1000000); \ } while (GRN_TRUE); \ } while (GRN_FALSE) /* format string for printf */ #ifdef HAVE_INTTYPES_H # include # define GRN_FMT_INT32D PRId32 # define GRN_FMT_INT32U PRIu32 # define GRN_FMT_INT64D PRId64 # define GRN_FMT_INT64U PRIu64 #else /* HAVE_INTTYPES_H */ # ifdef WIN32 # define GRN_FMT_INT32D "I32d" # define GRN_FMT_INT32U "I32u" # define GRN_FMT_INT64D "I64d" # define GRN_FMT_INT64U "I64u" # else /* WIN32 */ # define GRN_FMT_INT32D "d" # define GRN_FMT_INT32U "u" # ifdef __x86_64__ # define GRN_FMT_INT64D "ld" # define GRN_FMT_INT64U "lu" # else /* __x86_64__ */ # define GRN_FMT_INT64D "lld" # define GRN_FMT_INT64U "llu" # endif /* __x86_64__ */ # endif /* WIN32 */ #endif /* HAVE_INTTYPES_H */ #ifdef WIN32 # define GRN_FMT_LLD "I64d" # define GRN_FMT_LLU "I64u" # define GRN_FMT_SIZE "Iu" # define GRN_FMT_SSIZE "Id" # ifdef WIN64 # define GRN_FMT_SOCKET GRN_FMT_INT64U # define GRN_FMT_DWORD "lu" # else /* WIN64 */ # define GRN_FMT_SOCKET GRN_FMT_INT32U # define GRN_FMT_DWORD "u" # endif /* WIN64 */ # define GRN_FMT_OFF64_T GRN_FMT_LLD #else /* WIN32 */ # define GRN_FMT_LLD "lld" # define GRN_FMT_LLU "llu" # define GRN_FMT_SIZE "zu" # define GRN_FMT_SSIZE "zd" # define GRN_FMT_SOCKET "d" # define GRN_FMT_OFF64_T "jd" #endif /* WIN32 */ #ifdef __GNUC__ # if (defined(__i386__) || defined(__x86_64__)) /* ATOMIC ADD */ /* * GRN_ATOMIC_ADD_EX() performs { r = *p; *p += i; } atomically. */ # define GRN_ATOMIC_ADD_EX(p, i, r) \ __asm__ __volatile__ ("lock xaddl %0, %1" : "=r"(r), "+m"(*p) : "0"(i)) /* * GRN_BIT_SCAN_REV() finds the most significant 1 bit of `v'. Then, `r' is set * to the index of the found bit. Note that `v' must not be 0. */ # define GRN_BIT_SCAN_REV(v, r) \ __asm__ __volatile__ ("bsrl %1, %%eax; movl %%eax, %0" : "=r"(r) : "r"(v) : "%eax") /* * GRN_BIT_SCAN_REV0() is similar to GRN_BIT_SCAN_REV() but if `v' is 0, `r' is * set to 0. */ # define GRN_BIT_SCAN_REV0(v, r) \ __asm__ __volatile__ ("bsrl %1, %%eax; cmovzl %1, %%eax; movl %%eax, %0" : "=r"(r) : "r"(v) : "%eax", "cc") # elif (defined(__PPC__) || defined(__ppc__)) /* ATOMIC ADD */ # define GRN_ATOMIC_ADD_EX(p,i,r) \ __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") /* todo */ # define GRN_BIT_SCAN_REV(v,r) for (r = 31; r && !((1 << r) & v); r--) # define GRN_BIT_SCAN_REV0(v,r) GRN_BIT_SCAN_REV(v,r) # elif (defined(__sun) && defined(__SVR4)) /* ATOMIC ADD */ # include # define GRN_ATOMIC_ADD_EX(p,i,r) \ (r = atomic_add_32_nv(p, i) - i) /* todo */ # define GRN_BIT_SCAN_REV(v,r) for (r = 31; r && !((1 << r) & v); r--) # define GRN_BIT_SCAN_REV0(v,r) GRN_BIT_SCAN_REV(v,r) # elif defined(__ATOMIC_SEQ_CST) /* GCC atomic builtins */ # define GRN_ATOMIC_ADD_EX(p,i,r) \ (r = __atomic_fetch_add(p, i, __ATOMIC_SEQ_CST)) # define GRN_BIT_SCAN_REV(v,r) for (r = 31; r && !((1 << r) & v); r--) # define GRN_BIT_SCAN_REV0(v,r) GRN_BIT_SCAN_REV(v,r) # else /* ATOMIC ADD */ /* todo */ # define GRN_BIT_SCAN_REV(v,r) for (r = 31; r && !((1 << r) & v); r--) # define GRN_BIT_SCAN_REV0(v,r) GRN_BIT_SCAN_REV(v,r) # endif /* ATOMIC ADD */ # ifdef __i386__ /* ATOMIC 64BIT SET */ # define GRN_SET_64BIT(p,v) \ __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") # elif defined(__x86_64__) /* ATOMIC 64BIT SET */ # define GRN_SET_64BIT(p,v) \ (*(p) = (v)) # elif (defined(__sun) && defined(__SVR4)) /* ATOMIC 64BIT SET */ /* todo */ # define GRN_SET_64BIT(p,v) \ (void)atomic_swap_64(p, v) # elif defined(__ATOMIC_SEQ_CST) /* GCC atomic builtins */ # define GRN_SET_64BIT(p,v) \ __atomic_store_n(p, v, __ATOMIC_SEQ_CST) # else # warning Need atomic 64bit operation support. The current implementation may break data. # define GRN_SET_64BIT(p,v) \ (*(p) = (v)) # endif /* ATOMIC 64BIT SET */ #elif (defined(WIN32) || defined (_WIN64)) /* __GNUC__ */ # define GRN_ATOMIC_ADD_EX(p,i,r) \ ((r) = InterlockedExchangeAdd((p), (i))) # if defined(_WIN64) /* ATOMIC 64BIT SET */ # define GRN_SET_64BIT(p,v) \ (*(p) = (v)) # else /* ATOMIC 64BIT SET */ # define GRN_SET_64BIT(p,v) do {\ uint32_t v1, v2; \ uint64_t *p2= (p); \ v1 = *(((uint32_t *)&(v))+0);\ v2 = *(((uint32_t *)&(v))+1);\ __asm _set_loop: \ __asm mov esi, p2 \ __asm mov ebx, v1 \ __asm mov ecx, v2 \ __asm mov eax, dword ptr [esi] \ __asm mov edx, dword ptr [esi + 4] \ __asm lock cmpxchg8b qword ptr [esi] \ __asm jnz _set_loop \ } while (0) /* TODO: use _InterlockedCompareExchange64 or inline asm */ # endif /* ATOMIC 64BIT SET */ /* todo */ # define GRN_BIT_SCAN_REV(v,r) for (r = 31; r && !((1 << r) & v); r--) # define GRN_BIT_SCAN_REV0(v,r) GRN_BIT_SCAN_REV(v,r) #else /* __GNUC__ */ # if (defined(__sun) && defined(__SVR4)) /* ATOMIC ADD */ # define __FUNCTION__ "" # include # define GRN_ATOMIC_ADD_EX(p,i,r) \ (r = atomic_add_32_nv(p, i) - i) /* todo */ # define GRN_SET_64BIT(p,v) \ (void)atomic_swap_64(p, v) # endif /* ATOMIC ADD */ /* todo */ # define GRN_BIT_SCAN_REV(v,r) for (r = 31; r && !((1 << r) & v); r--) # define GRN_BIT_SCAN_REV0(v,r) GRN_BIT_SCAN_REV(v,r) #endif /* __GNUC__ */ typedef uint8_t byte; #define GRN_ID_WIDTH 30 #ifdef __GNUC__ inline static int grn_str_greater(const uint8_t *ap, uint32_t as, const uint8_t *bp, uint32_t bs) { for (;; ap++, bp++, as--, bs--) { if (!as) { return 0; } if (!bs) { return 1; } if (*ap < *bp) { return 0; } if (*ap > *bp) { return 1; } } } #else /* __GNUC__ */ # define grn_str_greater(ap,as,bp,bs)\ (((as) > (bs)) ? (memcmp((ap), (bp), (bs)) >= 0) : (memcmp((ap), (bp), (as)) > 0)) #endif /* __GNUC__ */ #ifdef WORDS_BIGENDIAN # define grn_hton(buf,key,size) do {\ uint32_t size_ = (uint32_t)size;\ uint8_t *buf_ = (uint8_t *)buf;\ uint8_t *key_ = (uint8_t *)key;\ while (size_--) { *buf_++ = *key_++; }\ } while (0) # define grn_ntohi(buf,key,size) do {\ uint32_t size_ = (uint32_t)size;\ uint8_t *buf_ = (uint8_t *)buf;\ uint8_t *key_ = (uint8_t *)key;\ if (size_) { *buf_++ = 0x80 ^ *key_++; size_--; }\ while (size_) { *buf_++ = *key_++; size_--; }\ } while (0) #else /* WORDS_BIGENDIAN */ # define grn_hton(buf,key,size) do {\ uint32_t size_ = (uint32_t)size;\ uint8_t *buf_ = (uint8_t *)buf;\ uint8_t *key_ = (uint8_t *)key + size;\ while (size_--) { *buf_++ = *(--key_); }\ } while (0) # define grn_ntohi(buf,key,size) do {\ uint32_t size_ = (uint32_t)size;\ uint8_t *buf_ = (uint8_t *)buf;\ uint8_t *key_ = (uint8_t *)key + size;\ while (size_ > 1) { *buf_++ = *(--key_); size_--; }\ if (size_) { *buf_ = 0x80 ^ *(--key_); } \ } while (0) #endif /* WORDS_BIGENDIAN */ #define grn_ntoh(buf,key,size) grn_hton(buf,key,size) #ifndef __GNUC_PREREQ # if defined(__GNUC__) && defined(__GNUC_MINOR__) # define __GNUC_PREREQ(maj, min) \ ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min)) # else # define __GNUC_PREREQ(maj, min) 0 # endif /* defined(__GNUC__) && defined(__GNUC_MINOR__) */ #endif /* __GNUC_PREREQ */ #ifdef _MSC_VER # define grn_bswap_uint64(in, out) ((out) = _byteswap_uint64(in)) #else /* _MSC_VER */ # if defined(__GNUC__) && __GNUC_PREREQ(4, 3) # define grn_bswap_uint64(in, out) ((out) = __builtin_bswap64(in)) # else /* defined(__GNUC__) && __GNUC_PREREQ(4, 3) */ # define grn_bswap_uint64(in, out) do {\ uint64_t temp_ = (in);\ (out) = (temp_ << 56) |\ ((temp_ & (0xFFULL << 8)) << 40) |\ ((temp_ & (0xFFULL << 16)) << 24) |\ ((temp_ & (0xFFULL << 24)) << 8) |\ ((temp_ & (0xFFULL << 32)) >> 8) |\ ((temp_ & (0xFFULL << 40)) >> 24) |\ ((temp_ & (0xFFULL << 48)) >> 40) |\ (temp_ >> 56);\ } while (0) # endif /* __GNUC__ */ #endif /* _MSC_VER */ #ifdef WORDS_BIGENDIAN # define grn_hton_uint64(in, out) ((out) = (in)) #else /* WORDS_BIGENDIAN */ # define grn_hton_uint64(in, out) grn_bswap_uint64(in, out) #endif /* WORDS_BIGENDIAN */ #define grn_ntoh_uint64(in, out) grn_hton_uint64(in, out) #define grn_gton(keybuf,key,size) do {\ const grn_geo_point *point_ = (const grn_geo_point *)key;\ uint64_t la_ = (uint32_t)point_->latitude;\ uint64_t lo_ = (uint32_t)point_->longitude;\ uint64_t result_;\ la_ = (la_ | (la_ << 16)) & 0x0000FFFF0000FFFFULL;\ la_ = (la_ | (la_ << 8)) & 0x00FF00FF00FF00FFULL;\ la_ = (la_ | (la_ << 4)) & 0x0F0F0F0F0F0F0F0FULL;\ la_ = (la_ | (la_ << 2)) & 0x3333333333333333ULL;\ la_ = (la_ | (la_ << 1)) & 0x5555555555555555ULL;\ lo_ = (lo_ | (lo_ << 16)) & 0x0000FFFF0000FFFFULL;\ lo_ = (lo_ | (lo_ << 8)) & 0x00FF00FF00FF00FFULL;\ lo_ = (lo_ | (lo_ << 4)) & 0x0F0F0F0F0F0F0F0FULL;\ lo_ = (lo_ | (lo_ << 2)) & 0x3333333333333333ULL;\ lo_ = (lo_ | (lo_ << 1)) & 0x5555555555555555ULL;\ result_ = (la_ << 1) | lo_;\ grn_hton_uint64(result_, result_);\ grn_memcpy(keybuf, &result_, sizeof(result_));\ } while (0) #define grn_ntog(keybuf,key,size) do {\ grn_geo_point *point_ = (grn_geo_point *)keybuf;\ uint64_t key_ = *(const uint64_t *)key;\ uint64_t la_, lo_;\ grn_ntoh_uint64(key_, key_);\ la_ = (key_ >> 1) & 0x5555555555555555ULL;\ lo_ = key_ & 0x5555555555555555ULL;\ la_ = (la_ | (la_ >> 1)) & 0x3333333333333333ULL;\ la_ = (la_ | (la_ >> 2)) & 0x0F0F0F0F0F0F0F0FULL;\ la_ = (la_ | (la_ >> 4)) & 0x00FF00FF00FF00FFULL;\ la_ = (la_ | (la_ >> 8)) & 0x0000FFFF0000FFFFULL;\ la_ = (la_ | (la_ >> 16)) & 0x00000000FFFFFFFFULL;\ lo_ = (lo_ | (lo_ >> 1)) & 0x3333333333333333ULL;\ lo_ = (lo_ | (lo_ >> 2)) & 0x0F0F0F0F0F0F0F0FULL;\ lo_ = (lo_ | (lo_ >> 4)) & 0x00FF00FF00FF00FFULL;\ lo_ = (lo_ | (lo_ >> 8)) & 0x0000FFFF0000FFFFULL;\ lo_ = (lo_ | (lo_ >> 16)) & 0x00000000FFFFFFFFULL;\ point_->latitude = la_;\ point_->longitude = lo_;\ } while (0) #ifdef HAVE__STRTOUI64 # define strtoull(nptr,endptr,base) _strtoui64(nptr,endptr,base) #endif /* HAVE__STRTOUI64 */ #ifdef USE_FUTEX # include # include # define GRN_FUTEX_WAIT(p) do {\ int err;\ struct timespec timeout = {1, 0};\ while (1) {\ if (!(err = syscall(SYS_futex, p, FUTEX_WAIT, *p, &timeout))) {\ break;\ }\ if (err == ETIMEDOUT) {\ GRN_LOG(ctx, GRN_LOG_CRIT, "timeout in GRN_FUTEX_WAIT(%p)", p);\ break;\ } else if (err != EWOULDBLOCK) {\ GRN_LOG(ctx, GRN_LOG_CRIT, "error %d in GRN_FUTEX_WAIT(%p)", err);\ break;\ }\ }\ } while(0) # define GRN_FUTEX_WAKE(p) syscall(SYS_futex, p, FUTEX_WAKE, 1) #else /* USE_FUTEX */ # define GRN_FUTEX_WAIT(p) grn_nanosleep(1000000) # define GRN_FUTEX_WAKE(p) #endif /* USE_FUTEX */ #ifndef HOST_NAME_MAX # ifdef _POSIX_HOST_NAME_MAX # define HOST_NAME_MAX _POSIX_HOST_NAME_MAX # else /* POSIX_HOST_NAME_MAX */ # define HOST_NAME_MAX 128 # endif /* POSIX_HOST_NAME_MAX */ #endif /* HOST_NAME_MAX */ #define GRN_NEXT_ADDR(p) (((byte *)(p)) + sizeof(*(p))) GRN_API void grn_sleep(uint32_t seconds); GRN_API void grn_nanosleep(uint64_t nanoseconds); #include