Bug #712

Fix thread management in all apps

Added by Hammel 22 days ago. Updated 22 days ago.

Status:In ProgressStart date:26 Jun 2019
Priority:ImmediateDue date:
Assignee:Hammel% Done:

10%

Category:04 - Applications
Target version:1.1.0 - Upgrades
Severity:01 - Critical

Description

I have lousy thread management in my apps. The current design for all apps is this.

  1. Start all threads
  2. each thread spins looking for work
    1. if no work, short delay and spin again
  3. spin in main thread till exit

This has worked fine up till now but it sucks. The threads are polling for work and spinning wildly if there isn't any. There are artificial delay loops to slow them down, but it's sucking the life out of the Pis, especially the Pi Zero. I disable some of the threads on Xeon builds but that's a hack. I need better thread synchronization.

What should really happen is this.
  1. Start event queue thread waiting on network or other I/O via select() or similar.
  2. Inbound message placed on appropriate queue.
  3. start thread for that queue is called.
In the other thread.
  1. If started, return (prevents multiple thread starts)
  2. Run the queue until exhausted.
  3. Exit the thread.

The start-thread call uses a mutex on a variable that can tell when the thread has exited.

There should never be more than one thread started when the app starts and that thread should be waiting on kernel events (network or other I/O) so that it's not polling and chewing up CPU time.

In other words: apps should be idle unless there is actual work to do!

Apps to review and fix:
  1. piboxd
  2. appmgr
  3. videofe
  4. musicfe
  5. jarvis
  6. picam
  7. pidialer
  8. pipics
  9. pixm

Note: Everything that uses the piboxTouchProcessor() should be reviewed but mostly the piboxTouchProcessor() should be checked to make sure it's event driven and not polling. I don't think msgProcessor.c or queueProcessor.c in libpibox are being used yet but they should be checked too.

History

#1 Updated by Hammel 22 days ago

  • Status changed from New to In Progress
  • % Done changed from 0 to 10

See: https://gist.github.com/rtv/4989304
See: https://www.geeksforgeeks.org/condition-wait-signal-multi-threading/
An alternative it to use pthread signals. We start each consumer thread as before but in each loop we wait on a signal

pthread_cond_wait( &cond, &mutex )

When we need to signal the thread from the producer (whoever is putting work on the queue)

pthread_cond_signal( &cond )

We need the mutex to set the signal and around the _wait() but the wait actually releases the mutex while it waits. Thread loops exhaust the queue before waiting on another signal, but producers always signal when they have work to do.

Q: do all signals have to be consumed by an equivalent wait?
A: I don't think so. They are async and immediately consumed, if anyone is waiting on them.

Also available in: Atom PDF