xref: /4.0.0/platform/src/cb_win32.c (revision c0012dd1)
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#include "config.h"
18#include <assert.h>
19#include <stdio.h>
20#include <fcntl.h>
21#include <io.h>
22
23struct thread_execute {
24    cb_thread_main_func func;
25    void *argument;
26};
27
28static DWORD WINAPI platform_thread_wrap(LPVOID arg)
29{
30    struct thread_execute *ctx = arg;
31    assert(ctx);
32    ctx->func(ctx->argument);
33    free(ctx);
34    return 0;
35}
36
37
38__declspec(dllexport)
39int cb_create_thread(cb_thread_t *id,
40                     void (*func)(void *arg),
41                     void *arg,
42                     int detached)
43{
44    HANDLE handle;
45    struct thread_execute *ctx = malloc(sizeof(struct thread_execute));
46    if (ctx == NULL) {
47        return -1;
48    }
49
50    ctx->func = func;
51    ctx->argument = arg;
52
53    handle = CreateThread(NULL, 0, platform_thread_wrap, ctx, 0, id);
54    if (handle == NULL) {
55        free(ctx);
56        return -1;
57    } else {
58        if (detached) {
59            CloseHandle(handle);
60        }
61    }
62
63    return 0;
64}
65
66__declspec(dllexport)
67int cb_join_thread(cb_thread_t id)
68{
69    HANDLE handle = OpenThread(SYNCHRONIZE, FALSE, id);
70    if (handle == NULL) {
71        return -1;
72    }
73    WaitForSingleObject(handle, INFINITE);
74    CloseHandle(handle);
75    return 0;
76}
77
78__declspec(dllexport)
79cb_thread_t cb_thread_self(void)
80{
81    return GetCurrentThreadId();
82}
83
84__declspec(dllexport)
85int cb_thread_equal(const cb_thread_t a, const cb_thread_t b)
86{
87    return a == b;
88}
89
90__declspec(dllexport)
91void cb_mutex_initialize(cb_mutex_t *mutex)
92{
93    InitializeCriticalSection(mutex);
94}
95
96__declspec(dllexport)
97void cb_mutex_destroy(cb_mutex_t *mutex)
98{
99    DeleteCriticalSection(mutex);
100}
101
102__declspec(dllexport)
103void cb_mutex_enter(cb_mutex_t *mutex)
104{
105    EnterCriticalSection(mutex);
106}
107
108__declspec(dllexport)
109int cb_mutex_try_enter(cb_mutex_t *mutex)
110{
111    return TryEnterCriticalSection(mutex) ? 0 : -1;
112}
113
114__declspec(dllexport)
115void cb_mutex_exit(cb_mutex_t *mutex)
116{
117    LeaveCriticalSection(mutex);
118}
119
120__declspec(dllexport)
121void cb_cond_initialize(cb_cond_t *cond)
122{
123    InitializeConditionVariable(cond);
124}
125
126__declspec(dllexport)
127void cb_cond_destroy(cb_cond_t *cond)
128{
129    (void)cond;
130}
131
132__declspec(dllexport)
133void cb_cond_wait(cb_cond_t *cond, cb_mutex_t *mutex)
134{
135    SleepConditionVariableCS(cond, mutex, INFINITE);
136}
137
138__declspec(dllexport)
139void cb_cond_timedwait(cb_cond_t *cond, cb_mutex_t *mutex, unsigned int msec) {
140    SleepConditionVariableCS(cond, mutex, msec);
141}
142
143__declspec(dllexport)
144void cb_cond_signal(cb_cond_t *cond)
145{
146    WakeConditionVariable(cond);
147}
148
149__declspec(dllexport)
150void cb_cond_broadcast(cb_cond_t *cond)
151{
152    WakeAllConditionVariable(cond);
153}
154
155static const char *get_dll_name(const char *path, char *buffer)
156{
157    char *ptr = strstr(path, ".dll");
158    if (ptr != NULL) {
159        return path;
160    }
161
162    strcpy(buffer, path);
163
164    ptr = strstr(buffer, ".so");
165    if (ptr != NULL) {
166        sprintf(ptr, ".dll");
167        return buffer;
168    }
169
170    strcat(buffer, ".dll");
171    return buffer;
172}
173
174__declspec(dllexport)
175cb_dlhandle_t cb_dlopen(const char *library, char **errmsg)
176{
177    cb_dlhandle_t handle;
178    char *buffer;
179
180    if (library == NULL) {
181        if (errmsg != NULL) {
182            *errmsg = _strdup("Open self is not supported");
183        }
184        return NULL;
185    }
186
187    buffer = malloc(strlen(library) + 20);
188    if (buffer == NULL) {
189        if (*errmsg) {
190            *errmsg = _strdup("Failed to allocate memory");
191        }
192        return NULL;
193    }
194
195    handle = LoadLibrary(get_dll_name(library, buffer));
196    if (handle == NULL && errmsg != NULL) {
197        DWORD err = GetLastError();
198        LPVOID error_msg;
199
200        if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
201                          FORMAT_MESSAGE_FROM_SYSTEM |
202                          FORMAT_MESSAGE_IGNORE_INSERTS,
203                          NULL, err, 0, (LPTSTR)&error_msg, 0, NULL) != 0) {
204            *errmsg = _strdup(error_msg);
205            LocalFree(error_msg);
206        } else {
207            *errmsg = _strdup("Failed to get error message");
208        }
209    }
210
211    free(buffer);
212
213    return handle;
214}
215
216__declspec(dllexport)
217void *cb_dlsym(cb_dlhandle_t handle, const char *symbol, char **errmsg)
218{
219    void *ret = GetProcAddress(handle, symbol);
220    if (ret == NULL && errmsg) {
221        DWORD err = GetLastError();
222        LPVOID error_msg;
223
224        if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
225                          FORMAT_MESSAGE_FROM_SYSTEM |
226                          FORMAT_MESSAGE_IGNORE_INSERTS,
227                          NULL, err, 0, (LPTSTR)&error_msg, 0, NULL) != 0) {
228            *errmsg = _strdup(error_msg);
229            LocalFree(error_msg);
230        } else {
231            *errmsg = _strdup("Failed to get error message");
232        }
233    }
234
235    return ret;
236}
237
238__declspec(dllexport)
239void cb_dlclose(cb_dlhandle_t handle)
240{
241    FreeLibrary(handle);
242}
243
244__declspec(dllexport)
245void usleep(unsigned int useconds)
246{
247    unsigned int msec = useconds / 1000;
248    if (msec == 0) {
249        msec = 1;
250    }
251    Sleep(msec);
252}
253
254__declspec(dllexport)
255int gettimeofday(struct timeval *tv, void *tz)
256{
257    FILETIME ft;
258    uint64_t usecs;
259    LARGE_INTEGER li;
260    uint64_t secs;
261
262    assert(tz == NULL); /* I don't support that right now */
263    assert(tv != NULL); /* I don't support that right now */
264
265    GetSystemTimeAsFileTime(&ft);
266    li.LowPart = ft.dwLowDateTime;
267    li.HighPart = ft.dwHighDateTime;
268    usecs = li.QuadPart;
269
270    // FILETIME is 100 nanosecs from from 1. jan 1601
271    // convert it to usecs..
272    usecs /= 10;
273
274    secs = usecs / 1000000;
275    tv->tv_usec = usecs % 1000000;
276
277    // gettimeofday use 1st january 1970, subtract the secs
278    // between the dates
279    secs -= 11644473600;
280    tv->tv_sec = (unsigned long)secs;
281
282    return 0;
283}
284
285__declspec(dllexport)
286int platform_set_binary_mode(FILE *fp)
287{
288    return _setmode(_fileno(fp), _O_BINARY);
289}
290