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