summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVito Caputo <vcaputo@pengaru.com>2023-08-13 23:16:20 -0700
committerVito Caputo <vcaputo@pengaru.com>2023-08-13 23:16:20 -0700
commitcf4b27c90534fe2c7842f96c1553eaace1e81190 (patch)
tree3d7d2f7481f88cae32c6c854646f5e89d6d039a1
parenta41d4e72dc915a8cb79aa8f1f2177def06d75844 (diff)
til_fb: introduce til_fb_halt()
This makes it so til_fb_page_get() will return NULL when the fb has been "halted". If til_fb_page_get() is already waiting for a page to become available, it will be woken up by til_fb_halt(). Preparatory commit for eliminating the reliance on pthread_cancel() to terminate rototiller_thread() on shutdown. Cancellation is always a PITA, especially cross-platform, but in general it's so easy to have subtle bugs when using it.
-rw-r--r--src/til_fb.c26
-rw-r--r--src/til_fb.h1
2 files changed, 25 insertions, 2 deletions
diff --git a/src/til_fb.c b/src/til_fb.c
index 10a5931..1bdb2e7 100644
--- a/src/til_fb.c
+++ b/src/til_fb.c
@@ -143,6 +143,7 @@ typedef struct til_fb_t {
_til_fb_page_t *all_pages_tail;
unsigned put_pages_count;
+ unsigned halted:1;
} til_fb_t;
#ifndef container_of
@@ -391,8 +392,14 @@ static inline _til_fb_page_t * _til_fb_page_get(til_fb_t *fb)
* pages faster than vhz.
*/
pthread_mutex_lock(&fb->inactive_mutex);
- while (!(page = fb->inactive_pages_tail))
+ while (!(page = fb->inactive_pages_tail) && !fb->halted)
pthread_cond_wait(&fb->inactive_cond, &fb->inactive_mutex);
+
+ if (!page) {
+ pthread_mutex_unlock(&fb->inactive_mutex);
+ return NULL;
+ }
+
fb->inactive_pages_tail = page->previous;
if (fb->inactive_pages_tail)
fb->inactive_pages_tail->next = NULL;
@@ -410,7 +417,13 @@ static inline _til_fb_page_t * _til_fb_page_get(til_fb_t *fb)
/* public interface */
til_fb_fragment_t * til_fb_page_get(til_fb_t *fb)
{
- return &(_til_fb_page_get(fb)->fragment.public);
+ _til_fb_page_t *page;
+
+ page = _til_fb_page_get(fb);
+ if (!page)
+ return NULL;
+
+ return &page->fragment.public;
}
@@ -602,6 +615,15 @@ void til_fb_rebuild(til_fb_t *fb)
}
+void til_fb_halt(til_fb_t *fb)
+{
+ assert(fb);
+
+ fb->halted = 1;
+ pthread_cond_signal(&fb->inactive_cond);
+}
+
+
/* accessor for getting the ops_context */
void * til_fb_context(til_fb_t *fb)
{
diff --git a/src/til_fb.h b/src/til_fb.h
index 1f100dd..5ad210f 100644
--- a/src/til_fb.h
+++ b/src/til_fb.h
@@ -55,6 +55,7 @@ til_fb_t * til_fb_free(til_fb_t *fb);
void til_fb_get_put_pages_count(til_fb_t *fb, unsigned *count);
int til_fb_new(const til_fb_ops_t *ops, const char *title, const til_setup_t *setup, int n_pages, til_fb_t **res_fb);
void til_fb_rebuild(til_fb_t *fb);
+void til_fb_halt(til_fb_t *fb);
void * til_fb_context(til_fb_t *fb);
int til_fb_flip(til_fb_t *fb);
void til_fb_fragment_divide(til_fb_fragment_t *fragment, unsigned n_fragments, til_fb_fragment_t fragments[]);
© All Rights Reserved