summaryrefslogtreecommitdiff
path: root/src/threads.c
diff options
context:
space:
mode:
authorVito Caputo <vcaputo@pengaru.com>2021-10-01 16:35:08 -0700
committerVito Caputo <vcaputo@pengaru.com>2021-10-01 16:35:08 -0700
commitb686b405c6a22b26e9b8082c92ed91513608bea3 (patch)
tree0000f671501863a8ee9b536ba869221d0f6710f9 /src/threads.c
parentd1da5500261e96efe0ede06fbebb32f0e191f3c1 (diff)
*: librototiller->libtil
Largely mechanical rename of librototiller -> libtil, but introducing a til_ prefix to all librototiller (now libtil) functions and types where a rototiller prefix was absent. This is just a step towards a more libized librototiller, and til is just a nicer to type/read prefix than rototiller_.
Diffstat (limited to 'src/threads.c')
-rw-r--r--src/threads.c168
1 files changed, 0 insertions, 168 deletions
diff --git a/src/threads.c b/src/threads.c
deleted file mode 100644
index dd1d620..0000000
--- a/src/threads.c
+++ /dev/null
@@ -1,168 +0,0 @@
-#include <assert.h>
-#include <pthread.h>
-#include <stdlib.h>
-
-#include "fb.h"
-#include "rototiller.h"
-#include "threads.h"
-#include "util.h"
-
-typedef struct thread_t {
- threads_t *threads;
- pthread_t pthread;
- unsigned id;
-} thread_t;
-
-typedef struct threads_t {
- unsigned n_threads;
-
- pthread_mutex_t idle_mutex;
- pthread_cond_t idle_cond;
- unsigned n_idle;
-
- pthread_mutex_t frame_mutex;
- pthread_cond_t frame_cond;
- void (*render_fragment_func)(void *context, unsigned ticks, unsigned cpu, fb_fragment_t *fragment);
- void *context;
- fb_fragment_t *fragment;
- rototiller_fragmenter_t fragmenter;
- unsigned ticks;
-
- unsigned next_fragment;
- unsigned frame_num;
-
- thread_t threads[];
-} threads_t;
-
-
-/* render fragments using the supplied render function */
-static void * thread_func(void *_thread)
-{
- thread_t *thread = _thread;
- threads_t *threads = thread->threads;
- unsigned prev_frame_num = 0;
-
- pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
-
- for (;;) {
-
- /* wait for a new frame */
- pthread_mutex_lock(&threads->frame_mutex);
- pthread_cleanup_push((void (*)(void *))pthread_mutex_unlock, &threads->frame_mutex);
- while (threads->frame_num == prev_frame_num)
- pthread_cond_wait(&threads->frame_cond, &threads->frame_mutex);
- prev_frame_num = threads->frame_num;
- pthread_cleanup_pop(1);
-
- /* render fragments */
- for (;;) {
- unsigned frag_num;
- fb_fragment_t fragment;
-
- frag_num = __sync_fetch_and_add(&threads->next_fragment, 1);
-
- if (!threads->fragmenter(threads->context, threads->fragment, frag_num, &fragment))
- break;
-
- threads->render_fragment_func(threads->context, threads->ticks, thread->id, &fragment);
- }
-
- /* report as idle */
- pthread_mutex_lock(&threads->idle_mutex);
- pthread_cleanup_push((void (*)(void *))pthread_mutex_unlock, &threads->idle_mutex);
- threads->n_idle++;
- if (threads->n_idle == threads->n_threads) /* Frame finished! Notify potential waiter. */
- pthread_cond_signal(&threads->idle_cond);
- pthread_cleanup_pop(1);
- }
-
- return NULL;
-}
-
-
-/* wait for all threads to be idle */
-void threads_wait_idle(threads_t *threads)
-{
- pthread_mutex_lock(&threads->idle_mutex);
- pthread_cleanup_push((void (*)(void *))pthread_mutex_unlock, &threads->idle_mutex);
- while (threads->n_idle < threads->n_threads)
- pthread_cond_wait(&threads->idle_cond, &threads->idle_mutex);
- pthread_cleanup_pop(1);
-}
-
-
-/* submit a frame's fragments to the threads */
-void threads_frame_submit(threads_t *threads, fb_fragment_t *fragment, rototiller_fragmenter_t fragmenter, void (*render_fragment_func)(void *context, unsigned ticks, unsigned cpu, fb_fragment_t *fragment), void *context, unsigned ticks)
-{
- threads_wait_idle(threads); /* XXX: likely non-blocking; already happens pre page flip */
-
- pthread_mutex_lock(&threads->frame_mutex);
- pthread_cleanup_push((void (*)(void *))pthread_mutex_unlock, &threads->frame_mutex);
- threads->fragment = fragment;
- threads->fragmenter = fragmenter;
- threads->render_fragment_func = render_fragment_func;
- threads->context = context;
- threads->ticks = ticks;
- threads->frame_num++;
- threads->n_idle = threads->next_fragment = 0;
- pthread_cond_broadcast(&threads->frame_cond);
- pthread_cleanup_pop(1);
-}
-
-
-/* create threads instance, a thread per cpu is created */
-threads_t * threads_create(void)
-{
- unsigned i, num = get_ncpus();
- threads_t *threads;
-
- threads = calloc(1, sizeof(threads_t) + sizeof(thread_t) * num);
- if (!threads)
- return NULL;
-
- threads->n_idle = threads->n_threads = num;
-
- pthread_mutex_init(&threads->idle_mutex, NULL);
- pthread_cond_init(&threads->idle_cond, NULL);
-
- pthread_mutex_init(&threads->frame_mutex, NULL);
- pthread_cond_init(&threads->frame_cond, NULL);
-
- for (i = 0; i < num; i++) {
- thread_t *thread = &threads->threads[i];
-
- thread->threads = threads;
- thread->id = i;
- pthread_create(&thread->pthread, NULL, thread_func, thread);
- }
-
- return threads;
-}
-
-
-/* destroy a threads instance */
-void threads_destroy(threads_t *threads)
-{
- unsigned i;
-
- for (i = 0; i < threads->n_threads; i++)
- pthread_cancel(threads->threads[i].pthread);
-
- for (i = 0; i < threads->n_threads; i++)
- pthread_join(threads->threads[i].pthread, NULL);
-
- pthread_mutex_destroy(&threads->idle_mutex);
- pthread_cond_destroy(&threads->idle_cond);
-
- pthread_mutex_destroy(&threads->frame_mutex);
- pthread_cond_destroy(&threads->frame_cond);
-
- free(threads);
-}
-
-
-/* return the number of threads */
-unsigned threads_num_threads(threads_t *threads)
-{
- return threads->n_threads;
-}
© All Rights Reserved