X-Git-Url: https://gerrit.automotivelinux.org/gerrit/gitweb?a=blobdiff_plain;f=src%2Fjobs.c;h=4b4472e54c0d801db1383d6d00202c209c1d5837;hb=4c7b7d3adcc10fbcf64d790a4e7c194ff3d5c6de;hp=464f1e11e76322b3e8e8a6299771715d4c8e5e95;hpb=48ecf6eed5091bdb4788da0112870e79d58baf19;p=src%2Fapp-framework-binder.git diff --git a/src/jobs.c b/src/jobs.c index 464f1e11..4b4472e5 100644 --- a/src/jobs.c +++ b/src/jobs.c @@ -29,6 +29,9 @@ #include #include +#ifndef NO_JOBS_WATCHDOG +#include +#endif #include "jobs.h" #include "sig-monitor.h" @@ -282,7 +285,7 @@ static void evloop_run(int signum, void *arg) ERROR("sd_event_wait returned an error (state: %d): %m", sd_event_get_state(se)); } } - el->state &= ~(EVLOOP_STATE_WAIT); + __atomic_and_fetch(&el->state, ~(EVLOOP_STATE_WAIT), __ATOMIC_RELAXED); if (rc > 0) { rc = sd_event_dispatch(se); @@ -293,7 +296,7 @@ static void evloop_run(int signum, void *arg) } } } - el->state &= ~(EVLOOP_STATE_WAIT|EVLOOP_STATE_RUN); + __atomic_and_fetch(&el->state, ~(EVLOOP_STATE_WAIT|EVLOOP_STATE_RUN), __ATOMIC_RELAXED); } @@ -326,8 +329,8 @@ static void thread_run(volatile struct thread *me) /* loop until stopped */ while (!me->stop) { /* release the event loop */ - if (current_evloop && !(current_evloop->state & EVLOOP_STATE_RUN)) { - current_evloop->state -= EVLOOP_STATE_LOCK; + if (current_evloop) { + __atomic_sub_fetch(¤t_evloop->state, EVLOOP_STATE_LOCK, __ATOMIC_RELAXED); current_evloop = NULL; } @@ -349,9 +352,9 @@ static void thread_run(volatile struct thread *me) } else { /* no job, check events */ el = &evloop[0]; - if (el->sdev && !el->state) { + if (el->sdev && !__atomic_load_n(&el->state, __ATOMIC_RELAXED)) { /* run the events */ - el->state = EVLOOP_STATE_LOCK|EVLOOP_STATE_RUN|EVLOOP_STATE_WAIT; + __atomic_store_n(&el->state, EVLOOP_STATE_LOCK|EVLOOP_STATE_RUN|EVLOOP_STATE_WAIT, __ATOMIC_RELAXED); current_evloop = el; pthread_mutex_unlock(&mutex); sig_monitor(0, evloop_run, el); @@ -369,6 +372,12 @@ static void thread_run(volatile struct thread *me) } } + /* release the event loop */ + if (current_evloop) { + __atomic_sub_fetch(¤t_evloop->state, EVLOOP_STATE_LOCK, __ATOMIC_RELAXED); + current_evloop = NULL; + } + /* unlink the current thread and cleanup */ prv = &threads; while (*prv != me) @@ -636,7 +645,9 @@ static int on_evloop_efd(sd_event_source *s, int fd, uint32_t revents, void *use uint64_t x; struct evloop *evloop = userdata; read(evloop->efd, &x, sizeof x); - pthread_cond_signal(&evloop->cond); + pthread_mutex_lock(&mutex); + pthread_cond_broadcast(&evloop->cond); + pthread_mutex_unlock(&mutex); return 1; } @@ -644,19 +655,19 @@ static int on_evloop_efd(sd_event_source *s, int fd, uint32_t revents, void *use * Gets a sd_event item for the current thread. * @return a sd_event or NULL in case of error */ -struct sd_event *jobs_get_sd_event() +static struct sd_event *get_sd_event_locked() { struct evloop *el; uint64_t x; int rc; - pthread_mutex_lock(&mutex); - /* creates the evloop on need */ el = &evloop[0]; if (!el->sdev) { + /* start the creation */ + el->state = 0; /* creates the eventfd for waking up polls */ - el->efd = eventfd(0, EFD_CLOEXEC|EFD_SEMAPHORE); + el->efd = eventfd(0, EFD_CLOEXEC); if (el->efd < 0) { ERROR("can't make eventfd for events"); goto error1; @@ -676,32 +687,43 @@ struct sd_event *jobs_get_sd_event() error2: close(el->efd); error1: - pthread_mutex_unlock(&mutex); return NULL; } - /* terminate creation */ - el->state = 0; } /* attach the event loop to the current thread */ if (current_evloop != el) { if (current_evloop) - current_evloop->state -= EVLOOP_STATE_LOCK; + __atomic_sub_fetch(¤t_evloop->state, EVLOOP_STATE_LOCK, __ATOMIC_RELAXED); current_evloop = el; - el->state += EVLOOP_STATE_LOCK; + __atomic_add_fetch(&el->state, EVLOOP_STATE_LOCK, __ATOMIC_RELAXED); } /* wait for a modifiable event loop */ - while (el->state & EVLOOP_STATE_WAIT) { + while (__atomic_load_n(&el->state, __ATOMIC_RELAXED) & EVLOOP_STATE_WAIT) { x = 1; write(el->efd, &x, sizeof x); pthread_cond_wait(&el->cond, &mutex); } - pthread_mutex_unlock(&mutex); return el->sdev; } +/** + * Gets a sd_event item for the current thread. + * @return a sd_event or NULL in case of error + */ +struct sd_event *jobs_get_sd_event() +{ + struct sd_event *result; + + pthread_mutex_lock(&mutex); + result = get_sd_event_locked(); + pthread_mutex_unlock(&mutex); + + return result; +} + /** * Enter the jobs processing loop. * @param allowed_count Maximum count of thread for jobs including this one @@ -743,6 +765,12 @@ int jobs_start(int allowed_count, int start_count, int waiter_count, void (*star running = 0; remains = waiter_count; +#ifndef NO_JOBS_WATCHDOG + /* set the watchdog */ + if (sd_watchdog_enabled(0, NULL)) + sd_event_set_watchdog(get_sd_event_locked(), 1); +#endif + /* start at least one thread */ launched = 0; while ((launched + 1) < start_count) {