2016-02-22 18:31:07 +03:00
|
|
|
#pragma once
|
|
|
|
|
2016-02-25 14:14:23 +03:00
|
|
|
#include "types.h"
|
|
|
|
|
2016-02-25 19:05:28 +03:00
|
|
|
#ifdef __APPLE__
|
2016-02-22 18:31:07 +03:00
|
|
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <assert.h>
|
|
|
|
#include <pthread.h>
|
|
|
|
#include <sys/time.h>
|
|
|
|
#include <dlfcn.h>
|
|
|
|
|
|
|
|
/* Init/shutdown */
|
|
|
|
|
2016-02-25 14:14:23 +03:00
|
|
|
void carp_platform_init() {
|
2016-02-22 18:31:07 +03:00
|
|
|
}
|
|
|
|
|
2016-02-25 14:14:23 +03:00
|
|
|
void carp_platform_shutdown() {
|
2016-02-22 18:31:07 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/* --- Threads --- */
|
|
|
|
|
|
|
|
struct carp_thread {
|
|
|
|
pthread_t thread;
|
|
|
|
};
|
|
|
|
|
|
|
|
typedef struct thread_arg_wrapper {
|
|
|
|
carp_thread_routine tr;
|
|
|
|
void* arg;
|
|
|
|
} thread_arg_wrapper;
|
|
|
|
|
2016-02-25 14:14:23 +03:00
|
|
|
void* thread_proc_wrapper(void* arg) {
|
2016-02-22 18:31:07 +03:00
|
|
|
thread_arg_wrapper* argw = (thread_arg_wrapper*)arg;
|
|
|
|
argw->tr(argw->arg);
|
|
|
|
free(argw);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2016-02-25 14:14:23 +03:00
|
|
|
carp_thread_t carp_thread_create(carp_thread_routine thread_routine, void* arg) {
|
2016-02-22 18:31:07 +03:00
|
|
|
carp_thread_t thread = malloc(sizeof(struct carp_thread));
|
|
|
|
assert(thread);
|
|
|
|
thread_arg_wrapper* argw = malloc(sizeof(thread_arg_wrapper));
|
|
|
|
assert(argw);
|
|
|
|
argw->arg = arg;
|
|
|
|
argw->tr = thread_routine;
|
|
|
|
pthread_create(&thread->thread, NULL, thread_proc_wrapper, argw);
|
|
|
|
return thread;
|
|
|
|
}
|
|
|
|
|
2016-02-25 14:14:23 +03:00
|
|
|
void carp_thread_destroy(carp_thread_t thread) {
|
2016-02-22 18:31:07 +03:00
|
|
|
free(thread);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* --- Timing --- */
|
|
|
|
|
2016-02-25 14:14:23 +03:00
|
|
|
int carp_millitime() {
|
2016-02-22 18:31:07 +03:00
|
|
|
struct timeval te;
|
|
|
|
gettimeofday(&te, NULL); // get current time
|
|
|
|
long long milliseconds = te.tv_sec * 1000LL + te.tv_usec / 1000; // calculate milliseconds
|
|
|
|
return milliseconds;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* --- Libraries --- */
|
|
|
|
|
|
|
|
struct carp_library {
|
|
|
|
void* handle;
|
|
|
|
};
|
|
|
|
|
2016-02-25 14:14:23 +03:00
|
|
|
carp_library_t carp_load_library(const char* name) {
|
2016-02-22 18:31:07 +03:00
|
|
|
void* handle = dlopen(name, RTLD_LAZY);
|
|
|
|
if (handle == NULL) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
return (carp_library_t)handle;
|
|
|
|
}
|
|
|
|
|
2016-02-25 14:14:23 +03:00
|
|
|
int carp_unload_library(carp_library_t lib) {
|
2016-02-22 18:31:07 +03:00
|
|
|
return dlclose((void*)lib);
|
|
|
|
}
|
|
|
|
|
2016-02-25 14:14:23 +03:00
|
|
|
void* carp_find_symbol(carp_library_t lib, const char * name) {
|
2016-02-22 18:31:07 +03:00
|
|
|
if (lib != NULL) {
|
|
|
|
return dlsym((void*)lib, name);
|
|
|
|
}
|
|
|
|
return dlsym(RTLD_DEFAULT, name);
|
|
|
|
}
|
|
|
|
|
2016-02-25 14:14:23 +03:00
|
|
|
char* carp_get_load_library_error() {
|
2016-02-22 18:31:07 +03:00
|
|
|
return dlerror();
|
|
|
|
}
|
|
|
|
|
2016-02-25 19:05:28 +03:00
|
|
|
#endif // __APPLE__
|
2016-02-22 18:31:07 +03:00
|
|
|
|
2016-02-25 20:28:50 +03:00
|
|
|
#ifdef WIN32
|
2016-02-22 18:31:07 +03:00
|
|
|
|
2016-02-22 18:38:07 +03:00
|
|
|
#define WIN32_LEAN_AND_MEAN
|
|
|
|
#include <Windows.h>
|
|
|
|
#include <assert.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
|
|
|
/* Support code for library symbol search */
|
|
|
|
|
|
|
|
typedef struct module_list {
|
|
|
|
HMODULE module;
|
|
|
|
struct module_list* next;
|
|
|
|
}*module_list_t;
|
|
|
|
|
2016-02-25 14:14:23 +03:00
|
|
|
LARGE_INTEGER carp_perf_freq;
|
|
|
|
HMODULE carp_main_module = INVALID_HANDLE_VALUE;
|
2016-02-25 18:38:16 +03:00
|
|
|
HMODULE carp_msvcrt_module = INVALID_HANDLE_VALUE;
|
2016-02-25 14:14:23 +03:00
|
|
|
module_list_t carp_loaded_modules = NULL;
|
2016-02-22 18:38:07 +03:00
|
|
|
|
2016-02-25 14:14:23 +03:00
|
|
|
module_list_t new_module_list_node() {
|
2016-02-22 18:38:07 +03:00
|
|
|
module_list_t lst = malloc(sizeof(struct module_list));
|
|
|
|
lst->module = INVALID_HANDLE_VALUE;
|
|
|
|
lst->next = NULL;
|
|
|
|
return lst;
|
|
|
|
}
|
|
|
|
|
2016-02-25 14:14:23 +03:00
|
|
|
void add_module_to_list(module_list_t lst, HMODULE module) {
|
2016-02-22 18:38:07 +03:00
|
|
|
while (lst->module != INVALID_HANDLE_VALUE) {
|
|
|
|
if (lst->next == NULL) {
|
|
|
|
lst->next = new_module_list_node();
|
|
|
|
}
|
|
|
|
lst = lst->next;
|
|
|
|
}
|
|
|
|
lst->module = module;
|
|
|
|
}
|
|
|
|
|
2016-02-25 14:14:23 +03:00
|
|
|
void remove_module_from_list(module_list_t lst, HMODULE module) {
|
2016-02-22 18:38:07 +03:00
|
|
|
while (lst->module != module) {
|
|
|
|
if (lst->next == NULL) {
|
|
|
|
return; // not found
|
|
|
|
}
|
|
|
|
lst = lst->next;
|
|
|
|
}
|
|
|
|
lst->module = INVALID_HANDLE_VALUE;
|
|
|
|
}
|
|
|
|
|
2016-02-25 14:14:23 +03:00
|
|
|
void free_all_modules_and_destroy_module_list(module_list_t lst) {
|
2016-02-22 18:38:07 +03:00
|
|
|
while (lst) {
|
|
|
|
if (lst->module != INVALID_HANDLE_VALUE) {
|
|
|
|
FreeLibrary(lst->module);
|
|
|
|
}
|
|
|
|
module_list_t tmp = lst;
|
|
|
|
lst = lst->next;
|
|
|
|
free(tmp);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Init/shutdown */
|
|
|
|
|
2016-02-25 14:14:23 +03:00
|
|
|
void carp_platform_init() {
|
|
|
|
QueryPerformanceFrequency(&carp_perf_freq);
|
|
|
|
carp_main_module = GetModuleHandle(NULL);
|
2016-02-25 18:38:16 +03:00
|
|
|
carp_msvcrt_module = LoadLibrary("msvcrt.dll");
|
2016-02-25 14:14:23 +03:00
|
|
|
carp_loaded_modules = new_module_list_node();
|
2016-02-25 18:38:16 +03:00
|
|
|
add_module_to_list(carp_loaded_modules, carp_msvcrt_module);
|
2016-02-22 18:38:07 +03:00
|
|
|
}
|
|
|
|
|
2016-02-25 14:14:23 +03:00
|
|
|
void carp_platform_shutdown() {
|
|
|
|
free_all_modules_and_destroy_module_list(carp_loaded_modules);
|
2016-02-25 18:38:16 +03:00
|
|
|
carp_main_module = INVALID_HANDLE_VALUE;
|
|
|
|
carp_msvcrt_module = INVALID_HANDLE_VALUE;
|
2016-02-25 14:14:23 +03:00
|
|
|
carp_loaded_modules = NULL;
|
2016-02-22 18:38:07 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/* --- Threads --- */
|
|
|
|
|
|
|
|
struct carp_thread {
|
|
|
|
HANDLE handle;
|
|
|
|
};
|
|
|
|
|
|
|
|
typedef struct thread_arg_wrapper {
|
|
|
|
carp_thread_routine tr;
|
|
|
|
void* arg;
|
|
|
|
} thread_arg_wrapper;
|
|
|
|
|
2016-02-25 14:14:23 +03:00
|
|
|
DWORD WINAPI thread_proc_wrapper(LPVOID p) {
|
2016-02-22 18:38:07 +03:00
|
|
|
thread_arg_wrapper* argw = (thread_arg_wrapper*)p;
|
|
|
|
argw->tr(argw->arg);
|
|
|
|
free(argw);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2016-02-25 14:14:23 +03:00
|
|
|
carp_thread_t carp_thread_create(carp_thread_routine thread_routine, void* arg) {
|
2016-02-22 18:38:07 +03:00
|
|
|
carp_thread_t thread = malloc(sizeof(struct carp_thread));
|
|
|
|
assert(thread);
|
|
|
|
thread_arg_wrapper* argw = malloc(sizeof(thread_arg_wrapper));
|
|
|
|
assert(argw);
|
|
|
|
argw->arg = arg;
|
|
|
|
argw->tr = thread_routine;
|
|
|
|
thread->handle = CreateThread(NULL, 0, thread_proc_wrapper, argw, 0, 0);
|
|
|
|
return thread;
|
|
|
|
}
|
|
|
|
|
2016-02-25 14:14:23 +03:00
|
|
|
void carp_thread_destroy(carp_thread_t thread) {
|
2016-02-22 18:38:07 +03:00
|
|
|
CloseHandle(thread->handle);
|
|
|
|
free(thread);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* --- Timing --- */
|
|
|
|
|
2016-02-25 14:14:23 +03:00
|
|
|
int carp_millitime() {
|
2016-02-22 18:38:07 +03:00
|
|
|
LARGE_INTEGER pt;
|
|
|
|
QueryPerformanceCounter(&pt);
|
2016-02-25 14:14:23 +03:00
|
|
|
return (int)(((double)pt.QuadPart) / ((double)carp_perf_freq.QuadPart) * 1000);
|
2016-02-22 18:38:07 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/* --- Libraries --- */
|
|
|
|
|
|
|
|
struct carp_library {
|
|
|
|
HMODULE module;
|
|
|
|
};
|
|
|
|
|
2016-02-25 14:14:23 +03:00
|
|
|
carp_library_t carp_load_library(const char* name) {
|
2016-02-22 18:38:07 +03:00
|
|
|
HMODULE module = LoadLibrary(name);
|
|
|
|
if (module == NULL) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
SetLastError(0);
|
2016-02-25 14:14:23 +03:00
|
|
|
add_module_to_list(carp_loaded_modules, module);
|
2016-02-22 18:38:07 +03:00
|
|
|
carp_library_t lib = malloc(sizeof(struct carp_library));
|
|
|
|
lib->module = module;
|
|
|
|
return lib;
|
|
|
|
}
|
|
|
|
|
2016-02-25 14:14:23 +03:00
|
|
|
int carp_unload_library(carp_library_t lib) {
|
|
|
|
remove_module_from_list(carp_loaded_modules, lib->module);
|
2016-02-22 18:38:07 +03:00
|
|
|
BOOL result = FreeLibrary(lib->module);
|
|
|
|
free(lib);
|
|
|
|
return (int)result;
|
|
|
|
}
|
|
|
|
|
2016-02-25 14:14:23 +03:00
|
|
|
void* carp_find_symbol(carp_library_t lib, const char * name) {
|
2016-02-22 18:38:07 +03:00
|
|
|
if (lib != NULL) {
|
|
|
|
assert(lib->module != INVALID_HANDLE_VALUE);
|
|
|
|
return GetProcAddress(lib->module, name);
|
|
|
|
}
|
2016-02-25 14:14:23 +03:00
|
|
|
void* addr = GetProcAddress(carp_main_module, name);
|
2016-02-22 18:38:07 +03:00
|
|
|
if (addr != NULL) {
|
|
|
|
return addr;
|
|
|
|
}
|
2016-02-25 14:14:23 +03:00
|
|
|
module_list_t lst = carp_loaded_modules;
|
2016-02-22 18:38:07 +03:00
|
|
|
while (lst) {
|
|
|
|
if (lst->module != INVALID_HANDLE_VALUE) {
|
|
|
|
void* addr = GetProcAddress(lst->module, name);
|
|
|
|
if (addr != NULL) {
|
|
|
|
return addr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
lst = lst->next;
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2016-02-25 14:14:23 +03:00
|
|
|
char error_buf[2048];
|
2016-02-22 18:38:07 +03:00
|
|
|
|
2016-02-25 14:14:23 +03:00
|
|
|
char* carp_get_load_library_error() {
|
2016-02-22 18:38:07 +03:00
|
|
|
DWORD error = GetLastError();
|
|
|
|
if (error == 0) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
assert(sizeof(TCHAR) == 1); // If wide chars are used, we have to convert to utf8
|
|
|
|
FormatMessage(
|
|
|
|
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
|
|
|
|
NULL,
|
|
|
|
error,
|
|
|
|
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
|
|
|
(LPSTR)&error_buf,
|
|
|
|
sizeof(error_buf) - 1,
|
|
|
|
NULL);
|
|
|
|
return error_buf;
|
|
|
|
}
|
|
|
|
|
2016-02-25 18:38:16 +03:00
|
|
|
void carp_sleep(int millis) {
|
|
|
|
Sleep(millis);
|
|
|
|
}
|
|
|
|
|
2016-02-22 18:38:07 +03:00
|
|
|
#endif
|