diff options
author | Christian Soffke <christian.soffke@gmail.com> | 2021-11-26 21:08:49 +0100 |
---|---|---|
committer | William Wilgus <me.theuser@yahoo.com> | 2021-12-03 23:51:12 -0500 |
commit | 2bd0d5738f1b29640eec2a916d7b57fe3cf5eaab (patch) | |
tree | 78735292ee3c10e414914829c9f44ee28c3264ac | |
parent | 09e1cd489f2316e2a2714436674fc4b97c8f9c49 (diff) | |
download | rockbox-2bd0d5738f.tar.gz rockbox-2bd0d5738f.zip |
PictureFlow: Preliminary fix for infinite loop
Supposed to prevent situations where PictureFlow
enters into an infinite loop while unsuccessfully
looking for a slide cache slot.
Technically more of a bandaid than a fix at this point,
since it masks behavior that shouldn't occur in the
first place, but at least it will make the issue essentially
unnoticeable by the user for the time being.
Change-Id: I8a9b30448949dd53f624eae918484b740b4f873e
-rw-r--r-- | apps/plugins/pictureflow/pictureflow.c | 67 |
1 files changed, 47 insertions, 20 deletions
diff --git a/apps/plugins/pictureflow/pictureflow.c b/apps/plugins/pictureflow/pictureflow.c index 6db28f3aa1..db04f6b89a 100644 --- a/apps/plugins/pictureflow/pictureflow.c +++ b/apps/plugins/pictureflow/pictureflow.c @@ -2198,6 +2198,26 @@ static bool create_pf_thread(void) } +static void initialize_slide_cache(void) +{ + int i= 0; + for (i = 0; i < SLIDE_CACHE_SIZE; i++) { + pf_sldcache.cache[i].hid = 0; + pf_sldcache.cache[i].index = 0; + pf_sldcache.cache[i].next = i + 1; + pf_sldcache.cache[i].prev = i - 1; + } + pf_sldcache.cache[0].prev = i - 1; + pf_sldcache.cache[i - 1].next = 0; + + pf_sldcache.free = 0; + pf_sldcache.used = -1; + pf_sldcache.left_idx = -1; + pf_sldcache.right_idx = -1; + pf_sldcache.center_idx = -1; +} + + /* * The following functions implement the linked-list-in-array used to manage * the LRU cache of slides, and the list of free cache slots. @@ -2206,20 +2226,30 @@ static bool create_pf_thread(void) #define _SEEK_RIGHT_WHILE(start, cond) \ ({ \ int ind_, next_ = (start); \ + int i_ = 0; \ do { \ ind_ = next_; \ next_ = pf_sldcache.cache[ind_].next; \ - } while (next_ != pf_sldcache.used && (cond)); \ + i_++; \ + } while (next_ != pf_sldcache.used && (cond) && i_ < SLIDE_CACHE_SIZE); \ + if (i_ >= SLIDE_CACHE_SIZE) \ + /* TODO: Not supposed to happen */ \ + ind_ = -1; \ ind_; \ }) #define _SEEK_LEFT_WHILE(start, cond) \ ({ \ int ind_, next_ = (start); \ + int i_ = 0; \ do { \ ind_ = next_; \ next_ = pf_sldcache.cache[ind_].prev; \ - } while (ind_ != pf_sldcache.used && (cond)); \ + i_++; \ + } while (ind_ != pf_sldcache.used && (cond) && i_ < SLIDE_CACHE_SIZE); \ + if (i_ >= SLIDE_CACHE_SIZE) \ + /* TODO: Not supposed to happen */ \ + ind_ = -1; \ ind_; \ }) @@ -2463,6 +2493,8 @@ bool load_new_slide(void) { pf_sldcache.center_idx = _SEEK_RIGHT_WHILE(pf_sldcache.center_idx, pf_sldcache.cache[next_].index <= center_index); + if (pf_sldcache.center_idx == -1) + goto fatal_fail; prev = pf_sldcache.center_idx; next = pf_sldcache.cache[pf_sldcache.center_idx].next; @@ -2471,6 +2503,8 @@ bool load_new_slide(void) { pf_sldcache.center_idx = _SEEK_LEFT_WHILE(pf_sldcache.center_idx, pf_sldcache.cache[next_].index >= center_index); + if (pf_sldcache.center_idx == -1) + goto fatal_fail; next = pf_sldcache.center_idx; prev = pf_sldcache.cache[pf_sldcache.center_idx].prev; @@ -2517,6 +2551,8 @@ bool load_new_slide(void) pf_sldcache.right_idx = _SEEK_RIGHT_WHILE(pf_sldcache.right_idx, pf_sldcache.cache[ind_].index - 1 == pf_sldcache.cache[next_].index); + if (pf_sldcache.right_idx == -1 || pf_sldcache.left_idx == -1) + goto fatal_fail; /* update indices */ @@ -2581,6 +2617,11 @@ fail_and_refree: } buf_ctx_unlock(); return false; +fatal_fail: + free_all_slide_prio(0); + initialize_slide_cache(); + buf_ctx_unlock(); + return false; } @@ -2612,11 +2653,13 @@ static inline struct dim *surface(const int slide_index) int i; if ((i = pf_sldcache.used ) != -1) { + int j = 0; do { if (pf_sldcache.cache[i].index == slide_index) return get_slide(pf_sldcache.cache[i].hid); i = pf_sldcache.cache[i].next; - } while (i != pf_sldcache.used); + j++; + } while (i != pf_sldcache.used && j < SLIDE_CACHE_SIZE); } return get_slide(empty_slide_hid); } @@ -3810,23 +3853,7 @@ static int pictureflow_main(void) return PLUGIN_ERROR; } - int i; - - /* initialize */ - for (i = 0; i < SLIDE_CACHE_SIZE; i++) { - pf_sldcache.cache[i].hid = 0; - pf_sldcache.cache[i].index = 0; - pf_sldcache.cache[i].next = i + 1; - pf_sldcache.cache[i].prev = i - 1; - } - pf_sldcache.cache[0].prev = i - 1; - pf_sldcache.cache[i - 1].next = 0; - - pf_sldcache.free = 0; - pf_sldcache.used = -1; - pf_sldcache.left_idx = -1; - pf_sldcache.right_idx = -1; - pf_sldcache.center_idx = -1; + initialize_slide_cache(); buffer = LCD_BUF; |