summaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
Diffstat (limited to 'core')
-rw-r--r--core/abort.c93
-rw-r--r--core/alloc.c157
-rw-r--r--core/callbacks.c27
-rw-r--r--core/init.c37
-rw-r--r--core/logging.c114
-rw-r--r--core/mod.c90
-rw-r--r--core/thread.c218
7 files changed, 0 insertions, 736 deletions
diff --git a/core/abort.c b/core/abort.c
deleted file mode 100644
index 5ee42f6..0000000
--- a/core/abort.c
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Rune Game Engine
- * Copyright 2024 Danny Holman <dholman@gymli.org>
- *
- * This software is provided 'as-is', without any express or implied
- * warranty. In no event will the authors be held liable for any damages
- * arising from the use of this software.
- *
- * Permission is granted to anyone to use this software for any purpose,
- * including commercial applications, and to alter it and redistribute it
- * freely, subject to the following restrictions:
- *
- * 1. The origin of this software must not be misrepresented; you must not
- * claim that you wrote the original software. If you use this software
- * in a product, an acknowledgment in the product documentation would be
- * appreciated but is not required.
- * 2. Altered source versions must be plainly marked as such, and must not be
- * misrepresented as being the original software.
- * 3. This notice may not be removed or altered from any source distribution.
- */
-
-#include <rune/core/abort.h>
-#include <rune/core/alloc.h>
-#include <rune/core/init.h>
-#include <rune/core/logging.h>
-#include <rune/util/exits.h>
-#include <stdlib.h>
-
-#define MAX_TRACE_ITEMS 30
-
-#ifdef _WIN32
-
-#include <windows.h>
-#include <dbghelp.h>
-
-void _stack_trace(void) {
- void* buffer[MAX_TRACE_ITEMS];
- HANDLE process = GetCurrentProcess();
-
- SymInitialize(process, NULL, TRUE);
- int num_links = CaptureStackBackTrace(0, MAX_TRACE_ITEMS, buffer, NULL);
- SYMBOL_INFO *symbol = (SYMBOL_INFO*)rune_alloc(sizeof(SYMBOL_INFO) + 256 * sizeof(char));
- symbol->SizeOfStruct = sizeof(SYMBOL_INFO);
- symbol->MaxNameLen = 255;
-
- for (int i = 0; i < num_links; i++) {
- SymFromAddr(process, (DWORD64)(buffer[i]), 0, symbol);
- log_output(LOG_INFO, "#%d: %s", i, symbol->Name, symbol->Address);
- }
-
- rune_free(symbol);
- SymCleanup(process);
-}
-
-#else
-
-#include <execinfo.h>
-
-void _stack_trace(void) {
- void* buffer[MAX_TRACE_ITEMS];
- int num_links = backtrace(buffer, MAX_TRACE_ITEMS);
- char** symbuf = backtrace_symbols(buffer, num_links);
-
- for (int i = 0; i < num_links; i++)
- log_output(LOG_INFO, "#%d: %s", i, symbuf[i]);
-
- free(symbuf);
-}
-
-#endif
-
-NORET void rune_abort(void) {
- log_output(LOG_INFO, "Abort called, printing stack trace");
- _stack_trace();
- rune_exit();
- exit(REXIT_FAIL);
-}
-
-#ifdef MSVC
-
-NORET void __security_error_handler(void) {
- log_output(LOG_FATAL, "Stack smashing detected in engine code");
- rune_abort();
-}
-
-#else
-
-NORET void __stack_chk_fail(void) {
- log_output(LOG_FATAL, "Stack smashing detected in engine code");
- rune_abort();
-}
-
-#endif
diff --git a/core/alloc.c b/core/alloc.c
deleted file mode 100644
index 0ed705c..0000000
--- a/core/alloc.c
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- * Rune Game Engine
- * Copyright 2024 Danny Holman <dholman@gymli.org>
- *
- * This software is provided 'as-is', without any express or implied
- * warranty. In no event will the authors be held liable for any damages
- * arising from the use of this software.
- *
- * Permission is granted to anyone to use this software for any purpose,
- * including commercial applications, and to alter it and redistribute it
- * freely, subject to the following restrictions:
- *
- * 1. The origin of this software must not be misrepresented; you must not
- * claim that you wrote the original software. If you use this software
- * in a product, an acknowledgment in the product documentation would be
- * appreciated but is not required.
- * 2. Altered source versions must be plainly marked as such, and must not be
- * misrepresented as being the original software.
- * 3. This notice may not be removed or altered from any source distribution.
- */
-
-#include <rune/core/alloc.h>
-#include <rune/core/logging.h>
-#include <stdlib.h>
-#include <string.h>
-
-// TODO: implement block coalescing so we can reuse freed blocks
-
-#define DEADBLOCK ((void*)0xDEADBEEF)
-
-static mem_block_t first_block;
-
-static mem_block_t* _find_free_block(size_t sz) {
- list_head_t *temp = &first_block.list;
- mem_block_t *block;
- while (temp != NULL) {
- block = (mem_block_t*)((void*)temp - offsetof(mem_block_t, list));
- if (block->sz == sz && block->free == 1)
- return block;
- temp = temp->next;
- }
- return NULL;
-}
-
-static mem_block_t* _find_block(void *ptr) {
- list_head_t *temp = &first_block.list;
- mem_block_t *block;
- while (temp != NULL) {
- block = (mem_block_t*)((void*)temp - offsetof(mem_block_t, list));
- if (block->ptr == ptr)
- return block;
- temp = temp->next;
- }
- return NULL;
-}
-
-static mem_block_t* _alloc_block(size_t sz) {
- if (first_block.ptr == NULL) {
- first_block.ptr == DEADBLOCK;
- first_block.sz = 0;
- }
-
- mem_block_t *ret = _find_free_block(sz);
- if (ret != NULL) {
- ret->free = 0;
- return ret->ptr;
- }
-
- ret = malloc(sizeof(mem_block_t));
- if (ret == NULL) {
- log_output(LOG_ERROR, "Cannot allocate block of size %d", sz);
- return NULL;
- }
-
- ret->ptr = malloc(sz);
- ret->sz = sz;
- ret->free = 0;
- list_add(&ret->list, &first_block.list);
- log_output(LOG_DEBUG, "Alloc'd block of size %d", sz);
- return ret;
-}
-
-static void _free_block(mem_block_t *block, int hard) {
- if (hard == 1) {
- list_del(&block->list);
- log_output(LOG_DEBUG, "Freed block of size %d", block->sz);
- free(block);
- return;
- }
- block->free = 1;
-}
-
-void* rune_alloc(size_t sz) {
- if (sz == 0)
- return NULL;
-
- mem_block_t *block = _find_free_block(sz);
- if (block != NULL) {
- block->free = 0;
- return block->ptr;
- }
-
- block = _alloc_block(sz);
- return block->ptr;
-}
-
-void* rune_calloc(size_t nmemb, size_t sz) {
- if (sz == 0)
- return NULL;
-
- mem_block_t *block = _find_free_block(sz);
- if (block != NULL) {
- block->free = 0;
- return block->ptr;
- }
-
- block = _alloc_block(sz);
- memset(block->ptr, 0, sz);
- return block->ptr;
-}
-
-void* rune_realloc(void *ptr, size_t sz) {
- if (ptr == NULL || sz == 0)
- return rune_alloc(sz);
-
- mem_block_t *old = _find_block(ptr);
- mem_block_t *new = _alloc_block(sz);
- memcpy(new->ptr, old->ptr, old->sz);
- old->free = 1;
- return new->ptr;
-}
-
-void rune_free(void *ptr) {
- if (ptr == NULL)
- return;
-
- mem_block_t *block = _find_block(ptr);
- if (block->free == 1)
- return;
- block->free = 1;
-}
-
-void rune_free_all(void) {
- list_head_t *temp = &first_block.list;
- mem_block_t *block;
- while (temp != NULL) {
- block = (mem_block_t*)((void*)temp - offsetof(mem_block_t, list));
- if (block->ptr == DEADBLOCK) {
- temp = temp->next;
- continue;
- }
-
- temp = temp->next;
- if (block->ptr != NULL)
- _free_block(block, 1);
- }
-}
diff --git a/core/callbacks.c b/core/callbacks.c
deleted file mode 100644
index ea7f50e..0000000
--- a/core/callbacks.c
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Rune Game Engine
- * Copyright 2024 Danny Holman <dholman@gymli.org>
- *
- * This software is provided 'as-is', without any express or implied
- * warranty. In no event will the authors be held liable for any damages
- * arising from the use of this software.
- *
- * Permission is granted to anyone to use this software for any purpose,
- * including commercial applications, and to alter it and redistribute it
- * freely, subject to the following restrictions:
- *
- * 1. The origin of this software must not be misrepresented; you must not
- * claim that you wrote the original software. If you use this software
- * in a product, an acknowledgment in the product documentation would be
- * appreciated but is not required.
- * 2. Altered source versions must be plainly marked as such, and must not be
- * misrepresented as being the original software.
- * 3. This notice may not be removed or altered from any source distribution.
- */
-
-#include <rune/core/callbacks.h>
-#include <rune/core/logging.h>
-
-void error_callback(int error, const char *desc) {
- log_output(LOG_ERROR, "%d: %s\n", error, desc);
-}
diff --git a/core/init.c b/core/init.c
deleted file mode 100644
index 5df4d04..0000000
--- a/core/init.c
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Rune Game Engine
- * Copyright 2024 Danny Holman <dholman@gymli.org>
- *
- * This software is provided 'as-is', without any express or implied
- * warranty. In no event will the authors be held liable for any damages
- * arising from the use of this software.
- *
- * Permission is granted to anyone to use this software for any purpose,
- * including commercial applications, and to alter it and redistribute it
- * freely, subject to the following restrictions:
- *
- * 1. The origin of this software must not be misrepresented; you must not
- * claim that you wrote the original software. If you use this software
- * in a product, an acknowledgment in the product documentation would be
- * appreciated but is not required.
- * 2. Altered source versions must be plainly marked as such, and must not be
- * misrepresented as being the original software.
- * 3. This notice may not be removed or altered from any source distribution.
- */
-
-#include <rune/core/init.h>
-#include <rune/core/abort.h>
-#include <rune/core/logging.h>
-#include <rune/core/thread.h>
-
-int rune_init(int argc, char* argv[]) {
- log_output(LOG_INFO, "Started Rune Engine version %s", RUNE_VER);
- _parse_args(argc, argv);
- rune_init_thread_api();
- return 0;
-}
-
-void rune_exit(void) {
- log_output(LOG_INFO, "Engine shutdown requested");
- rune_free_all();
-}
diff --git a/core/logging.c b/core/logging.c
deleted file mode 100644
index b7f77bd..0000000
--- a/core/logging.c
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * Rune Game Engine
- * Copyright 2024 Danny Holman <dholman@gymli.org>
- *
- * This software is provided 'as-is', without any express or implied
- * warranty. In no event will the authors be held liable for any damages
- * arising from the use of this software.
- *
- * Permission is granted to anyone to use this software for any purpose,
- * including commercial applications, and to alter it and redistribute it
- * freely, subject to the following restrictions:
- *
- * 1. The origin of this software must not be misrepresented; you must not
- * claim that you wrote the original software. If you use this software
- * in a product, an acknowledgment in the product documentation would be
- * appreciated but is not required.
- * 2. Altered source versions must be plainly marked as such, and must not be
- * misrepresented as being the original software.
- * 3. This notice may not be removed or altered from any source distribution.
- */
-
-#include <rune/core/logging.h>
-#include <rune/core/config.h>
-#include <stdio.h>
-#include <string.h>
-#include <stdarg.h>
-
-#define COLOR_NONE ""
-#define COLOR_DEFAULT "\033[0m"
-#define COLOR_RED "\033[31m"
-#define COLOR_GREEN "\033[32m"
-#define COLOR_YELLOW "\033[33m"
-#define COLOR_BLUE "\033[34m"
-
-#define LSTR_FATAL "[FATAL]"
-#define LSTR_ERROR "[ERROR]"
-#define LSTR_WARN "[WARNING]"
-#define LSTR_INFO "[INFO]"
-#define LSTR_DEBUG "[DEBUG]"
-
-static int debug_enabled = 0;
-static int color_enabled = 0;
-
-void log_output(int level, const char *fmt, ...) {
- char out[4096];
- memset(out, 0, sizeof(out));
-
- debug_enabled = rune_get_log_debug();
- color_enabled = rune_get_log_color();
-
- va_list arg_ptr;
- va_start(arg_ptr, fmt);
- vsnprintf(out, 4096, fmt, arg_ptr);
- va_end(arg_ptr);
-
- char *lvl_str;
- char *color = COLOR_NONE;
- switch (level) {
- case LOG_FATAL:
- if (color_enabled == 1)
- color = COLOR_RED;
- lvl_str = LSTR_FATAL;
- break;
- case LOG_ERROR:
- if (color_enabled == 1)
- color = COLOR_RED;
- lvl_str = LSTR_ERROR;
- break;
- case LOG_WARN:
- if (color_enabled == 1)
- color = COLOR_YELLOW;
- lvl_str = LSTR_WARN;
- break;
- case LOG_INFO:
- lvl_str = LSTR_INFO;
- break;
- case LOG_DEBUG:
- if (color_enabled == 1)
- color = COLOR_GREEN;
- if (debug_enabled == 0)
- return;
- lvl_str = LSTR_DEBUG;
- break;
- }
-
- if (color_enabled == 0) {
- printf("%s %s\n", lvl_str, out);
- } else {
- printf("%s%s %s\n", color, lvl_str, out);
- printf(COLOR_DEFAULT);
- }
-}
-
-//#ifdef _WIN32
-//
-//#include <windows.h>
-//
-//void enable_log_color(void) {
-// HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
-// SetConsoleMode(handle, ENABLE_VIRTUAL_TERMINAL_PROCESSING);
-// color_enabled = 1;
-//}
-//
-//#else
-//
-//void enable_log_color(void) {
-// color_enabled = 1;
-//}
-//
-//#endif
-//
-//void disable_log_color(void) {
-// color_enabled = 0;
-//}
diff --git a/core/mod.c b/core/mod.c
deleted file mode 100644
index 3d9e710..0000000
--- a/core/mod.c
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Rune Game Engine
- * Copyright 2024 Danny Holman <dholman@gymli.org>
- *
- * This software is provided 'as-is', without any express or implied
- * warranty. In no event will the authors be held liable for any damages
- * arising from the use of this software.
- *
- * Permission is granted to anyone to use this software for any purpose,
- * including commercial applications, and to alter it and redistribute it
- * freely, subject to the following restrictions:
- *
- * 1. The origin of this software must not be misrepresented; you must not
- * claim that you wrote the original software. If you use this software
- * in a product, an acknowledgment in the product documentation would be
- * appreciated but is not required.
- * 2. Altered source versions must be plainly marked as such, and must not be
- * misrepresented as being the original software.
- * 3. This notice may not be removed or altered from any source distribution.
- */
-
-#include <rune/core/mod.h>
-#include <rune/core/logging.h>
-#include <rune/core/alloc.h>
-#include <stdio.h>
-#include <string.h>
-#include <dirent.h>
-#include <dlfcn.h>
-
-list_head_t *mods = NULL;
-
-void _load_mod(const char *filename) {
- char mod_path[4096];
- sprintf(mod_path, "mods/%s", filename);
- void *handle = dlopen(mod_path, RTLD_LAZY);
- if (handle == NULL)
- log_output(LOG_ERROR, "Error loading mod %s: %s", filename, dlerror());
-}
-
-void rune_load_mods(void) {
- DIR *dir = opendir("mods");
- if (dir == NULL) {
- log_output(LOG_INFO, "No mods folder found, skipping mod loading");
- return;
- }
-
- struct dirent *mods_de;
- while ((mods_de = readdir(dir)) != NULL) {
- if (strstr(mods_de->d_name, ".so"))
- _load_mod(mods_de->d_name);
- }
-}
-
-void rune_init_mods(void) {
- list_head_t *temp = mods;
- struct mod *mod;
- while (temp != NULL) {
- mod = (struct mod*)((void*)temp - offsetof(struct mod, list));
- (*mod->init_func)();
- temp = temp->next;
- }
-}
-
-void rune_close_mods(void) {
- if (mods == NULL)
- return;
-
- list_head_t *temp = mods;
- struct mod *mod;
- while (temp != NULL) {
- mod = (struct mod*)((void*)temp - offsetof(struct mod, list));
- (*mod->exit_func)();
- temp = temp->next;
- rune_free(mod);
- }
-}
-
-void rune_register_mod(const char *name, mod_func init_func, mod_func exit_func, mod_func update_func) {
- struct mod *new = rune_alloc(sizeof(struct mod));
- new->name = name;
- new->init_func = init_func;
- new->exit_func = exit_func;
- new->update_func = update_func;
- new->list.next = NULL;
- new->list.prev = NULL;
- if (mods == NULL)
- mods = &new->list;
- else
- list_add(&new->list, mods);
-}
diff --git a/core/thread.c b/core/thread.c
deleted file mode 100644
index 3c5db8c..0000000
--- a/core/thread.c
+++ /dev/null
@@ -1,218 +0,0 @@
-/*
- * Rune Game Engine
- * Copyright 2024 Danny Holman <dholman@gymli.org>
- *
- * This software is provided 'as-is', without any express or implied
- * warranty. In no event will the authors be held liable for any damages
- * arising from the use of this software.
- *
- * Permission is granted to anyone to use this software for any purpose,
- * including commercial applications, and to alter it and redistribute it
- * freely, subject to the following restrictions:
- *
- * 1. The origin of this software must not be misrepresented; you must not
- * claim that you wrote the original software. If you use this software
- * in a product, an acknowledgment in the product documentation would be
- * appreciated but is not required.
- * 2. Altered source versions must be plainly marked as such, and must not be
- * misrepresented as being the original software.
- * 3. This notice may not be removed or altered from any source distribution.
- */
-
-#include <rune/core/thread.h>
-#include <rune/core/logging.h>
-#include <rune/core/alloc.h>
-#include <pthread.h>
-#include <string.h>
-#include <stdatomic.h>
-
-static list_head_t *threads = NULL;
-static list_head_t *mutexes = NULL;
-static int next_tid = 0;
-static int next_mid = 0;
-
-struct start_args {
- struct thread *thread;
- void* (*thread_fn)(void*);
- void *thread_args;
-};
-
-static struct thread* _find_thread_by_handle(void *handle) {
- if (threads == NULL)
- return NULL;
-
- list_head_t *temp = threads;
- struct thread *ret;
- while (temp != NULL) {
- ret = (struct thread*)((void*)temp - offsetof(struct thread, list));
- if (pthread_equal(*(pthread_t*)ret->thread_handle, *(pthread_t*)handle) == 1)
- return ret;
- temp = temp->next;
- }
- return NULL;
-}
-
-static struct thread* _find_thread_by_id(int ID) {
- if (threads == NULL)
- return NULL;
-
- list_head_t *temp = threads;
- struct thread *ret;
- while (temp != NULL) {
- ret = (struct thread*)((void*)temp - offsetof(struct thread, list));
- if (ret->ID == ID)
- return ret;
- temp = temp->next;
- }
- return NULL;
-}
-
-static struct mutex* _find_mutex_by_id(int ID) {
- if (mutexes == NULL)
- return NULL;
-
- list_head_t *temp = mutexes;
- struct mutex *ret;
- while (temp != NULL) {
- ret = (struct mutex*)((void*)temp - offsetof(struct mutex, list));
- if (ret->ID == ID)
- return ret;
- temp = temp->next;
- }
- return NULL;
-}
-
-
-static void _cleanup_pthread(void *arg) {
- struct thread *thread = (struct thread*)arg;
- if (&thread->list != threads)
- list_del(&thread->list);
- rune_free(thread->thread_handle);
- rune_free(thread);
-}
-
-static void* _startup_pthread(void *arg) {
- struct start_args *start_args = (struct start_args*)arg;
-
- void* (*thread_fn)(void *data) = start_args->thread_fn;
- pthread_cleanup_push(_cleanup_pthread, start_args->thread);
- if (thread_fn != NULL)
- (*thread_fn)(start_args->thread_args);
- pthread_cleanup_pop(1);
- return NULL;
-}
-
-void rune_init_thread_api(void) {
- struct thread *start_thread = rune_alloc(sizeof(struct thread));
- start_thread->ID = next_tid++;
- start_thread->detached = 0;
- start_thread->thread_handle = rune_alloc(sizeof(pthread_t));
- *(pthread_t*)start_thread->thread_handle = pthread_self();
- pthread_cleanup_push(_cleanup_pthread, threads);
- pthread_cleanup_pop(0);
-}
-
-int rune_thread_init(void* (*thread_fn)(void *data), void *data, int detached) {
- struct thread *thread = rune_alloc(sizeof(struct thread));
- thread->ID = next_tid++;
- thread->detached = detached;
- thread->thread_handle = rune_alloc(sizeof(pthread_t));
- if (threads == NULL)
- threads = &thread->list;
- else
- list_add(&thread->list, threads);
-
- struct start_args *args = rune_alloc(sizeof(struct start_args));
- args->thread = thread;
- args->thread_fn = thread_fn;
- args->thread_args = data;
- int retval = pthread_create(thread->thread_handle, NULL, _startup_pthread, args);
- rune_free(args);
- if (retval != 0) {
- log_output(LOG_ERROR, "Thread creation failed: %s", strerror(retval));
- return -1;
- }
- log_output(LOG_DEBUG, "Initialized new thread with ID=%d", thread->ID);
- if (detached == 1) {
- log_output(LOG_DEBUG, "Thread %d has been detached, join no longer possible");
- pthread_detach(*(pthread_t*)thread->thread_handle);
- }
- return thread->ID;
-}
-
-int rune_thread_cancel(int ID) {
- log_output(LOG_DEBUG, "Received cancel request for thread %d", ID);
- struct thread *thread = _find_thread_by_id(ID);
- if (thread == NULL) {
- log_output(LOG_ERROR, "Thread %d does not exist", ID);
- return -1;
- }
- pthread_cancel(*((pthread_t*)thread->thread_handle));
- return 0;
-}
-
-int rune_thread_join(int ID, void **retval) {
- struct thread *thread = _find_thread_by_id(ID);
- if (thread == NULL)
- return 0;
-
- if (thread->detached == 1) {
- log_output(LOG_ERROR, "Cannot join thread %d, detached", thread->ID);
- return -1;
- }
- pthread_join(*((pthread_t*)thread->thread_handle), retval);
- return 0;
-}
-
-int rune_thread_self(void) {
- pthread_t cur = pthread_self();
- struct thread *ret = _find_thread_by_handle((void*)&cur);
- if (ret != NULL)
- return ret->ID;
- return -1;
-}
-
-void rune_thread_exit(void *retval) {
- pthread_t cur = pthread_self();
- struct thread *self = _find_thread_by_handle((void*)&cur);
- log_output(LOG_DEBUG, "Thread %d called thread_exit", self->ID);
- pthread_exit(retval);
-}
-
-int rune_mutex_init(void) {
- struct mutex *mutex = rune_alloc(sizeof(struct mutex));
- mutex->ID = next_mid++;
- mutex->mutex_handle = rune_alloc(sizeof(pthread_mutex_t));
- pthread_mutex_init((pthread_mutex_t*)mutex->mutex_handle, NULL);
- if (mutexes == NULL)
- mutexes = &mutex->list;
- else
- list_add(&mutex->list, mutexes);
- return mutex->ID;
-}
-
-int rune_mutex_destroy(int ID) {
- struct mutex *mutex = _find_mutex_by_id(ID);
- rune_free(mutex->mutex_handle);
- if (&mutex->list != mutexes)
- list_del(&mutex->list);
- rune_free(mutex);
-}
-
-int rune_mutex_lock(int ID) {
- struct mutex *mutex = _find_mutex_by_id(ID);
- int retval = pthread_mutex_lock((pthread_mutex_t*)mutex->mutex_handle);
- if (retval != 0) {
- char *str = strerror(retval);
- log_output(LOG_ERROR, "Cannot lock mutex %d: %s", mutex->ID, str);
- }
-}
-
-int rune_mutex_unlock(int ID) {
- struct mutex *mutex = _find_mutex_by_id(ID);
- int retval = pthread_mutex_unlock((pthread_mutex_t*)mutex->mutex_handle);
- if (retval != 0) {
- char *str = strerror(retval);
- log_output(LOG_ERROR, "Cannot unlock mutex %d: %s", mutex->ID, str);
- }
-}