diff --git a/README.md b/README.md index 2fa9e58..31155df 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ gb single-file public domain libraries for C & C++ library | latest version | category | description ----------------|----------------|----------|------------- -**gb.h** | 0.26d | misc | Helper library (Standard library _improvement_) +**gb.h** | 0.27 | misc | Helper library (Standard library _improvement_) **gb_math.h** | 0.07c | math | Vector math library geared towards game development **gb_gl.h** | 0.05 | graphics | OpenGL Helper Library **gb_string.h** | 0.95a | strings | A better string library (this is built into gb.h too with custom allocator support!) diff --git a/gb.h b/gb.h index 6c6cc40..e45ceb0 100644 --- a/gb.h +++ b/gb.h @@ -1,4 +1,4 @@ -/* gb.h - v0.26d - Ginger Bill's C Helper Library - public domain +/* gb.h - v0.27 - Ginger Bill's C Helper Library - public domain - no warranty implied; use at your own risk This is a single header file with a bunch of useful stuff @@ -58,6 +58,7 @@ TODOS - More date & time functions VERSION HISTORY + 0.27 - OSX fixes and Linux gbAffinity 0.26d - Minor changes to how gbFile works 0.26c - gb_str_to_f* fix 0.26b - Minor fixes @@ -276,6 +277,8 @@ extern "C" { #include #include + + #if defined(GB_SYSTEM_WINDOWS) #if !defined(GB_NO_WINDOWS_H) #define NOMINMAX 1 @@ -296,6 +299,9 @@ extern "C" { #include #include #include + #ifndef _IOSC11_SOURCE + #define _IOSC11_SOURCE + #endif #include // NOTE(bill): malloc on linux #include #if !defined(GB_SYSTEM_OSX) @@ -309,18 +315,18 @@ extern "C" { #endif #if defined(GB_SYSTEM_OSX) -#include -#include -#include -#include -#include -#include -#include -#include + #include + #include + #include + #include + #include + #include + #include + #include #endif #if defined(GB_SYSTEM_UNIX) -#include + #include #endif @@ -412,21 +418,20 @@ typedef i32 Rune; // NOTE(bill): Unicode codepoint #define GB_RUNE_EOF cast(Rune)(-1) -// NOTE(bill): I think C99 and C++ `bool` is stupid for numerous reasons but there are too many -// to write in this small comment. typedef i8 b8; typedef i16 b16; typedef i32 b32; // NOTE(bill): Prefer this!!! // NOTE(bill): Get true and false #if !defined(__cplusplus) - #if (defined(_MSC_VER) && _MSC_VER <= 1800) || !defined(__STDC_VERSION__) + #if (defined(_MSC_VER) && _MSC_VER <= 1800) || (!defined(_MSC_VER) && !defined(__STDC_VERSION__)) #ifndef true #define true (0 == 0) #endif #ifndef false #define false (0 != 0) #endif + typedef b8 bool; #else #include #endif @@ -615,7 +620,7 @@ extern "C++" { // // NOTE: C++11 (and above) only! // -#if defined(__cplusplus) && ((defined(_MSC_VER) && _MSC_VER >= 1400) || (__cplusplus >= 201103L)) +#if !defined(GB_NO_DEFER) && defined(__cplusplus) && ((defined(_MSC_VER) && _MSC_VER >= 1400) || (__cplusplus >= 201103L)) extern "C++" { // NOTE(bill): Stupid fucking templates template struct gbRemoveReference { typedef T Type; }; @@ -1004,7 +1009,12 @@ typedef struct gbAffinity { } gbAffinity; #elif defined(GB_SYSTEM_LINUX) -#error TODO(bill): Implement gbAffinity for linux +typedef struct gbAffinity { + b32 is_accurate; + isize core_count; + isize thread_count; + isize threads_per_core; +} gbAffinity; #else #error TODO(bill): Unknown system #endif @@ -4113,7 +4123,7 @@ gb_inline i64 gb_atomic64_fetch_and(gbAtomic64 volatile *a, i64 operand) { gb_inline i64 gb_atomic64_fetch_or(gbAtomic64 volatile *a, i64 operand) { #if defined(GB_ARCH_64_BIT) - return _InterlockedAnd64(cast(i64 volatile *)a, operand); + return _InterlockedOr64(cast(i64 volatile *)a, operand); #elif GB_CPU_X86 i64 expected = a->value; for (;;) { @@ -4820,18 +4830,15 @@ GB_ALLOCATOR_PROC(gb_heap_allocator_proc) { #else // TODO(bill): *nix version that's decent case gbAllocation_Alloc: { - gbAllocationHeader *header; - isize total_size = size + alignment + gb_size_of(gbAllocationHeader); - ptr = malloc(total_size); - header = cast(gbAllocationHeader *)ptr; - ptr = gb_align_forward(header+1, alignment); - gb_allocation_header_fill(header, ptr, size); - if (flags & gbAllocatorFlag_ClearToZero) + posix_memalign(&ptr, alignment, size); + + if (flags & gbAllocatorFlag_ClearToZero) { gb_zero_size(ptr, size); + } } break; case gbAllocation_Free: { - free(gb_allocation_header(old_memory)); + free(old_memory); } break; case gbAllocation_Resize: { @@ -4928,7 +4935,7 @@ isize gb_affinity_thread_count_for_core(gbAffinity *a, isize core) { void gb_affinity_init(gbAffinity *a) { usize count, count_size = gb_size_of(count); - a->is_accurate = false; + a->is_accurate = false; a->thread_count = 1; a->core_count = 1; a->threads_per_core = 1; @@ -4978,7 +4985,83 @@ isize gb_affinity_thread_count_for_core(gbAffinity *a, isize core) { } #elif defined(GB_SYSTEM_LINUX) -#error TODO(bill): Implement gbAffinity for linux +// IMPORTANT TODO(bill): This gbAffinity stuff for linux needs be improved a lot! +// NOTE(zangent): I have to read /proc/cpuinfo to get the number of threads per core. +#include + +void gb_affinity_init(gbAffinity *a) { + b32 accurate = true; + isize threads = 0; + + a->thread_count = 1; + a->core_count = sysconf(_SC_NPROCESSORS_ONLN); + a->threads_per_core = 1; + + + if(a->core_count <= 0) { + a->core_count = 1; + accurate = false; + } + + // Parsing /proc/cpuinfo to get the number of threads per core. + // NOTE(zangent): This calls the CPU's threads "cores", although the wording + // is kind of weird. This should be right, though. + if (fopen("/proc/cpuinfo", "r") != NULL) { + for (;;) { + // The 'temporary char'. Everything goes into this char, + // so that we can check against EOF at the end of this loop. + char c; + +#define AF__CHECK(letter) ((c = getc(cpu_info)) == letter) + if (AF__CHECK('c') && AF__CHECK('p') && AF__CHECK('u') && AF__CHECK(' ') && + AF__CHECK('c') && AF__CHECK('o') && AF__CHECK('r') && AF__CHECK('e') && AF__CHECK('s')) { + // We're on a CPU info line. + while (!AF__CHECK(EOF)) { + if (c == '\n') { + break; + } else if (c < '0' || '9' > c) { + continue; + } + threads = threads * 10 + (c - '0'); + } + break; + } else { + while (!AF__CHECK('\n')) { + if (c==EOF) { + break; + } + } + } + if (c == EOF) { + break; + } +#undef AF__CHECK + } + } + + if (threads == 0) { + threads = 1; + accurate = false; + } + + a->threads_per_core = threads; + a->thread_count = a->threads_per_core * a->core_count; + a->is_accurate = accurate; + +} + +void gb_affinity_destroy(gbAffinity *a) { + gb_unused(a); +} + +b32 gb_affinity_set(gbAffinity *a, isize core, isize thread_index) { + return true; +} + +isize gb_affinity_thread_count_for_core(gbAffinity *a, isize core) { + GB_ASSERT(0 <= core && core < a->core_count); + return a->threads_per_core; +} #else #error TODO(bill): Unknown system #endif @@ -7759,7 +7842,18 @@ char *gb_path_get_full_name(gbAllocator a, char const *path) { return gb_alloc_str_len(a, buf, len+1); #else // TODO(bill): Make work on *nix, etc. - return gb_alloc_str_len(a, path, gb_strlen(path)); + char* p = realpath(path, 0); + GB_ASSERT(p && "file does not exist"); + + isize len = gb_strlen(p); + + // bill... gb_alloc_str_len refused to work for this... + char* ret = gb_alloc(a, sizeof(char) * len + 1); + gb_memmove(ret, p, len); + ret[len] = 0; + free(p); + + return ret; #endif }