/*
* Copyright (C) 2008 Search Solution Corporation. All rights reserved by Search Solution.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
/*
* porting.h - Functions supporting platform porting
*/
#ifndef _PORTING_H_
#define _PORTING_H_
#ident "$Id$"
#include "config.h"
#ifdef __cplusplus
extern "C"
{
#endif
#if defined(AIX)
#include <sys/socket.h>
#endif
#if !defined(__GNUC__)
#define __attribute__(X)
#endif
#if defined(MAC_OS)
#include <stdlib.h>
#endif
#if defined(WINDOWS)
#define IMPORT_VAR __declspec(dllimport)
#define EXPORT_VAR __declspec(dllexport)
#else
#define IMPORT_VAR extern
#define EXPORT_VAR
#endif
#if defined(WINDOWS)
#define L_cuserid 9
#else /* WINDOWS */
#ifndef L_cuserid
#define L_cuserid 9
#endif /* !L_cuserid */
#endif /* WINDOWS */
#define ONE_K 1024
#define ONE_M 1048576
#define ONE_G 1073741824
#define ONE_T 1099511627776LL
#define ONE_P 1125899906842624LL
#define ONE_SEC 1000
#define ONE_MIN 60000
#define ONE_HOUR 3600000
#define CTIME_MAX 64
#if defined(WINDOWS)
#include <fcntl.h>
#include <direct.h>
#include <process.h>
#include <sys/timeb.h>
#include <time.h>
#include <sys/locking.h>
#include <windows.h>
#include <winbase.h>
#include <errno.h>
#include <assert.h>
/* not defined errno on Windows */
#define ENOMSG 100
#define PATH_MAX 256
#define NAME_MAX 256
#define log2(x) (log ((double) x) / log ((double) 2))
extern char *realpath (const char *path, char *resolved_path);
#define sleep(sec) Sleep(1000*(sec))
#define usleep(usec) Sleep((usec)/1000)
#define mkdir(dir, mode) _mkdir(dir)
#define getpid() _getpid()
#define snprintf _sprintf_p
#define strcasecmp(str1, str2) _stricmp(str1, str2)
#define strncasecmp(str1, str2, size) _strnicmp(str1, str2, size)
#define lseek(fd, offset, origin) _lseeki64(fd, offset, origin)
#define fseek(fd, offset, origin) _fseeki64(fd, offset, origin)
#define ftruncate(fd, size) _chsize_s(fd, size)
#define strdup(src) _strdup(src)
#define getcwd(buffer, length) _getcwd(buffer, length)
#define popen _popen
#define pclose _pclose
#define strtok_r strtok_s
#define strtoll _strtoi64
#define strtoull _strtoui64
#define stat _stati64
#define fstat _fstati64
#define ftime _ftime_s
#define timeb _timeb
#define fileno _fileno
#define vsnprintf cub_vsnprintf
#define tempnam _tempnam
#define printf _printf_p
#define fprintf _fprintf_p
#define vfprintf _vfprintf_p
#define vprintf _vprintf_p
#if (_WIN32_WINNT < 0x0600)
#define POLLRDNORM 0x0100
#define POLLRDBAND 0x0200
#define POLLIN (POLLRDNORM | POLLRDBAND)
#define POLLPRI 0x0400
#define POLLWRNORM 0x0010
#define POLLOUT (POLLWRNORM)
#define POLLWRBAND 0x0020
#define POLLERR 0x0001
#define POLLHUP 0x0002
#define POLLNVAL 0x0004
struct pollfd
{
SOCKET fd;
SHORT events;
SHORT revents;
};
#endif /* (_WIN32_WINNT < 0x0600) */
typedef unsigned long int nfds_t;
extern int poll (struct pollfd *fds, nfds_t nfds, int timeout);
#if 0
#define O_RDONLY _O_RDONLY
#endif
#define O_SYNC 0
#undef O_CREAT
#undef O_RDWR
#undef O_RDONLY
#undef O_TRUNC
#undef O_EXCL
#define O_CREAT _O_CREAT|_O_BINARY
#define O_RDWR _O_RDWR|_O_BINARY
#define O_RDONLY _O_RDONLY|_O_BINARY
#define O_TRUNC _O_TRUNC|_O_BINARY
#define O_EXCL _O_EXCL|_O_BINARY
/* Fake up approxomate DOS definitions see sys/stat.h */
/* for umask() stub */
#define S_IRGRP 0
#define S_IWGRP 0
#define S_IROTH 0
#define S_IWOTH 0
/* read, write, execute for owner */
#define S_IRWXU _S_IREAD | _S_IWRITE | _S_IEXEC
/* rwx for group, same as owner since there are no groups in DOS */
#define S_IRWXG S_IRWXU
/* rwx for other, same as owner since there are no groups in DOS */
#define S_IRWXO S_IRWXU
/* access() mode flags */
#define F_OK 0 /* Test for existence. */
#define W_OK 2 /* Test for write permission. */
#define R_OK 4 /* Test for read permission. */
/* definitions for the WINDOWS implementation of lockf() */
#define F_ULOCK _LK_UNLCK
#define F_LOCK _LK_LOCK
#define F_TLOCK _LK_NBLCK
#define F_TEST -1
/* definitions for the WINDOWS implmentation of pathconf() */
#define _PC_NAME_MAX 4
#define _PC_PATH_MAX 5
#define _PC_NO_TRUNC 8
/*
* MAXHOSTNAMELEN definition
* This is defined in sys/param.h on the linux.
*/
#define MAXHOSTNAMELEN 64
typedef char *caddr_t;
typedef SSIZE_T ssize_t;
#if 0
struct stat
{
_dev_t st_dev;
_ino_t st_ino;
unsigned short st_mode;
short st_nlink;
short st_uid;
short st_gid;
_dev_t st_rdev;
_off_t st_size;
time_t st_atime;
time_t st_mtime;
time_t st_ctime;
};
extern int stat (const char *path, struct stat *buf);
#endif
extern int gettimeofday (struct timeval *tp, void *tzp);
extern int lockf (int fd, int cmd, long size);
extern char *cuserid (char *string);
extern int getlogin_r (char *buf, size_t bufsize);
extern struct tm *localtime_r (const time_t * time, struct tm *tm_val);
extern char *ctime_r (const time_t * time, char *time_buf);
#if 0
extern int umask (int mask);
#endif
int fsync (int filedes);
long pathconf (char *path, int name);
/*
* Used by the sigfillset() etc. function in pcio.c
*/
typedef struct sigsettype
{
unsigned int mask;
void (*abrt_state) (int);
void (*fpe_state) (int);
void (*ill_state) (int);
void (*int_state) (int);
void (*term_state) (int);
void (*sev_state) (int);
} sigset_t;
int sigfillset (sigset_t * set);
int sigprocmask (int how, sigset_t * set, sigset_t * oldset);
/*
* MS Windows specific operations
*/
extern void pc_init (void);
extern void pc_final (void);
#if defined(ENABLE_UNUSED_FUNCTION)
extern int lock_region (int fd, int cmd, long offset, long size);
#endif
extern int free_space (const char *);
#define _longjmp longjmp
/*
#define _setjmp setjmp
*/
#elif !defined(MAC_OS) /* WINDOWS */
#if !defined(HAVE_CTIME_R)
# error "HAVE_CTIME_R"
#endif
#if !defined(HAVE_LOCALTIME_R)
# error "HAVE_LOCALTIME_R"
#endif
#if !defined(HAVE_DRAND48_R)
# error "HAVE_DRAND48_R"
#endif
#endif /* WINDOWS */
#if defined(WINDOWS)
#define PATH_SEPARATOR '\\'
#else /* WINDOWS */
#define PATH_SEPARATOR '/'
#endif /* WINDOWS */
#define PATH_CURRENT '.'
#define IS_PATH_SEPARATOR(c) ((c) == PATH_SEPARATOR)
#if defined(WINDOWS)
#define IS_ABS_PATH(p) IS_PATH_SEPARATOR((p)[0]) \
|| (isalpha((p)[0]) && (p)[1] == ':' && IS_PATH_SEPARATOR((p)[2]))
#else /* WINDOWS */
#define IS_ABS_PATH(p) IS_PATH_SEPARATOR((p)[0])
#endif /* WINDOWS */
/*
* Some platforms (e.g., Solaris) evidently don't define _longjmp. If
* it's not available, just use regular old longjmp.
*/
#if defined(SOLARIS) || defined(WINDOWS)
#define LONGJMP longjmp
#define SETJMP setjmp
#else
#define LONGJMP _longjmp
#define SETJMP _setjmp
#endif
#if defined(WINDOWS)
#define GETHOSTNAME(p, l) css_gethostname(p, l)
#else /* ! WINDOWS */
#define GETHOSTNAME(p, l) gethostname(p, l)
#endif /* ! WINDOWS */
#if defined(WINDOWS)
#define FINITE(x) _finite(x)
#elif defined(HPUX)
#define FINITE(x) isfinite(x)
#else /* ! WINDOWS && ! HPUX */
#define FINITE(x) finite(x)
#endif
#if defined(WINDOWS)
#define difftime64(time1, time2) _difftime64(time1, time2)
#else /* !WINDOWS */
#define difftime64(time1, time2) difftime(time1, time2)
#endif /* !WINDOWS */
#if defined(WINDOWS)
#ifndef wcswcs
#define wcswcs(ws1, ws2) wcsstr((ws1), (ws2))
#endif
#define wcsspn(ws1, ws2) ((int) wcsspn((ws1), (ws2)))
#endif /* WINDOWS */
#if defined(SOLARIS)
#define wcslen(ws) wslen((ws))
#define wcschr(ws, wc) wschr((ws), (wc))
#define wcsrchr(ws, wc) wsrchr((ws), (wc))
#define wcstok(ws1, ws2) wstok((ws1), (ws2))
#define wcscoll(ws1, ws2) wscoll((ws1), (ws2))
#define wcsspn(ws1, ws2) wsspn((ws1), (ws2))
#define wcscspn(ws1, ws2) wscspn((ws1), (ws2))
#define wcscmp(ws1, ws2) wscmp((ws1), (ws2))
#define wcsncmp(ws1, ws2, n) wsncmp((ws1), (ws2), (n))
#define wcscpy(ws1, ws2) wscpy((ws1), (ws2))
#define wcsncpy(ws1, ws2, n) wsncpy((ws1), (ws2), (n))
#endif /* SOLARIS */
#if !defined(HAVE_STRDUP)
extern char *strdup (const char *str);
#endif /* HAVE_STRDUP */
#if !defined(HAVE_VASPRINTF)
extern int vasprintf (char **ptr, const char *format, va_list ap);
#endif /* HAVE_VASPRINTF */
#if !defined(HAVE_ASPRINTF)
extern int asprintf (char **ptr, const char *format, ...);
#endif /* HAVE_ASPRINTF */
#if defined(HAVE_ERR_H)
#include <err.h>
#else
#define err(fd, ...) do { fprintf(stderr, __VA_ARGS__); exit(1); } while (0)
#define errx(fd, ...) do { fprintf(stderr, __VA_ARGS__); exit(1); } while (0)
#endif
extern int cub_dirname_r (const char *path, char *pathbuf, size_t buflen);
#if defined(AIX)
double aix_ceil (double x);
#define ceil(x) aix_ceil(x)
#endif
#if !defined(HAVE_DIRNAME)
char *dirname (const char *path);
#endif /* HAVE_DIRNAME */
extern int basename_r (const char *path, char *pathbuf, size_t buflen);
#if !defined(HAVE_BASENAME)
extern char *basename (const char *path);
#endif /* HAVE_BASENAME */
#if defined(WINDOWS)
#if !defined(HAVE_STRSEP)
extern char *strsep (char **stringp, const char *delim);
#endif
extern char *getpass (const char *prompt);
#endif
#if defined(ENABLE_UNUSED_FUNCTION)
extern int utona (unsigned int u, char *s, size_t n);
extern int itona (int i, char *s, size_t n);
#endif
extern char *stristr (const char *s, const char *find);
#define strlen(s1) ((int) strlen(s1))
#define CAST_STRLEN (int)
#define CAST_BUFLEN (int)
#if _FILE_OFFSET_BITS == 32
#define OFF_T_MAX INT_MAX
#else
#define OFF_T_MAX LLONG_MAX
#endif
#if defined(WINDOWS)
#define IS_INVALID_SOCKET(socket) ((socket) == INVALID_SOCKET)
typedef int socklen_t;
#else
typedef int SOCKET;
#define INVALID_SOCKET (-1)
#define IS_INVALID_SOCKET(socket) ((socket) < 0)
#endif
/*
* wrapper for cuserid()
*/
extern char *getuserid (char *string, int size);
/*
* wrapper for OS dependent operations
*/
extern int os_rename_file (const char *src_path, const char *dest_path);
/* os_send_kill() - send the KILL signal to ourselves */
#if defined(WINDOWS)
#define os_send_kill() os_send_signal(SIGABRT)
#else
#define os_send_kill() os_send_signal(SIGKILL)
#endif
typedef void (*SIGNAL_HANDLER_FUNCTION) (int sig_no);
extern SIGNAL_HANDLER_FUNCTION os_set_signal_handler (const int sig_no,
SIGNAL_HANDLER_FUNCTION
sig_handler);
extern void os_send_signal (const int sig_no);
#if defined(WINDOWS)
#define atoll(a) _atoi64((a))
#define llabs(a) _abs64((a))
#endif
#if defined(AIX) && !defined(NAME_MAX)
#define NAME_MAX pathconf("/",_PC_NAME_MAX)
#endif
#if defined(AIX) && !defined(DONT_HOOK_MALLOC)
void *aix_malloc (size_t size);
#define malloc(a) aix_malloc(a)
#endif
#if defined(AIX) && !defined(SOL_TCP)
#define SOL_TCP IPPROTO_TCP
#endif
#if defined(WINDOWS)
int setenv (const char *name, const char *value, int overwrite);
int cub_vsnprintf (char *buffer, size_t count, const char *format,
va_list argptr);
#endif
#if defined(WINDOWS) || defined(MAC_OS)
/* The following structure is used to generate uniformly distributed
* pseudo-random numbers reentrantly.
*/
struct drand48_data
{
unsigned short _rand48_seed[3];
};
#endif
#if defined(WINDOWS)
/* These functions are implemented in rand.c. And rand.c will be included
* on Windows build.
*/
extern long lrand48 (void);
extern void srand48 (long seed);
extern double drand48 (void);
extern int srand48_r (long int seedval, struct drand48_data *buffer);
extern int lrand48_r (struct drand48_data *buffer, long int *result);
extern int drand48_r (struct drand48_data *buffer, double *result);
extern int rand_r (unsigned int *seedp);
extern double round (double d);
typedef struct
{
CRITICAL_SECTION cs;
CRITICAL_SECTION *csp;
} pthread_mutex_t;
typedef HANDLE pthread_mutexattr_t;
#endif
#if defined(WINDOWS) || defined(MAC_OS)
#define PTHREAD_MUTEX_INITIALIZER {{ NULL, 0, 0, NULL, NULL, 0 }, NULL}
#endif
#if defined(WINDOWS)
typedef union
{
CONDITION_VARIABLE native_cond;
struct
{
bool initialized;
unsigned int waiting;
CRITICAL_SECTION lock_waiting;
enum
{
COND_SIGNAL = 0,
COND_BROADCAST = 1,
MAX_EVENTS = 2
} EVENTS;
HANDLE events[MAX_EVENTS];
HANDLE broadcast_block_event;
};
} pthread_cond_t;
typedef HANDLE pthread_condattr_t;
#define ETIMEDOUT WAIT_TIMEOUT
#define PTHREAD_COND_INITIALIZER { NULL }
struct timespec
{
int tv_sec;
int tv_nsec;
};
extern pthread_mutex_t css_Internal_mutex_for_mutex_initialize;
int pthread_mutex_init (pthread_mutex_t * mutex,
pthread_mutexattr_t * attr);
int pthread_mutex_destroy (pthread_mutex_t * mutex);
void port_win_mutex_init_and_lock (pthread_mutex_t * mutex);
int port_win_mutex_init_and_trylock (pthread_mutex_t * mutex);
__inline int pthread_mutex_lock (pthread_mutex_t * mutex)
{
if (mutex->csp == &mutex->cs)
{
EnterCriticalSection (mutex->csp);
}
else
{
port_win_mutex_init_and_lock (mutex);
}
return 0;
}
__inline int pthread_mutex_unlock (pthread_mutex_t * mutex)
{
if (mutex->csp->LockCount == -1)
{
/* this means unlock mutex which isn't locked */
assert (0);
return 0;
}
LeaveCriticalSection (mutex->csp);
return 0;
}
__inline int pthread_mutex_trylock (pthread_mutex_t * mutex)
{
if (mutex->csp == &mutex->cs)
{
if (TryEnterCriticalSection (mutex->csp))
{
if (mutex->csp->RecursionCount > 1)
{
LeaveCriticalSection (mutex->csp);
return EBUSY;
}
return 0;
}
return EBUSY;
}
else
{
return port_win_mutex_init_and_trylock (mutex);
}
return 0;
}
int pthread_mutexattr_init (pthread_mutexattr_t * attr);
int pthread_mutexattr_settype (pthread_mutexattr_t * attr, int type);
int pthread_mutexattr_destroy (pthread_mutexattr_t * attr);
int pthread_cond_init (pthread_cond_t * cond,
const pthread_condattr_t * attr);
int pthread_cond_wait (pthread_cond_t * cond, pthread_mutex_t * mutex);
int pthread_cond_timedwait (pthread_cond_t * cond, pthread_mutex_t * mutex,
struct timespec *ts);
int pthread_cond_destroy (pthread_cond_t * cond);
int pthread_cond_signal (pthread_cond_t * cond);
int pthread_cond_broadcast (pthread_cond_t * cond);
/* Data Types */
typedef HANDLE pthread_t;
typedef int pthread_attr_t;
typedef int pthread_key_t;
#define THREAD_RET_T unsigned int
#define THREAD_CALLING_CONVENTION __stdcall
int pthread_create (pthread_t * thread, const pthread_attr_t * attr,
THREAD_RET_T (THREAD_CALLING_CONVENTION *
start_routine) (void *), void *arg);
void pthread_exit (void *ptr);
pthread_t pthread_self (void);
int pthread_join (pthread_t thread, void **value_ptr);
#define pthread_attr_init(dummy1) 0
#define pthread_attr_destroy(dummy1) 0
int pthread_key_create (pthread_key_t * key, void (*destructor) (void *));
int pthread_key_delete (pthread_key_t key);
int pthread_setspecific (pthread_key_t key, const void *value);
void *pthread_getspecific (pthread_key_t key);
#else /* WINDOWS */
#define THREAD_RET_T void*
#define THREAD_CALLING_CONVENTION
#endif /* WINDOWS */
#if (defined(WINDOWS) || defined(X86))
#define COPYMEM(type,dst,src) do { \
*((type *) (dst)) = *((type *) (src)); \
}while(0)
#else /* WINDOWS || X86 */
#define COPYMEM(type,dst,src) do { \
memcpy((dst), (src), sizeof(type)); \
}while(0)
#endif /* WINDOWS || X86 */
/*
* Interfaces for atomic operations
*
* Developers should check HAVE_ATOMIC_BUILTINS before using atomic builtins
* as follows.
* #if defined(HAVE_ATOMIC_BUILTINS)
* ... write codes with atomic builtins ...
* #else
* ... leave legacy codes or write codes without atomic builtins ...
* #endif
*
* ATOMIC_TAS_xx (atomic test-and-set) writes new_val into *ptr, and returns
* the previous contents of *ptr. ATOMIC_CAS_xx (atomic compare-and-swap) returns
* true if the swap is done. It is only done if *ptr equals to cmp_val.
* ATOMIC_INC_xx (atomic increment) returns the result of *ptr + amount.
*
* Regarding Windows, there are two types of APIs to provide atomic operations.
* While InterlockedXXX functions handles 32bit values, InterlockedXXX64 handles
* 64bit values. That is why we define two types of macros.
*/
#if defined(WINDOWS)
#define HAVE_ATOMIC_BUILTINS
#define ATOMIC_TAS_32(ptr, new_val) \
InterlockedExchange(ptr, new_val)
#define ATOMIC_CAS_32(ptr, cmp_val, swap_val) \
(InterlockedCompareExchange(ptr, swap_val, cmp_val) == cmp_val)
#define ATOMIC_INC_32(ptr, amount) \
(InterlockedExchangeAdd(ptr, amount) + amount)
#if defined(_WIN64)
#define ATOMIC_TAS_64(ptr, new_val) \
InterlockedExchange64(ptr, new_val)
#define ATOMIC_CAS_64(ptr, cmp_val, swap_val) \
(InterlockedCompareExchange64(ptr, swap_val, cmp_val) == cmp_val)
#define ATOMIC_INC_64(ptr, amount) \
(InterlockedExchangeAdd64(ptr, amount) + amount)
#else /* _WIN64 */
/*
* These functions are used on Windows 32bit OS.
* InterlockedXXX64 functions are provided by Windows Vista (client)/Windows
* 2003 (server) or later versions. So, Windows XP 32bit does not have them.
* We provide the following functions to support atomic operations on all
* Windows versions.
*/
extern UINT64 win32_compare_exchange64 (UINT64 volatile *val_ptr,
UINT64 swap_val, UINT64 cmp_val);
extern UINT64 win32_exchange_add64 (UINT64 volatile *ptr, UINT64 amount);
extern UINT64 win32_exchange64 (UINT64 volatile *ptr, UINT64 new_val);
#define ATOMIC_TAS_64(ptr, new_val) \
win32_exchange64(ptr, new_val)
#define ATOMIC_CAS_64(ptr, cmp_val, swap_val) \
(win32_compare_exchange64(ptr, swap_val, cmp_val) == cmp_val)
#define ATOMIC_INC_64(ptr, amount) \
(win32_exchange_add64(ptr, amount) + amount)
#endif /* _WIN64 */
#else /* WINDOWS */
#if defined(HAVE_GCC_ATOMIC_BUILTINS)
#define HAVE_ATOMIC_BUILTINS
#define ATOMIC_TAS_32(ptr, new_val) \
__sync_lock_test_and_set(ptr, new_val)
#define ATOMIC_CAS_32(ptr, cmp_val, swap_val) \
__sync_bool_compare_and_swap(ptr, cmp_val, swap_val)
#define ATOMIC_INC_32(ptr, amount) \
__sync_add_and_fetch(ptr, amount)
#define ATOMIC_TAS_64(ptr, new_val) \
__sync_lock_test_and_set(ptr, new_val)
#define ATOMIC_CAS_64(ptr, cmp_val, swap_val) \
__sync_bool_compare_and_swap(ptr, cmp_val, swap_val)
#define ATOMIC_INC_64(ptr, amount) \
__sync_add_and_fetch(ptr, amount)
#else /* HAVE_GCC_ATOMIC_BUILTINS */
/*
* Currently we do not provide interfaces for atomic operations
* on other OS or compilers.
*/
#endif /* HAVE_GCC_ATOMIC_BUILTINS */
#endif /* WINDOWS */
#ifdef __cplusplus
}
#endif
#if defined(WINDOWS)
extern double strtod_win (const char *str, char **end_ptr);
#define string_to_double(str, end_ptr) strtod_win((str), (end_ptr));
#else
#define string_to_double(str, end_ptr) strtod((str), (end_ptr))
#endif
extern INT64 timeval_diff_in_msec (const struct timeval *end_time,
const struct timeval *start_time);
extern int timeval_add_msec (struct timeval *added_time,
const struct timeval *start_time, int msec);
extern int timeval_to_timespec (struct timespec *to,
const struct timeval *from);
extern FILE *port_open_memstream (char **ptr, size_t * sizeloc);
extern void port_close_memstream (FILE * fp, char **ptr, size_t * sizeloc);
extern char *trim (char *str);
extern int port_str_to_int (int *ret_p, const char *str_p, int base);
#endif /* _PORTING_H_ */