diff options
author | Vito Caputo <vcaputo@pengaru.com> | 2021-02-18 03:12:25 -0800 |
---|---|---|
committer | Vito Caputo <vcaputo@pengaru.com> | 2021-02-18 03:36:37 -0800 |
commit | 0536326f814739a4ee6136f4156431e77fe45769 (patch) | |
tree | e911431e878f2fa0ee6f102bfdc10cfe1202c2cb | |
parent | 561bc18c2ff6ba42d4640eccb097b7f4bc8fecc3 (diff) |
fb: make inactive pages list doubly-linked
This introduces a previous pointer to _fb_page_t, but it's
only used on the inactive list.
This is a preparatory commit to facilitate adding inactive pages
at the head and consuming inactive pages off the tail, without
having to always iterate the list for the new tail.
Rebuilding pages on resize needs to happen somewhere, and the
inactive list seems like the right place to do it. And to do it
with a simple per-fb pages-needing-rebuild counter requires
turning the inactive list into a FIFO queue.
-rw-r--r-- | src/fb.c | 46 |
1 files changed, 35 insertions, 11 deletions
@@ -58,7 +58,7 @@ typedef struct _fb_page_t _fb_page_t; struct _fb_page_t { void *ops_page; - _fb_page_t *next; + _fb_page_t *next, *previous; fb_page_t public_page; }; @@ -75,7 +75,8 @@ typedef struct fb_t { pthread_mutex_t inactive_mutex; pthread_cond_t inactive_cond; - _fb_page_t *inactive_pages; /* finished pages available for (re)use */ + _fb_page_t *inactive_pages_head; /* finished pages available for (re)use */ + _fb_page_t *inactive_pages_tail; unsigned put_pages_count; } fb_t; @@ -114,8 +115,13 @@ int fb_flip(fb_t *fb) /* now that we're displaying a new page, make the previously active one inactive so rendering can reuse it */ pthread_mutex_lock(&fb->inactive_mutex); - fb->active_page->next = fb->inactive_pages; - fb->inactive_pages = fb->active_page; + fb->active_page->next = fb->inactive_pages_head; + fb->inactive_pages_head = fb->active_page; + fb->inactive_pages_head->previous = NULL; + if (fb->inactive_pages_head->next) + fb->inactive_pages_head->next->previous = fb->inactive_pages_head; + else + fb->inactive_pages_tail = fb->inactive_pages_head; pthread_cond_signal(&fb->inactive_cond); pthread_mutex_unlock(&fb->inactive_mutex); @@ -144,8 +150,18 @@ static int fb_acquire(fb_t *fb, _fb_page_t *page) static void fb_release(fb_t *fb) { fb->ops->release(fb, fb->ops_context); - fb->active_page->next = fb->inactive_pages; - fb->inactive_pages = fb->active_page; + + /* XXX: this is getting silly, either add a doubly linked list header or + * at least use some functions for this local to this file. + */ + fb->active_page->next = fb->inactive_pages_head; + fb->inactive_pages_head = fb->active_page; + fb->inactive_pages_head->previous = NULL; + if (fb->inactive_pages_head->next) + fb->inactive_pages_head->next->previous = fb->inactive_pages_head; + else + fb->inactive_pages_tail = fb->inactive_pages_head; + fb->active_page = NULL; } @@ -161,8 +177,12 @@ static void fb_page_new(fb_t *fb) page->ops_page = fb->ops->page_alloc(fb, fb->ops_context, &page->public_page); pthread_mutex_lock(&fb->inactive_mutex); - page->next = fb->inactive_pages; - fb->inactive_pages = page; + page->next = fb->inactive_pages_head; + fb->inactive_pages_head = page; + if (fb->inactive_pages_head->next) + fb->inactive_pages_head->next->previous = fb->inactive_pages_head; + else + fb->inactive_pages_tail = fb->inactive_pages_head; pthread_mutex_unlock(&fb->inactive_mutex); } @@ -185,12 +205,16 @@ static inline _fb_page_t * _fb_page_get(fb_t *fb) * pages faster than vhz. */ pthread_mutex_lock(&fb->inactive_mutex); - while (!(page = fb->inactive_pages)) + while (!(page = fb->inactive_pages_tail)) pthread_cond_wait(&fb->inactive_cond, &fb->inactive_mutex); - fb->inactive_pages = page->next; + fb->inactive_pages_tail = page->previous; + if (fb->inactive_pages_tail) + fb->inactive_pages_tail->next = NULL; + else + fb->inactive_pages_head = NULL; pthread_mutex_unlock(&fb->inactive_mutex); - page->next = NULL; + page->next = page->previous = NULL; page->public_page.fragment.zeroed = 0; return page; |