2626
2727#include <queues/task_queue.h>
2828
29+ #include <features/features_cpu.h>
30+
2931#ifdef HAVE_THREADS
3032#include <rthreads/rthreads.h>
3133#define SLOCK_LOCK (x ) slock_lock(x)
@@ -112,7 +114,24 @@ static void task_queue_put(task_queue_t *queue, retro_task_t *task)
112114 task -> next = NULL ;
113115
114116 if (queue -> front )
117+ {
118+ /* Make sure to insert in order - the queue is sorted by 'when' so items that aren't scheduled
119+ * to run immediately are at the back of the queue. Items with the same 'when' are inserted after
120+ * all the other items with the same 'when'. This primarily affects items with a 'when' of 0.
121+ */
122+ if (queue -> back -> when > task -> when )
123+ {
124+ retro_task_t * * prev = & queue -> front ;
125+ while (* prev && (* prev )-> when <= task -> when )
126+ prev = & ((* prev )-> next );
127+
128+ task -> next = * prev ;
129+ * prev = task ;
130+ return ;
131+ }
132+
115133 queue -> back -> next = task ;
134+ }
116135 else
117136 queue -> front = task ;
118137
@@ -181,9 +200,13 @@ static void retro_task_regular_gather(void)
181200 for (task = queue ; task ; task = next )
182201 {
183202 next = task -> next ;
184- task -> handler (task );
185203
186- task_queue_push_progress (task );
204+ if (!task -> when || task -> when < cpu_features_get_time_usec ())
205+ {
206+ task -> handler (task );
207+
208+ task_queue_push_progress (task );
209+ }
187210
188211 if (task -> finished )
189212 task_queue_put (& tasks_finished , task );
@@ -304,9 +327,10 @@ static void task_queue_remove(task_queue_t *queue, retro_task_t *task)
304327 {
305328 slock_lock (queue_lock );
306329 queue -> front = task -> next ;
330+ if (queue -> back == task ) /* if only element, also update back */
331+ queue -> back = NULL ;
307332 slock_unlock (queue_lock );
308333 task -> next = NULL ;
309-
310334 return ;
311335 }
312336
@@ -320,6 +344,15 @@ static void task_queue_remove(task_queue_t *queue, retro_task_t *task)
320344 {
321345 t -> next = task -> next ;
322346 task -> next = NULL ;
347+
348+ /* When removing the tail of the queue, update the tail pointer */
349+ if (queue -> back == task )
350+ {
351+ slock_lock (queue_lock );
352+ if (queue -> back == task )
353+ queue -> back = t ;
354+ slock_unlock (queue_lock );
355+ }
323356 break ;
324357 }
325358
@@ -453,6 +486,18 @@ static void threaded_worker(void *userdata)
453486 continue ;
454487 }
455488
489+ if (task -> when )
490+ {
491+ retro_time_t now = cpu_features_get_time_usec ();
492+ retro_time_t delay = task -> when - now - 500 ; /* allow half a millisecond for context switching */
493+ if (delay > 0 )
494+ {
495+ scond_wait_timeout (worker_cond , running_lock , delay );
496+ slock_unlock (running_lock );
497+ continue ;
498+ }
499+ }
500+
456501 slock_unlock (running_lock );
457502
458503 task -> handler (task );
0 commit comments