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