summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md23
-rw-r--r--src/deque.c47
-rw-r--r--src/deque.h4
-rw-r--r--src/dft.c54
-rw-r--r--src/ez_arena.c10
-rw-r--r--src/log.c4
-rw-r--r--src/slidingwindow.c5
-rw-r--r--src/slidingwindow.h1
-rw-r--r--src/smrt_arena.c32
-rw-r--r--src/smrt_arena.h2
-rw-r--r--src/string.c17
-rw-r--r--src/string.h2
-rw-r--r--src/threadpool.c50
-rw-r--r--src/threadpool.h12
-rw-r--r--src/vec2.c2
-rw-r--r--src/vec2sw.c7
-rw-r--r--src/vec2sw.h1
-rw-r--r--src/wav.c54
-rw-r--r--src/wav.h2
19 files changed, 239 insertions, 90 deletions
diff --git a/README.md b/README.md
index f41b314..d5130a3 100644
--- a/README.md
+++ b/README.md
@@ -1,15 +1,24 @@
# SteEZ (Steven-NA EZ library)
## Todo
-- [ ] Add trace log calls, disabled with NLOG_TRACE
+- [x] Add allocation checks and trace log calls (disabled with NLOG_TRACE)
+ - [x] deque
+ - [x] ez_arena
+ - [x] smrt_arena
+ - [x] slidingwindow
+ - [x] string
+ - [x] threadpool
+ - [x] vec2sw
+ - [x] wav
- [ ] Add strng_view
- want start, end, max_len, char*
-- [ ] Make status return values consistent. i64, 0 success, -1 fail, >0 info if necessary
- - [ ] Deque enqueue (both)
- - [ ] smrt_arena_pop_to_mark
- - [ ] strng_set
- - [ ] write_wav_file
+- [x] Make status return values consistent. i64, 0 success, -1 fail, >0 info if necessary
+ - [x] Deque enqueue (both)
+ - [x] smrt_arena_pop_to_mark
+ - [x] strng_set
+ - [x] write_wav_file
- [ ] Finish thread_pool
- [ ] make some tests for it
- [x] base implementation done
- - Note: there is a crash that occurs regularly, but not when running in debug, (a junk data pointer being passed arond that is zeroed out in debug?)
+ - [x] Note: there is a crash that occurs regularly, but not when running in debug, (a junk data pointer being passed arond that is zeroed out in debug?)
+ - Race condition fixed in commit d3e8a23
diff --git a/src/deque.c b/src/deque.c
index 9b63b55..1046575 100644
--- a/src/deque.c
+++ b/src/deque.c
@@ -1,32 +1,40 @@
#include "deque.h"
#include "smrt_arena.h"
+#include "log.h"
#include <bits/pthreadtypes.h>
#include <pthread.h>
#include <semaphore.h>
-#include <stdlib.h>
#include <string.h>
ez_deque_t *ez_deque_create(smrt_arena_t *arena, u64 elem_size, u64 size) {
u64 total_size = EZ_DEQUE_BASE_POS + (elem_size * size);
- ez_deque_t *q = smrt_arena_push(arena, total_size, true);
+ ez_deque_t *q = smrt_arena_mark_push(arena, total_size, true);
+ if (!q) {
+ log_error("Failed to allocate deque");
+ smrt_arena_pop_to_mark(arena);
+ return NULL;
+ }
q->size = size;
q->element_size_bytes = elem_size;
+ #ifndef NLOG_TRACE
+ log_trace("Created deque; elem size %lu, capacity %lu", elem_size, size);
+ #endif /* ifndef NLOG_TRACE */
return q;
}
-// Returns false if queue can't hold elem.
-b32 ez_deque_enqueue(ez_deque_t *q, void *elem) {
+// Returns -1 if queue can't hold element, otherwise 0.
+i32 ez_deque_enqueue(ez_deque_t *q, void *elem) {
if (q->occupied < q->size) {
u64 insert_pos = EZ_DEQUE_BASE_POS + (q->back * q->element_size_bytes);
memcpy((u8*)q+insert_pos, elem, q->element_size_bytes);
q->back = (q->back + 1) % q->size;
q->occupied++;
- return true;
+ return 0;
}
- return false;
+ return -1;
}
void *ez_deque_pop(ez_deque_t *q) {
@@ -39,12 +47,27 @@ void *ez_deque_pop(ez_deque_t *q) {
// Sync constructs are allocated on arena
ts_deque_t ts_deque_create(smrt_arena_t *arena, ez_deque_t *q) {
- pthread_mutex_t *m = smrt_arena_push(arena, sizeof(pthread_mutex_t), true);
+ pthread_mutex_t *m = smrt_arena_mark_push(arena, sizeof(pthread_mutex_t), true);
+ if (!m) {
+ log_error("Failed to allocate TSQ mutex");
+ smrt_arena_pop_to_mark(arena);
+ return (ts_deque_t){0};
+ }
+
pthread_mutex_init(m, NULL);
sem_t *s = smrt_arena_push(arena, sizeof(sem_t), true);
+ if (!s) {
+ log_error("Failed to allocate TSQ semaphore");
+ smrt_arena_pop_to_mark(arena);
+ return (ts_deque_t){0};
+ }
sem_init(s, 0, 0);
+ #ifndef NLOG_TRACE
+ log_trace("Created thread-safe Deque; queue %p", q);
+ #endif /* ifndef NLOG_TRACE */
+
return (ts_deque_t){
.queue = q,
.write_lock = m,
@@ -55,13 +78,17 @@ ts_deque_t ts_deque_create(smrt_arena_t *arena, ez_deque_t *q) {
void ts_deque_destroy(ts_deque_t tsq) {
sem_destroy(tsq.count_sem);
pthread_mutex_destroy(tsq.write_lock);
+
+ #ifndef NLOG_TRACE
+ log_trace("Destroyed thread-safe Deque");
+ #endif /* ifndef NLOG_TRACE */
}
-b32 ts_deque_enqueue(ts_deque_t tsq, void *elem) {
+i32 ts_deque_enqueue(ts_deque_t tsq, void *elem) {
pthread_mutex_lock(tsq.write_lock);
- b32 result = ez_deque_enqueue(tsq.queue, elem);
+ i32 result = ez_deque_enqueue(tsq.queue, elem);
pthread_mutex_unlock(tsq.write_lock);
- if (result) sem_post(tsq.count_sem);
+ if (result == 0) sem_post(tsq.count_sem);
return result;
}
diff --git a/src/deque.h b/src/deque.h
index 65b1ca8..8a77b44 100644
--- a/src/deque.h
+++ b/src/deque.h
@@ -22,7 +22,7 @@ typedef struct {
ez_deque_t *ez_deque_create(smrt_arena_t *arena, u64 elem_size, u64 size);
// Returns false if queue can't hold elem.
- b32 ez_deque_enqueue(ez_deque_t *q, void *elem);
+ i32 ez_deque_enqueue(ez_deque_t *q, void *elem);
// Returns deque backed memory. Copy if needed.
void * ez_deque_pop(ez_deque_t *q);
@@ -38,6 +38,6 @@ ts_deque_t ts_deque_create(smrt_arena_t *arena, ez_deque_t * q);
void ts_deque_destroy(ts_deque_t tsq);
// Deal with re-enqueueing yourself
- b32 ts_deque_enqueue(ts_deque_t tsq ,
+ i32 ts_deque_enqueue(ts_deque_t tsq ,
void *elem);
void * ts_deque_pop(ts_deque_t tsq);
diff --git a/src/dft.c b/src/dft.c
index 7538b95..96630d8 100644
--- a/src/dft.c
+++ b/src/dft.c
@@ -8,43 +8,43 @@
dft_data_t discrete_fourier_transform(smrt_arena_t *arena, f64 *samples, u64 sample_count, u64 sample_rate) {
u64 freq_count = (sample_count / 2) + 1;
- f64 freq_step = (f64)sample_rate / (f64)sample_count;
+ f64 freq_step = (f64)sample_rate / (f64)sample_count;
- dft_data_t d = {.freq_count = freq_count};
- d.frequencies = SMRTA_ALLOC_ARRAY(arena, f64, freq_count);
- d.amplitudes = SMRTA_ALLOC_ARRAY(arena, f64, freq_count);
- d.phases = SMRTA_ALLOC_ARRAY(arena, f64, freq_count);
+ dft_data_t d = {.freq_count = freq_count};
+ d.frequencies = SMRTA_ALLOC_ARRAY(arena, f64, freq_count);
+ d.amplitudes = SMRTA_ALLOC_ARRAY(arena, f64, freq_count);
+ d.phases = SMRTA_ALLOC_ARRAY(arena, f64, freq_count);
- for (u64 freq_index = 0; freq_index < freq_count; freq_index++) {
- smrta_temp_t scratch = smrta_scratch_start(NULL, 0);
+ for (u64 freq_index = 0; freq_index < freq_count; freq_index++) {
+ smrta_temp_t scratch = smrta_scratch_start(NULL, 0);
- vec2d_soa_t vs;
- vs.xs = SMRTA_ALLOC_ARRAY(scratch.arena, f64, sample_count);
- vs.ys = SMRTA_ALLOC_ARRAY(scratch.arena, f64, sample_count);
- vs.size = sample_count;
+ vec2d_soa_t vs;
+ vs.xs = SMRTA_ALLOC_ARRAY(scratch.arena, f64, sample_count);
+ vs.ys = SMRTA_ALLOC_ARRAY(scratch.arena, f64, sample_count);
+ vs.size = sample_count;
- if (!vs.xs || !vs.ys) { smrta_scratch_end(scratch); return (dft_data_t){ 0 }; }
+ if (!vs.xs || !vs.ys) { smrta_scratch_end(scratch); return (dft_data_t){ 0 }; }
- for (u64 i = 0; i < sample_count; i++) {
- f64 angle = i / (f64)sample_count * PI * 2.0 * freq_index;
+ for (u64 i = 0; i < sample_count; i++) {
+ f64 angle = i / (f64)sample_count * PI * 2.0 * freq_index;
- vs.xs[i] = cos(angle) * samples[i];
- vs.ys[i] = sin(angle) * samples[i];
- }
+ vs.xs[i] = cos(angle) * samples[i];
+ vs.ys[i] = sin(angle) * samples[i];
+ }
- vec2d_t average_pos = vec2d_soa_average(&vs);
- smrta_scratch_end(scratch);
+ vec2d_t average_pos = vec2d_soa_average(&vs);
+ smrta_scratch_end(scratch);
- b8 is_zero_hz = freq_index == 0;
- b8 is_nyquist = freq_index == freq_count - 1 && sample_count % 2 == 0;
- f64 amp_coeff = is_zero_hz || is_nyquist ? 1.0 : 2.0;
+ b8 is_zero_hz = freq_index == 0;
+ b8 is_nyquist = freq_index == freq_count - 1 && sample_count % 2 == 0;
+ f64 amp_coeff = is_zero_hz || is_nyquist ? 1.0 : 2.0;
- d.frequencies[freq_index] = freq_index * freq_step;
- d.amplitudes[freq_index] = vec2d_length(average_pos) * amp_coeff;
- d.phases[freq_index] = -atan2(average_pos.y, average_pos.x);
+ d.frequencies[freq_index] = freq_index * freq_step;
+ d.amplitudes[freq_index] = vec2d_length(average_pos) * amp_coeff;
+ d.phases[freq_index] = -atan2(average_pos.y, average_pos.x);
- }
- return d;
+ }
+ return d;
}
static inline f64 hann_window(u64 i, u64 n) {
diff --git a/src/ez_arena.c b/src/ez_arena.c
index e37766e..a814289 100644
--- a/src/ez_arena.c
+++ b/src/ez_arena.c
@@ -1,4 +1,5 @@
#include "ez_arena.h"
+#include "log.h"
#include <stdlib.h>
#include <string.h>
@@ -7,6 +8,7 @@ ez_arena_t *ez_arena_create(u64 size, b32 zero_out) {
ez_arena_t *alloc = malloc(size + sizeof(ez_arena_t));
if (!alloc) {
+ log_error("Failed to malloc arena memory");
return NULL;
}
@@ -16,6 +18,10 @@ ez_arena_t *ez_arena_create(u64 size, b32 zero_out) {
*alloc = (ez_arena_t){ .alloc_size = size, .pos = EZ_ARENA_BASE_POS };
+ #ifndef NLOG_TRACE
+ log_trace("Created ez_arena; size %lu", size);
+ #endif /* ifndef NLOG_TRACE */
+
return alloc;
}
@@ -55,4 +61,8 @@ void ez_arena_clear(ez_arena_t *arena, b32 zero_out) {
void ez_arena_destroy(ez_arena_t *arena) {
free(arena);
+
+ #ifndef NLOG_TRACE
+ log_trace("Destroyed ez_arena");
+ #endif /* ifndef NLOG_TRACE */
}
diff --git a/src/log.c b/src/log.c
index 03b81e9..670fbb5 100644
--- a/src/log.c
+++ b/src/log.c
@@ -56,7 +56,7 @@ static inline void write_to_file(LogLevelE lvl, const char *src_file, u64 src_li
char time_str[64];
time_str[strftime(time_str, sizeof(time_str), "%Y-%m-%d %H:%M:%S", time)] = '\0';
- fprintf(L.log_file, "%s %-5s%s:%lu ", time_str, level_strings[lvl], src_file, src_line);
+ fprintf(L.log_file, "%s [%-5s] %s:%lu ", time_str, level_strings[lvl], src_file, src_line);
vfprintf(L.log_file, fmt, va);
fprintf(L.log_file, "\n");
}
@@ -81,7 +81,7 @@ void log_log(LogLevelE lvl, const char *src_file, u64 src_line, const char *fmt,
time_str[strftime(time_str, sizeof(time_str), "%H:%M:%S", time)] = '\0';
#ifndef LOG_NO_COLOR
- fprintf(L.log_default, "%s %s%-5s\x1b[0m\x1b[90m%s:%lu:\x1b[0m ",
+ fprintf(L.log_default, "%s %s[%-5s] \x1b[0m\x1b[90m%s:%lu:\x1b[0m ",
time_str, level_colors[lvl], level_strings[lvl], src_file, src_line);
#else
fprintf(L.log_default, "%s %-5s %s:%lu: ",
diff --git a/src/slidingwindow.c b/src/slidingwindow.c
index 883e852..5cf7415 100644
--- a/src/slidingwindow.c
+++ b/src/slidingwindow.c
@@ -1,6 +1,7 @@
#include "slidingwindow.h"
#include "common.h"
#include "smrt_arena.h"
+#include "log.h"
#include <string.h>
@@ -9,6 +10,10 @@ sliding_window_array_t *sw_create(smrt_arena_t *arena, u64 elem_size, u64 size)
sw->size = size;
sw->element_size_bytes = elem_size;
+ #ifndef NLOG_TRACE
+ log_trace("Created sliding window; elem size %lu, capacity %lu", elem_size, size);
+ #endif /* ifndef NLOG_TRACE */
+
return sw;
}
diff --git a/src/slidingwindow.h b/src/slidingwindow.h
index 17de775..424c11a 100644
--- a/src/slidingwindow.h
+++ b/src/slidingwindow.h
@@ -5,6 +5,7 @@
#define SLIDING_WINDOW_BASE_POS (sizeof(sliding_window_array_t))
+// Data structure that allows infinite inserts allowing access to the last 'size' elements
typedef struct {
u64 size;
u64 num_elements;
diff --git a/src/smrt_arena.c b/src/smrt_arena.c
index cf6418e..055877d 100644
--- a/src/smrt_arena.c
+++ b/src/smrt_arena.c
@@ -6,6 +6,7 @@
#include "common.h"
#include "smrt_arena.h"
+#include "log.h"
#include <string.h>
@@ -20,6 +21,7 @@ smrt_arena_t *smrt_arena_create(u64 reserve_size, u64 commit_size, b32 auto_deco
smrt_arena_t *arena = plat_mem_reserve(reserve_size);
if (!plat_mem_commit(arena, commit_size)) {
+ log_error("Failed to acquire virtual memory for smrt_arena");
return NULL;
}
@@ -30,6 +32,11 @@ smrt_arena_t *smrt_arena_create(u64 reserve_size, u64 commit_size, b32 auto_deco
arena->mark_pos = 0;
arena->auto_decommit = auto_decommit;
+ #ifndef NLOG_TRACE
+ log_trace("Created smrt_arena; Total %lu bytes, Commit size %lu bytes",
+ reserve_size, commit_size);
+ #endif /* ifndef NLOG_TRACE */
+
return arena;
}
@@ -58,7 +65,10 @@ void *smrt_arena_push(smrt_arena_t *arena, u64 alloc_amount, b32 zero_out) {
u64 pos_aligned = ALIGN_UP_POW2(arena->pos, ARENA_ALIGN);
u64 new_pos = pos_aligned + alloc_amount;
- if (new_pos > arena->reserve_size) { return NULL; }
+ if (new_pos > arena->reserve_size) {
+ log_warn("Allocation on smrt_arena exceeds reserve size");
+ return NULL;
+ }
if (new_pos > arena->commit_pos) {
u64 new_commit_pos = new_pos;
@@ -70,6 +80,7 @@ void *smrt_arena_push(smrt_arena_t *arena, u64 alloc_amount, b32 zero_out) {
u64 commit_size = new_commit_pos - arena->commit_pos;
if (!plat_mem_commit(mem, commit_size)) {
+ log_error("Failed to commit smrt_arena virtual memory");
return NULL;
}
@@ -111,14 +122,15 @@ void smrt_arena_pop_to(smrt_arena_t *arena, u64 pos) {
smrt_arena_pop(arena, size);
}
-b32 smrt_arena_pop_to_mark(smrt_arena_t *arena) {
+i32 smrt_arena_pop_to_mark(smrt_arena_t *arena) {
if (arena->mark_pos == 0) {
- return false;
+ log_debug("Tried to pop to mark but no mark was set");
+ return -1;
}
smrt_arena_pop_to(arena, arena->mark_pos);
- return true;
+ return 0;
}
void smrt_arena_clear(smrt_arena_t *arena, b32 zero_out) {
@@ -137,9 +149,17 @@ void smrt_arena_mark(smrt_arena_t *arena) {
void smrt_arena_destroy(smrt_arena_t *arena) {
plat_mem_release(arena, arena->reserve_size);
+
+ #ifndef NLOG_TRACE
+ log_trace("Destroyed smrt_arena");
+ #endif /* ifndef NLOG_TRACE */
}
smrta_temp_t smrta_temp_start(smrt_arena_t *arena) {
+ #ifndef NLOG_TRACE
+ log_trace("Starting temp arena");
+ #endif /* ifndef NLOG_TRACE */
+
return (smrta_temp_t){
.arena=arena,
.start_pos=arena->pos
@@ -148,6 +168,9 @@ smrta_temp_t smrta_temp_start(smrt_arena_t *arena) {
void smrta_temp_end(smrta_temp_t temp) {
smrt_arena_pop_to(temp.arena, temp.start_pos);
+ #ifndef NLOG_TRACE
+ log_trace("Ending temp arena");
+ #endif /* ifndef NLOG_TRACE */
}
smrta_temp_t smrta_scratch_start(smrt_arena_t **conflicts, u32 num_conflicts) {
@@ -226,6 +249,7 @@ u32 plat_get_pagesize(void) {
void* plat_mem_reserve(u64 size) {
void* out = mmap(NULL, size, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
if (out == MAP_FAILED) {
+ log_error("Failed to reserve virtual memory");
return NULL;
}
return out;
diff --git a/src/smrt_arena.h b/src/smrt_arena.h
index 48774e2..1b6725f 100644
--- a/src/smrt_arena.h
+++ b/src/smrt_arena.h
@@ -22,7 +22,7 @@ smrt_arena_t * smrt_arena_create(u64 reserve_size, u64 commit_size, b32 auto_
void smrt_arena_destroy(smrt_arena_t *arena);
void smrt_arena_mark(smrt_arena_t *arena);
void * smrt_arena_mark_push(smrt_arena_t *arena, u64 alloc_amount, b32 zero_out);
- b32 smrt_arena_pop_to_mark(smrt_arena_t *arena);
+ i32 smrt_arena_pop_to_mark(smrt_arena_t *arena);
#define SMRTA_ALLOC_ARRAY(arena, T, n) (T*)smrt_arena_push(arena, sizeof(T) * (n), true)
diff --git a/src/string.c b/src/string.c
index a29af19..c808642 100644
--- a/src/string.c
+++ b/src/string.c
@@ -1,13 +1,15 @@
#include "common.h"
#include "smrt_arena.h"
-#include <string.h>
-
+#include "log.h"
#include "string.h"
+#include <string.h>
+
strng_t *strng_new(smrt_arena_t *arena, u64 size) {
strng_t *s = smrt_arena_push(arena, sizeof(strng_t) + size, true);
if (!s) {
+ log_error("Failed to allocate strng");
return NULL;
}
@@ -21,6 +23,7 @@ strng_t *strng_from(smrt_arena_t *arena, char const *c) {
strng_t *s = strng_new(arena, size);
if (!s) {
+ log_error("Failed to allocate strng");
return NULL;
}
@@ -36,6 +39,7 @@ strng_t *strng_dup(smrt_arena_t *arena, strng_t const *src) {
strng_t *string = smrt_arena_push(arena, size, true);
if (!string) {
+ log_error("Failed to allocate strng");
return NULL;
}
@@ -51,6 +55,7 @@ char *strng_str(smrt_arena_t *arena, strng_t const *string) {
char *s = SMRTA_ALLOC_ARRAY(arena, char, string->len+1);
if (!s) {
+ log_error("Failed to allocate char*");
return NULL;
} else if (string->len == 0) {
return s;
@@ -61,17 +66,15 @@ char *strng_str(smrt_arena_t *arena, strng_t const *string) {
return s;
}
-b32 strng_set(strng_t *string, char const *c) {
+i32 strng_set(strng_t *string, char const *c) {
u64 size = strlen(c);
- if (string->alloc_size < size) {
- return false;
- }
+ if (string->alloc_size < size) return -1;
memcpy((u8*)string+STRNG_BASE_POS, c, size);
string->len = size;
- return true;
+ return 0;
}
void strng_clear(strng_t *string) {
diff --git a/src/string.h b/src/string.h
index ef6d966..5a89dec 100644
--- a/src/string.h
+++ b/src/string.h
@@ -14,7 +14,7 @@ strng_t * strng_new(smrt_arena_t *arena, u64 size);
strng_t *strng_from(smrt_arena_t *arena, char const *c);
strng_t * strng_dup(smrt_arena_t *arena, strng_t const *src);
char * strng_str(smrt_arena_t *arena, strng_t const *string);
- b32 strng_set(strng_t *string, char const *c);
+ i32 strng_set(strng_t *string, char const *c);
void strng_clear(strng_t *string);
#define STRNG_FMT(s) (i32)s->len, (char *)((u8*)s+STRNG_BASE_POS)
diff --git a/src/threadpool.c b/src/threadpool.c
index 68b34d6..56fcc3b 100644
--- a/src/threadpool.c
+++ b/src/threadpool.c
@@ -2,13 +2,13 @@
#include "threadpool.h"
#include "smrt_arena.h"
#include "deque.h"
+#include "log.h"
#include <bits/pthreadtypes.h>
#include <pthread.h>
#include <stdatomic.h>
#include <string.h>
-
typedef struct {
tp_job_proc proc;
void *args;
@@ -20,19 +20,25 @@ thread_pool_t *tp;
} worker_args;
void *worker_proc(void *args) {
- worker_args *wargs = (worker_args*)args;
- thread_pool_t *tp = wargs->tp;
+ worker_args *w_args = (worker_args*)args;
+ thread_pool_t *tp = w_args->tp;
+
+ #ifndef NLOG_TRACE
+ log_trace("Spinning up thread %lu", w_args->id);
+ #endif /* ifndef NLOG_TRACE */
pthread_mutex_lock(tp->count_mtx); {
tp->num_alive++;
} pthread_mutex_unlock(tp->count_mtx);
for (;;) {
- if (!wargs->tp->is_running) {
+ // if (!tp->is_running) break;
+ if (!w_args->tp->is_running) {
break;
}
- tp_job_t *j = (tp_job_t*)ts_deque_pop(wargs->tp->jobs);
+
+ tp_job_t *j = (tp_job_t*)ts_deque_pop(tp->jobs);
pthread_mutex_lock(tp->count_mtx);
tp->num_active++;
@@ -45,10 +51,19 @@ void *worker_proc(void *args) {
// If this is the last active thread finishing, tell someone about it
if (!tp->num_active) {
pthread_cond_broadcast(tp->done_signal);
+
+ #ifndef NLOG_TRACE
+ log_trace("[Thread %lu] Broadcasting complete", w_args->id);
+ #endif /* ifndef NLOG_TRACE */
+
}
pthread_mutex_unlock(tp->count_mtx);
}
+ #ifndef NLOG_TRACE
+ log_trace("Spinning down thread %lu", w_args->id);
+ #endif /* ifndef NLOG_TRACE */
+
pthread_mutex_lock(tp->count_mtx); {
tp->num_alive--;
} pthread_mutex_unlock(tp->count_mtx);
@@ -66,7 +81,7 @@ thread_pool_t *tp_create(smrt_arena_t *arena, u64 max_jobs, u64 num_threads) {
// I just leak this into the arena
worker_args * args = SMRTA_ALLOC_ARRAY(arena, worker_args, num_threads);
- pthread_mutex_t *count_mtx = smrt_arena_push(arena, sizeof(pthread_cond_t), true);
+ pthread_mutex_t *count_mtx = smrt_arena_push(arena, sizeof(pthread_mutex_t), true);
pthread_mutex_init(count_mtx, NULL);
pthread_cond_t *all_done = smrt_arena_push(arena, sizeof(pthread_cond_t), true);
pthread_cond_init(all_done, NULL);
@@ -94,12 +109,20 @@ thread_pool_t *tp_create(smrt_arena_t *arena, u64 max_jobs, u64 num_threads) {
while (tp->num_alive != num_threads) {}
+ #ifndef NLOG_TRACE
+ log_trace("Created threadpool; thread count %lu", num_threads);
+ #endif /* ifndef NLOG_TRACE */
+
return tp;
}
void no_op(void *nothing) { (void)nothing; }
i32 tp_destroy(thread_pool_t *tp) {
+ #ifndef NLOG_TRACE
+ log_trace("Destroying threadpool");
+ #endif /* ifndef NLOG_TRACE */
+
tp->is_running = false;
for (;;) {
// TODO: add timeout to skip this if a thread is hung
@@ -115,6 +138,9 @@ i32 tp_destroy(thread_pool_t *tp) {
ts_deque_destroy(tp->jobs);
pthread_mutex_destroy(tp->count_mtx);
pthread_cond_destroy(tp->done_signal);
+ #ifndef NLOG_TRACE
+ log_trace("Destroyed threadpool");
+ #endif /* ifndef NLOG_TRACE */
return 0;
}
@@ -124,13 +150,25 @@ i32 tp_push_job(thread_pool_t *tp, tp_job_proc job, void *args) {
.args = args,
};
+ #ifndef NLOG_TRACE
+ log_trace("Pushing job %p with arg %p onto threadpool.", job, args);
+ #endif /* ifndef NLOG_TRACE */
+
return ts_deque_enqueue(tp->jobs, &j);
}
void tp_wait(thread_pool_t *tp) {
+ #ifndef NLOG_TRACE
+ log_trace("Threadpool waiting for %lu jobs", tp->num_active + tp->jobs.queue->occupied);
+ #endif /* ifndef NLOG_TRACE */
+
pthread_mutex_lock(tp->count_mtx);
while (tp->jobs.queue->occupied || tp->num_active) {
pthread_cond_wait(tp->done_signal, tp->count_mtx);
}
pthread_mutex_unlock(tp->count_mtx);
+
+ #ifndef NLOG_TRACE
+ log_trace("Threadpool finished waiting");
+ #endif /* ifndef NLOG_TRACE */
}
diff --git a/src/threadpool.h b/src/threadpool.h
index ae97583..b009008 100644
--- a/src/threadpool.h
+++ b/src/threadpool.h
@@ -5,22 +5,23 @@
#include "smrt_arena.h"
#include <bits/pthreadtypes.h>
-#include <semaphore.h>
typedef void (*tp_job_proc)(void *args);
typedef struct {
u64 num_threads;
pthread_t * threads;
-
+// Threads check this before waiting for a job
b32 is_running;
-
+// Write mutex for num_active/alive
pthread_mutex_t * count_mtx;
+// Signal to tp_wait that all jobs are complete
pthread_cond_t *done_signal;
-
+// Threads currently doing a job
u64 num_active;
+// Threads who are alive
u64 num_alive;
-
+// Job queue
ts_deque_t jobs;
} thread_pool_t;
@@ -29,7 +30,6 @@ thread_pool_t *tp_create(smrt_arena_t * arena ,
u64 max_jobs ,
u64 num_threads);
-// This function waits for threads to finish, frees relevant allocations, and then frees *tp.
i32 tp_destroy(thread_pool_t *tp);
i32 tp_push_job(thread_pool_t * tp ,
diff --git a/src/vec2.c b/src/vec2.c
index 1e09c8e..9e779b1 100644
--- a/src/vec2.c
+++ b/src/vec2.c
@@ -1,5 +1,5 @@
-#include "vec2.h"
#include "common.h"
+#include "vec2.h"
#include <assert.h>
#include <math.h>
diff --git a/src/vec2sw.c b/src/vec2sw.c
index 0e1aec0..7e5e4d7 100644
--- a/src/vec2sw.c
+++ b/src/vec2sw.c
@@ -1,4 +1,5 @@
#include "vec2sw.h"
+#include "log.h"
#include "slidingwindow.h"
#include "vec2.h"
@@ -6,6 +7,10 @@ vec2d_sw_soa_t vec2d_sw_soa(smrt_arena_t *arena, u64 size) {
vec2d_sw_soa_t vs = { .size=size };
vs.xs = SMRTA_ALLOC_SLIDINGWINDOW(arena, f64, size);
vs.ys = SMRTA_ALLOC_SLIDINGWINDOW(arena, f64, size);
+ if (!(vs.xs && vs.ys)) {
+ log_error("Failed to allocate vec2d_sw_soa");
+ return (vec2d_sw_soa_t){0};
+ }
return vs;
}
@@ -14,7 +19,7 @@ void vec2d_sw_soa_insert(vec2d_sw_soa_t sw_vs, vec2d_t v) {
sw_insert(sw_vs.ys, (void*)&v.y);
}
-vec2d_soa_t vec2d_sw_soa_get(vec2d_sw_soa_t sw_vs) {
+vec2d_soa_t ec2d_sw_soa_get(vec2d_sw_soa_t sw_vs) {
return (vec2d_soa_t){
.size = sw_vs.xs->num_elements,
.xs = SLIDINGWINDOW_GET(sw_vs.xs, f64),
diff --git a/src/vec2sw.h b/src/vec2sw.h
index cbf8e6d..0207fdb 100644
--- a/src/vec2sw.h
+++ b/src/vec2sw.h
@@ -5,6 +5,7 @@
#include "vec2.h"
#include "slidingwindow.h"
+// Vec2d sliding window
typedef struct {
sliding_window_array_t *xs;
sliding_window_array_t *ys;
diff --git a/src/wav.c b/src/wav.c
index e1e6e2c..655b7b2 100644
--- a/src/wav.c
+++ b/src/wav.c
@@ -1,5 +1,6 @@
#include "wav.h"
#include "common.h"
+#include "log.h"
#include "smrt_arena.h"
#include <assert.h>
@@ -34,7 +35,10 @@ b32 seek_to_chunk(FILE *file, char const *chunk_name) {
wav_data_t load_wav_file(smrt_arena_t *arena, FILE *wav_file, wav_master_chunk_t *master_o, wav_fmt_chunk_t *format_o, u64 align_up_memoryn) {
wav_data_t data = { 0 };
- if (!wav_file) return data;
+ if (!wav_file) {
+ log_error("NULL file passed into load_wav_file");
+ return data;
+ }
fread(master_o, sizeof(wav_master_chunk_t), 1, wav_file);
@@ -44,7 +48,7 @@ wav_data_t load_wav_file(smrt_arena_t *arena, FILE *wav_file, wav_master_chunk_t
{
u16 f = format_o->audio_format;
if (f != 1 && f != 3) {
- perror("Attempted to read non pcm integer wave file.");
+ log_error("Attempted to read non pcm integer wave file.");
return data;
}
}
@@ -56,7 +60,10 @@ wav_data_t load_wav_file(smrt_arena_t *arena, FILE *wav_file, wav_master_chunk_t
fread(&sampled_data_size, 4, 1, wav_file);
data.samples = smrt_arena_push(arena, ALIGN_UP_POW2(sampled_data_size, align_up_memoryn), true);
- if (!data.samples) return data;
+ if (!data.samples) {
+ log_error("Failed to allocate samples");
+ return data;
+ }
fread((u8*)data.samples, sampled_data_size, 1, wav_file);
data.sample_count = sampled_data_size / ((format_o->bits_per_sample / 8) * format_o->num_channels);
@@ -64,8 +71,8 @@ wav_data_t load_wav_file(smrt_arena_t *arena, FILE *wav_file, wav_master_chunk_t
return data;
}
-b32 write_wav_file(FILE *wav_file, wav_fmt_chunk_t *fmt_chunk_i, wav_data_t data_i) {
- if (!wav_file) return false;
+i32 write_wav_file(FILE *wav_file, wav_fmt_chunk_t *fmt_chunk_i, wav_data_t data_i) {
+ if (!wav_file) return -1;
u32 data_size_bytes = data_i.sample_count * fmt_chunk_i->bytes_per_block;
@@ -82,7 +89,7 @@ b32 write_wav_file(FILE *wav_file, wav_fmt_chunk_t *fmt_chunk_i, wav_data_t data
fwrite(&data_size_bytes, 4, 1, wav_file);
fwrite(data_i.samples, sizeof(u8), data_size_bytes, wav_file);
- return true;
+ return 0;
}
wav_fmt_chunk_t make_wav_fmt_chunk(u32 num_channels, u32 sample_rate, u16 bits_per_sample) {
@@ -115,7 +122,7 @@ void wav_load(smrt_arena_t *arena, FILE *wav, f64 ***samples_o ,u16 *channel_cou
align_up_memoryn);
if (!data.samples) {
- perror("Failed to load data.");
+ log_error("Failed to load data.");
goto failed;
}
@@ -150,7 +157,7 @@ void wav_load(smrt_arena_t *arena, FILE *wav, f64 ***samples_o ,u16 *channel_cou
align_up_memoryn);
break;
default:
- perror("Only PCM integer 8,16,24 bits data can be read.");
+ log_error("Only PCM integer 8,16,24 bits data can be read.");
goto failed;
}
break;
@@ -164,12 +171,12 @@ void wav_load(smrt_arena_t *arena, FILE *wav, f64 ***samples_o ,u16 *channel_cou
align_up_memoryn);
break;
default:
- perror("Only 32 bits float data can be read.");
+ log_error("Only 32 bits float data can be read.");
goto failed;
}
break;
default:
- perror("Expected audio_format=1|3");
+ log_error("Expected audio_format=1|3");
goto failed;
}
(*samples_o)[c] = d;
@@ -178,6 +185,12 @@ void wav_load(smrt_arena_t *arena, FILE *wav, f64 ***samples_o ,u16 *channel_cou
smrta_scratch_end(scratch);
*sample_count_o = data.sample_count;
*sample_rate_o = f.sample_rate;
+
+ #ifndef NLOG_TRACE
+ log_trace("Loaded wav file; %lu samples, %duhz, %du channels",
+ data.sample_count, f.sample_rate, f.num_channels);
+ #endif /* ifndef NLOG_TRACE */
+
return;
failed:
@@ -186,6 +199,7 @@ failed:
*samples_o = NULL;
*sample_count_o = 0;
*sample_rate_o = 0;
+ *channel_count_o = 0;
return;
}
@@ -193,7 +207,10 @@ f64 *read_8bps_data(smrt_arena_t *arena, wav_data_t data, u16 num_channels, u16
assert(num_channels != 0 && "num_channels must be >0");
f64 *vs = smrt_arena_push(arena, ALIGN_UP_POW2(sizeof(f64) * data.sample_count, align_up_memoryn), true);
- if (!vs) return NULL;
+ if (!vs) {
+ log_error("Failed to allocate values");
+ return NULL;
+ }
for (u64 i = 0; i < data.sample_count; i++) {
u8 sample = data.samples[(i*num_channels)+ channel];
@@ -209,7 +226,10 @@ f64 *read_16bps_data(smrt_arena_t *arena, wav_data_t data, u16 num_channels, u16
assert(num_channels != 0 && "num_channels must be >0");
f64 *vs = smrt_arena_push(arena, ALIGN_UP_POW2(sizeof(f64) * data.sample_count, align_up_memoryn), true);
- if (!vs) return NULL;
+ if (!vs) {
+ log_error("Failed to allocate values");
+ return NULL;
+ }
for (u64 i = 0; i < data.sample_count; i++) {
u8 low = data.samples[(i*2*num_channels)+ channel*2];
@@ -227,7 +247,10 @@ f64 *read_24bps_data(smrt_arena_t *arena, wav_data_t data, u16 num_channels, u16
assert(num_channels != 0 && "num_channels must be >0");
f64 *vs = smrt_arena_push(arena, ALIGN_UP_POW2(sizeof(f64) * data.sample_count, align_up_memoryn), true);
- if (!vs) return NULL;
+ if (!vs) {
+ log_error("Failed to allocate values");
+ return NULL;
+ }
for (u64 i = 0; i < data.sample_count; i++) {
u8 low = data.samples[(i*3*num_channels)+ channel*3];
@@ -247,7 +270,10 @@ f64 *read_32bps_float_data(smrt_arena_t *arena, wav_data_t data, u16 num_channel
assert(num_channels != 0 && "num_channels must be >0");
f64 *vs = smrt_arena_push(arena, ALIGN_UP_POW2(sizeof(f64) * data.sample_count, align_up_memoryn), true);
- if (!vs) return NULL;
+ if (!vs) {
+ log_error("Failed to allocate values");
+ return NULL;
+ }
for (u64 i = 0; i < data.sample_count; i++) {
u8 one = data.samples[(i*4*num_channels)+ channel*4];
diff --git a/src/wav.h b/src/wav.h
index cba319e..584d9d4 100644
--- a/src/wav.h
+++ b/src/wav.h
@@ -51,7 +51,7 @@ wav_data_t load_wav_file(smrt_arena_t * arena ,
u64 align_up_memoryn);
/// Write WAV headers and data to wav_file.
-b32 write_wav_file(FILE * wav_file ,
+i32 write_wav_file(FILE * wav_file ,
wav_fmt_chunk_t *fmt_chunk_i ,
wav_data_t data_i);