1/* -*- Mode: C; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2/*
3 *     Copyright 2013 Couchbase, Inc
4 *
5 *   Licensed under the Apache License, Version 2.0 (the "License");
6 *   you may not use this file except in compliance with the License.
7 *   You may obtain a copy of the License at
8 *
9 *       http://www.apache.org/licenses/LICENSE-2.0
10 *
11 *   Unless required by applicable law or agreed to in writing, software
12 *   distributed under the License is distributed on an "AS IS" BASIS,
13 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 *   See the License for the specific language governing permissions and
15 *   limitations under the License.
16 */
17#pragma once
18
19#include <platform/cbassert.h>
20
21#ifdef WIN32
22/* Include winsock2.h before windows.h to avoid winsock.h to be included */
23#include <winsock2.h>
24#include <windows.h>
25#else
26#include <pthread.h>
27#include <stdint.h>
28#ifdef __sun
29#define CB_DONT_NEED_BYTEORDER 1
30#define CB_DONT_NEED_GETHRTIME 1
31#include <sys/time.h> /* for hrtime_t */
32#endif
33#endif
34
35#include <platform/visibility.h>
36
37#ifdef __cplusplus
38extern "C" {
39#endif
40
41#ifdef WIN32
42    typedef DWORD cb_thread_t;
43    typedef CRITICAL_SECTION cb_mutex_t;
44
45#ifdef _MSC_VER
46    typedef CONDITION_VARIABLE cb_cond_t;
47    typedef long ssize_t;
48#else
49    /* @TODO make sure that this buffer is big enough!!! */
50    typedef struct {
51        __int64 blob[64];
52    } cb_cond_t;
53#endif
54    typedef unsigned __int64 hrtime_t;
55
56    /* Unfortunately we don't have stdint.h on windows.. Let's just
57     * typedef them here for now.. we need to find a better solution for
58     * this!
59     */
60#if defined(_MSC_VER) && _MSC_VER < 1800
61    typedef __int8 int8_t;
62    typedef __int16 int16_t;
63    typedef __int32 int32_t;
64    typedef __int64 int64_t;
65    typedef unsigned __int8 uint8_t;
66    typedef unsigned __int16 uint16_t;
67    typedef unsigned __int32 uint32_t;
68    typedef unsigned __int64 uint64_t;
69#else
70#define CB_DONT_NEED_BYTEORDER 1
71#include <stdint.h>
72#endif
73
74#else
75    typedef pthread_t cb_thread_t;
76    typedef pthread_mutex_t cb_mutex_t;
77    typedef pthread_cond_t cb_cond_t;
78
79#ifndef __sun
80    typedef uint64_t hrtime_t;
81#endif
82
83#endif
84
85    /***********************************************************************
86     *                     Thread related functions                        *
87     **********************************************************************/
88
89    /**
90     * Thread function signature.
91     */
92    typedef void (*cb_thread_main_func)(void *argument);
93
94    /**
95     * Create a new thread (in a running state).
96     *
97     * @param id The thread identifier (returned)
98     * @param func The entry point for the newly created thread
99     * @param arg Arguments passed to the newly created thread
100     * @param detached Set to non-null if the thread should be
101     *                 created in a detached state (which you
102     *                 can't call cb_join_thread on).
103     */
104    PLATFORM_PUBLIC_API
105    int cb_create_thread(cb_thread_t *id,
106                         cb_thread_main_func func,
107                         void *arg,
108                         int detached);
109
110    /**
111     * Wait for a thread to complete
112     *
113     * @param id The thread identifier to wait for
114     */
115    PLATFORM_PUBLIC_API
116    int cb_join_thread(cb_thread_t id);
117
118    /**
119     * Get the id for the running thread
120     *
121     * @return the id for the running thread
122     */
123    PLATFORM_PUBLIC_API
124    cb_thread_t cb_thread_self(void);
125
126    /**
127     * Check if two cb_thread_t objects represent the same thread
128     *
129     * @param a the first thread
130     * @param b the second thread
131     * @return nonzero if the two objects represent the same object, 0 otherwise
132     */
133    PLATFORM_PUBLIC_API
134    int cb_thread_equal(const cb_thread_t a, const cb_thread_t b);
135
136    /***********************************************************************
137     *                      Mutex related functions                        *
138     **********************************************************************/
139    /**
140     * Initialize a mutex.
141     *
142     * We don't have <b>any</b> static initializers, so the mutex <b>must</b>
143     * be initialized by calling this function before being used.
144     *
145     * @param mutex the mutex object to initialize
146     */
147    PLATFORM_PUBLIC_API
148    void cb_mutex_initialize(cb_mutex_t *mutex);
149
150    /**
151     * Destroy (and release all allocated resources) a mutex.
152     *
153     * @param mutex the mutex object to destroy
154     */
155    PLATFORM_PUBLIC_API
156    void cb_mutex_destroy(cb_mutex_t *mutex);
157
158    /**
159     * Enter a locked section
160     *
161     * @param mutex the mutex protecting this section
162     */
163    PLATFORM_PUBLIC_API
164    void cb_mutex_enter(cb_mutex_t *mutex);
165
166    /**
167     * Try to enter a locked section
168     *
169     * @param mutex the mutex protecting this section
170     * @return 0 if the mutex was obtained, -1 otherwise
171     */
172    PLATFORM_PUBLIC_API
173    int cb_mutex_try_enter(cb_mutex_t *mutex);
174
175    /**
176     * Exit a locked section
177     *
178     * @param mutex the mutex protecting this section
179     */
180    PLATFORM_PUBLIC_API
181    void cb_mutex_exit(cb_mutex_t *mutex);
182
183    /***********************************************************************
184     *                 Condition variable related functions                *
185     **********************************************************************/
186    /**
187     * Initialize a condition variable
188     * @param cond the condition variable to initialize
189     */
190    PLATFORM_PUBLIC_API
191    void cb_cond_initialize(cb_cond_t *cond);
192
193    /**
194     * Destroy and release all allocated resources for a condition variable
195     * @param cond the condition variable to destroy
196     */
197    PLATFORM_PUBLIC_API
198    void cb_cond_destroy(cb_cond_t *cond);
199
200    /**
201     * Wait for a condition variable to be signaled.
202     *
203     * The mutex must be in a locked state, and this method will release
204     * the mutex and wait for the condition variable to be signaled in an
205     * atomic operation.
206     *
207     * The mutex is locked when the method returns.
208     *
209     * @param cond the condition variable to wait for
210     * @param mutex the locked mutex protecting the critical section
211     */
212    PLATFORM_PUBLIC_API
213    void cb_cond_wait(cb_cond_t *cond, cb_mutex_t *mutex);
214
215    /**
216     * Wait for a condition variable to be signaled, but give up after a
217     * given time.
218     *
219     * The mutex must be in a locked state, and this method will release
220     * the mutex and wait for the condition variable to be signaled in an
221     * atomic operation.
222     *
223     * The mutex is locked when the method returns.
224     *
225     * @param cond the condition variable to wait for
226     * @param mutex the locked mutex protecting the critical section
227     * @param ms the number of milliseconds to wait.
228     */
229    PLATFORM_PUBLIC_API
230    void cb_cond_timedwait(cb_cond_t *cond, cb_mutex_t *mutex, unsigned int ms);
231
232    /**
233     * Singal a single thread waiting for a condition variable
234     *
235     * @param cond the condition variable to signal
236     */
237    PLATFORM_PUBLIC_API
238    void cb_cond_signal(cb_cond_t *cond);
239
240    /**
241     * Singal all threads waiting for on condition variable
242     *
243     * @param cond the condition variable to signal
244     */
245    PLATFORM_PUBLIC_API
246    void cb_cond_broadcast(cb_cond_t *cond);
247
248
249#ifndef CB_DONT_NEED_GETHRTIME
250    /**
251     * Get a high resolution time
252     *
253     * @return number of nanoseconds since some arbitrary time in the past
254     */
255    PLATFORM_PUBLIC_API
256    hrtime_t gethrtime(void);
257#endif
258
259#ifndef CB_DONT_NEED_BYTEORDER
260    PLATFORM_PUBLIC_API
261    uint64_t ntohll(uint64_t);
262
263    PLATFORM_PUBLIC_API
264    uint64_t htonll(uint64_t);
265#endif
266
267    typedef void *cb_dlhandle_t;
268
269    PLATFORM_PUBLIC_API
270    cb_dlhandle_t cb_dlopen(const char *library, char **errmsg);
271
272    PLATFORM_PUBLIC_API
273    void *cb_dlsym(cb_dlhandle_t handle, const char *symbol, char **errmsg);
274
275    PLATFORM_PUBLIC_API
276    void cb_dlclose(cb_dlhandle_t handle);
277
278#ifdef WIN32
279    struct iovec {
280        size_t iov_len;
281        void *iov_base;
282    };
283
284    struct msghdr {
285        void *msg_name;         /* Socket name */
286        int msg_namelen;       /* Length of name */
287        struct iovec *msg_iov; /* Data blocks */
288        int msg_iovlen;        /* Number of blocks */
289    };
290
291    PLATFORM_PUBLIC_API
292    int sendmsg(SOCKET sock, const struct msghdr *msg, int flags);
293
294    /**
295     * Initialize the winsock library
296     */
297    PLATFORM_PUBLIC_API
298    void cb_initialize_sockets(void);
299
300    PLATFORM_PUBLIC_API
301    void usleep(unsigned int useconds);
302
303    PLATFORM_PUBLIC_API
304    int gettimeofday(struct timeval *tv, void *tz);
305#else
306
307#define cb_initialize_sockets()
308
309#endif
310
311#ifdef __cplusplus
312}
313#endif
314