diff options
author | José Bollo <jose.bollo@iot.bzh> | 2017-08-30 18:25:42 +0200 |
---|---|---|
committer | José Bollo <jose.bollo@iot.bzh> | 2017-08-30 18:25:42 +0200 |
commit | 4c55ef0515cd2c04616c445823224517d36119b4 (patch) | |
tree | 57b7d56d6abd367039e6f74ce64b5a1cc2c211f1 | |
parent | a221b08b008c3e3e63dccdbccbcdb7fe8aeb3481 (diff) |
jobs: fix starve
Signed-off-by: José Bollo <jose.bollo@iot.bzh>
-rw-r--r-- | src/jobs.c | 46 |
1 files changed, 33 insertions, 13 deletions
@@ -64,6 +64,7 @@ struct events struct events *next; struct sd_event *event; uint64_t timeout; + unsigned used: 1; unsigned runs: 1; }; @@ -203,7 +204,7 @@ static inline struct job *job_get() static inline struct events *events_get() { struct events *events = first_events; - while (events && events->runs) + while (events && events->used) events = events->next; return events; } @@ -285,7 +286,7 @@ static void events_call(int signum, void *arg) */ static void thread_run(volatile struct thread *me) { - struct thread **prv; + struct thread **prv, *thr; struct job *job; struct events *events; uint64_t evto; @@ -330,13 +331,16 @@ static void thread_run(volatile struct thread *me) /* release event if any */ events = me->events; if (events) { - events->runs = 0; + events->used = 0; me->events = NULL; } } else { /* no job, check events */ - events = events_get(); - if (events) { + thr = (struct thread*)me; + events = NULL; + while (thr && !(events = thr->events)) + thr = thr->upper; + if (events && !events->runs) { /* run the events */ events->runs = 1; events->timeout = evto; @@ -347,12 +351,28 @@ static void thread_run(volatile struct thread *me) events->runs = 0; me->events = NULL; } else { - /* no job and not events */ - waiting++; - me->waits = 1; - pthread_cond_wait(&cond, &mutex); - me->waits = 0; - waiting--; + /* no owned event, check events */ + events = events_get(); + if (events) { + /* run the events */ + events->used = 1; + events->runs = 1; + events->timeout = evto; + me->events = events; + pthread_mutex_unlock(&mutex); + sig_monitor(0, events_call, events); + pthread_mutex_lock(&mutex); + events->used = 0; + events->runs = 0; + me->events = NULL; + } else { + /* no job and not events */ + waiting++; + me->waits = 1; + pthread_cond_wait(&cond, &mutex); + me->waits = 0; + waiting--; + } } } } @@ -644,6 +664,7 @@ struct sd_event *jobs_get_sd_event() events = malloc(sizeof *events); if (events && (rc = sd_event_new(&events->event)) >= 0) { if (nevents < started || start_one_thread() >= 0) { + events->used = 0; events->runs = 0; events->next = first_events; first_events = events; @@ -667,10 +688,9 @@ struct sd_event *jobs_get_sd_event() } } if (events) { - /* */ me = current; if (me) { - events->runs = 1; + events->used = 1; me->events = events; } else { WARNING("event returned for unknown thread!"); |