xref: /4.0.0/platform/include/platform/platform.h (revision 5f3357af)
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#include <platform/dynamic.h>
21
22#ifdef WIN32
23/* Include winsock2.h before windows.h to avoid winsock.h to be included */
24#define NOMINMAX
25#include <winsock2.h>
26#include <windows.h>
27#else
28#include <pthread.h>
29#include <sys/time.h>
30#endif
31
32#include <time.h>
33#include <stdio.h>
34#include <stdint.h>
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    typedef CONDITION_VARIABLE cb_cond_t;
45    typedef long ssize_t;
46    typedef unsigned __int64 hrtime_t;
47#define CB_DONT_NEED_BYTEORDER 1
48#define DIRECTORY_SEPARATOR_CHARACTER '\\'
49
50#else
51
52#define DIRECTORY_SEPARATOR_CHARACTER '/'
53
54    typedef pthread_t cb_thread_t;
55    typedef pthread_mutex_t cb_mutex_t;
56    typedef pthread_cond_t cb_cond_t;
57
58#ifndef __sun
59    typedef uint64_t hrtime_t;
60#endif
61
62#endif
63
64    /***********************************************************************
65     *                     Thread related functions                        *
66     **********************************************************************/
67
68    /**
69     * Thread function signature.
70     */
71    typedef void (*cb_thread_main_func)(void *argument);
72
73    /**
74     * Create a new thread (in a running state).
75     *
76     * @param id The thread identifier (returned)
77     * @param func The entry point for the newly created thread
78     * @param arg Arguments passed to the newly created thread
79     * @param detached Set to non-null if the thread should be
80     *                 created in a detached state (which you
81     *                 can't call cb_join_thread on).
82     */
83    PLATFORM_PUBLIC_API
84    int cb_create_thread(cb_thread_t *id,
85                         cb_thread_main_func func,
86                         void *arg,
87                         int detached);
88
89    /**
90     * Wait for a thread to complete
91     *
92     * @param id The thread identifier to wait for
93     */
94    PLATFORM_PUBLIC_API
95    int cb_join_thread(cb_thread_t id);
96
97    /**
98     * Get the id for the running thread
99     *
100     * @return the id for the running thread
101     */
102    PLATFORM_PUBLIC_API
103    cb_thread_t cb_thread_self(void);
104
105    /**
106     * Check if two cb_thread_t objects represent the same thread
107     *
108     * @param a the first thread
109     * @param b the second thread
110     * @return nonzero if the two objects represent the same object, 0 otherwise
111     */
112    PLATFORM_PUBLIC_API
113    int cb_thread_equal(const cb_thread_t a, const cb_thread_t b);
114
115    /***********************************************************************
116     *                      Mutex related functions                        *
117     **********************************************************************/
118    /**
119     * Initialize a mutex.
120     *
121     * We don't have <b>any</b> static initializers, so the mutex <b>must</b>
122     * be initialized by calling this function before being used.
123     *
124     * @param mutex the mutex object to initialize
125     */
126    PLATFORM_PUBLIC_API
127    void cb_mutex_initialize(cb_mutex_t *mutex);
128
129    /**
130     * Destroy (and release all allocated resources) a mutex.
131     *
132     * @param mutex the mutex object to destroy
133     */
134    PLATFORM_PUBLIC_API
135    void cb_mutex_destroy(cb_mutex_t *mutex);
136
137    /**
138     * Enter a locked section
139     *
140     * @param mutex the mutex protecting this section
141     */
142    PLATFORM_PUBLIC_API
143    void cb_mutex_enter(cb_mutex_t *mutex);
144
145    /**
146     * Try to enter a locked section
147     *
148     * @param mutex the mutex protecting this section
149     * @return 0 if the mutex was obtained, -1 otherwise
150     */
151    PLATFORM_PUBLIC_API
152    int cb_mutex_try_enter(cb_mutex_t *mutex);
153
154    /**
155     * Exit a locked section
156     *
157     * @param mutex the mutex protecting this section
158     */
159    PLATFORM_PUBLIC_API
160    void cb_mutex_exit(cb_mutex_t *mutex);
161
162    /***********************************************************************
163     *                 Condition variable related functions                *
164     **********************************************************************/
165    /**
166     * Initialize a condition variable
167     * @param cond the condition variable to initialize
168     */
169    PLATFORM_PUBLIC_API
170    void cb_cond_initialize(cb_cond_t *cond);
171
172    /**
173     * Destroy and release all allocated resources for a condition variable
174     * @param cond the condition variable to destroy
175     */
176    PLATFORM_PUBLIC_API
177    void cb_cond_destroy(cb_cond_t *cond);
178
179    /**
180     * Wait for a condition variable to be signaled.
181     *
182     * The mutex must be in a locked state, and this method will release
183     * the mutex and wait for the condition variable to be signaled in an
184     * atomic operation.
185     *
186     * The mutex is locked when the method returns.
187     *
188     * @param cond the condition variable to wait for
189     * @param mutex the locked mutex protecting the critical section
190     */
191    PLATFORM_PUBLIC_API
192    void cb_cond_wait(cb_cond_t *cond, cb_mutex_t *mutex);
193
194    /**
195     * Wait for a condition variable to be signaled, but give up after a
196     * given time.
197     *
198     * The mutex must be in a locked state, and this method will release
199     * the mutex and wait for the condition variable to be signaled in an
200     * atomic operation.
201     *
202     * The mutex is locked when the method returns.
203     *
204     * @param cond the condition variable to wait for
205     * @param mutex the locked mutex protecting the critical section
206     * @param ms the number of milliseconds to wait.
207     */
208    PLATFORM_PUBLIC_API
209    void cb_cond_timedwait(cb_cond_t *cond, cb_mutex_t *mutex, unsigned int ms);
210
211    /**
212     * Singal a single thread waiting for a condition variable
213     *
214     * @param cond the condition variable to signal
215     */
216    PLATFORM_PUBLIC_API
217    void cb_cond_signal(cb_cond_t *cond);
218
219    /**
220     * Singal all threads waiting for on condition variable
221     *
222     * @param cond the condition variable to signal
223     */
224    PLATFORM_PUBLIC_API
225    void cb_cond_broadcast(cb_cond_t *cond);
226
227
228#ifndef CB_DONT_NEED_GETHRTIME
229    /**
230     * Get a high resolution time
231     *
232     * @return number of nanoseconds since some arbitrary time in the past
233     */
234    PLATFORM_PUBLIC_API
235    hrtime_t gethrtime(void);
236#endif
237
238    /**
239     * Get the period of the high resolution time clock.
240     *
241     * @return Period of the clock in nanoseconds.
242     */
243    PLATFORM_PUBLIC_API
244    hrtime_t gethrtime_period(void);
245
246#ifndef CB_DONT_NEED_BYTEORDER
247    PLATFORM_PUBLIC_API
248    uint64_t ntohll(uint64_t);
249
250    PLATFORM_PUBLIC_API
251    uint64_t htonll(uint64_t);
252#endif
253
254    typedef void *cb_dlhandle_t;
255
256    PLATFORM_PUBLIC_API
257    cb_dlhandle_t cb_dlopen(const char *library, char **errmsg);
258
259    PLATFORM_PUBLIC_API
260    void *cb_dlsym(cb_dlhandle_t handle, const char *symbol, char **errmsg);
261
262    PLATFORM_PUBLIC_API
263    void cb_dlclose(cb_dlhandle_t handle);
264
265#ifdef WIN32
266    struct iovec {
267        size_t iov_len;
268        void *iov_base;
269    };
270
271    struct msghdr {
272        void *msg_name;         /* Socket name */
273        int msg_namelen;       /* Length of name */
274        struct iovec *msg_iov; /* Data blocks */
275        int msg_iovlen;        /* Number of blocks */
276    };
277
278    PLATFORM_PUBLIC_API
279    int sendmsg(SOCKET sock, const struct msghdr *msg, int flags);
280
281    /**
282     * Initialize the winsock library
283     */
284    PLATFORM_PUBLIC_API
285    void cb_initialize_sockets(void);
286
287    PLATFORM_PUBLIC_API
288    void usleep(unsigned int useconds);
289
290    PLATFORM_PUBLIC_API
291    int gettimeofday(struct timeval *tv, void *tz);
292#else
293
294#define cb_initialize_sockets()
295
296#endif
297
298    /*
299     * Set mode to binary
300     */
301    PLATFORM_PUBLIC_API
302    int platform_set_binary_mode(FILE *fp);
303
304    /*
305        return a monotonically increasing value with a seconds frequency.
306    */
307    PLATFORM_PUBLIC_API
308    uint64_t cb_get_monotonic_seconds(void);
309
310    /*
311        obtain a timeval structure containing the current time since EPOCH.
312    */
313    PLATFORM_PUBLIC_API
314    int cb_get_timeofday(struct timeval *tv);
315
316    /*
317        set an offset so that cb_get_timeofday returns an offsetted time.
318        This is intended for testing of time jumps.
319    */
320    PLATFORM_PUBLIC_API
321    void cb_set_timeofday_offset(uint64_t offset);
322
323    /**
324     * Some of our platforms complain on not using mkstemp. Instead of
325     * having the test in all programs we're just going to use this
326     * method instead.
327     *
328     * @param pattern The input pattern for the filename. It should end
329     *                with six X's that will be replaced with the unique
330     *                filename. The file will be created.
331     * @return pattern on success, NULL upon failure. Check errno for
332     *                 the reason.
333     */
334    PLATFORM_PUBLIC_API
335    char *cb_mktemp(char *pattern);
336
337    /**
338     * Convert time_t to a structure
339     *
340     * @param clock the input value
341     * @param result the output value
342     * @return 0 for success, -1 on failure
343     */
344    PLATFORM_PUBLIC_API
345    int cb_gmtime_r(const time_t *clock, struct tm *result);
346
347
348    /**
349     * Convert a time value with adjustments for the local time zone
350     *
351     * @param clock the input value
352     * @param result the output value
353     * @return 0 for success, -1 on failure
354     */
355    PLATFORM_PUBLIC_API
356    int cb_localtime_r(const time_t *clock, struct tm *result);
357
358#ifdef __cplusplus
359}
360#endif
361