X-Git-Url: https://gerrit.automotivelinux.org/gerrit/gitweb?a=blobdiff_plain;f=src%2Fjobs.c;h=b7d161120b250c7647fe481ac41c814ff253d821;hb=7ffecab08bf91e26ffedb393d9b8cb6151e2b836;hp=e3aa5c99db6f9d25ab300b55cd51aca8b3731b38;hpb=4c55ef0515cd2c04616c445823224517d36119b4;p=src%2Fapp-framework-binder.git diff --git a/src/jobs.c b/src/jobs.c index e3aa5c99..b7d16112 100644 --- a/src/jobs.c +++ b/src/jobs.c @@ -50,7 +50,7 @@ typedef void (*job_cb_t)(int, void*); struct job { struct job *next; /**< link to the next job enqueued */ - void *group; /**< group of the request */ + const void *group; /**< group of the request */ job_cb_t callback; /**< processing callback */ void *arg; /**< argument */ int timeout; /**< timeout in second for processing the request */ @@ -64,8 +64,11 @@ struct events struct events *next; struct sd_event *event; uint64_t timeout; - unsigned used: 1; - unsigned runs: 1; + enum { + Available, + Modifiable, + Locked + } state; }; /** Description of threads */ @@ -74,10 +77,8 @@ struct thread struct thread *next; /**< next thread of the list */ struct thread *upper; /**< upper same thread */ struct job *job; /**< currently processed job */ - struct events *events; /**< currently processed job */ pthread_t tid; /**< the thread id */ unsigned stop: 1; /**< stop requested */ - unsigned lowered: 1; /**< has a lower same thread */ unsigned waits: 1; /**< is waiting? */ }; @@ -109,7 +110,8 @@ static int nevents = 0; /** count of events */ /* list of threads */ static struct thread *threads; -static _Thread_local struct thread *current; +static _Thread_local struct thread *current_thread; +static _Thread_local struct events *current_events; /* queue of pending jobs */ static struct job *first_job; @@ -125,7 +127,7 @@ static struct job *free_jobs; * @return the created job unblock or NULL when no more memory */ static struct job *job_create( - void *group, + const void *group, int timeout, job_cb_t callback, void *arg) @@ -164,7 +166,7 @@ end: */ static void job_add(struct job *job) { - void *group; + const void *group; struct job *ijob, **pjob; /* prepare to add */ @@ -204,7 +206,7 @@ static inline struct job *job_get() static inline struct events *events_get() { struct events *events = first_events; - while (events && events->used) + while (events && events->state != Available) events = events->next; return events; } @@ -218,7 +220,7 @@ static inline struct events *events_get() static inline void job_release(struct job *job) { struct job *ijob, **pjob; - void *group; + const void *group; /* first unqueue the job */ pjob = &first_job; @@ -272,9 +274,34 @@ static void job_cancel(int signum, void *arg) */ static void events_call(int signum, void *arg) { + int rc; + struct sd_event *se; struct events *events = arg; - if (!signum) - sd_event_run(events->event, events->timeout); + + if (!signum) { + se = events->event; + rc = sd_event_prepare(se); + if (rc < 0) { + errno = -rc; + ERROR("sd_event_prepare returned an error (state: %d): %m", sd_event_get_state(events->event)); + } else { + if (rc == 0) { + rc = sd_event_wait(se, events->timeout); + if (rc < 0) { + errno = -rc; + ERROR("sd_event_wait returned an error (state: %d): %m", sd_event_get_state(events->event)); + } + } + + if (rc > 0) { + rc = sd_event_dispatch(se); + if (rc < 0) { + errno = -rc; + ERROR("sd_event_dispatch returned an error (state: %d): %m", sd_event_get_state(events->event)); + } + } + } + } } /** @@ -286,7 +313,7 @@ static void events_call(int signum, void *arg) */ static void thread_run(volatile struct thread *me) { - struct thread **prv, *thr; + struct thread **prv; struct job *job; struct events *events; uint64_t evto; @@ -294,11 +321,9 @@ static void thread_run(volatile struct thread *me) /* initialize description of itself and link it in the list */ me->tid = pthread_self(); me->stop = 0; - me->lowered = 0; me->waits = 0; - me->upper = current; - if (current) { - current->lowered = 1; + me->upper = current_thread; + if (current_thread) { evto = EVENT_TIMEOUT_CHILD; } else { started++; @@ -307,10 +332,9 @@ static void thread_run(volatile struct thread *me) } me->next = threads; threads = (struct thread*)me; - current = (struct thread*)me; + current_thread = (struct thread*)me; /* loop until stopped */ - me->events = NULL; while (!me->stop) { /* get a job */ job = job_get(first_job); @@ -325,54 +349,39 @@ static void thread_run(volatile struct thread *me) sig_monitor(job->timeout, job->callback, job->arg); pthread_mutex_lock(&mutex); - /* release the run job */ - job_release(job); - /* release event if any */ - events = me->events; - if (events) { - events->used = 0; - me->events = NULL; + events = current_events; + if (events && events->state == Modifiable) { + current_events = NULL; + events->state = Available; } + + /* release the run job */ + job_release(job); } else { /* no job, check events */ - thr = (struct thread*)me; - events = NULL; - while (thr && !(events = thr->events)) - thr = thr->upper; - if (events && !events->runs) { + events = current_events; + if (!events) + events = events_get(); + else if (events->state == Locked) + events = 0; + if (events) { /* run the events */ - events->runs = 1; + events->state = Locked; events->timeout = evto; - me->events = events; + current_events = events; pthread_mutex_unlock(&mutex); sig_monitor(0, events_call, events); pthread_mutex_lock(&mutex); - events->runs = 0; - me->events = NULL; + current_events = NULL; + events->state = Available; } else { - /* 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--; - } + /* no job and not events */ + waiting++; + me->waits = 1; + pthread_cond_wait(&cond, &mutex); + me->waits = 0; + waiting--; } } } @@ -382,10 +391,8 @@ static void thread_run(volatile struct thread *me) while (*prv != me) prv = &(*prv)->next; *prv = me->next; - current = me->upper; - if (current) { - current->lowered = 0; - } else { + current_thread = me->upper; + if (!current_thread) { sig_monitor_clean_timeouts(); started--; } @@ -442,7 +449,7 @@ static int start_one_thread() * @return 0 in case of success or -1 in case of error */ int jobs_queue( - void *group, + const void *group, int timeout, void (*callback)(int, void*), void *arg) @@ -524,7 +531,7 @@ static void call_cb(int signum, void *closure) * @see jobs_call, jobs_enter, jobs_leave */ static int do_sync( - void *group, + const void *group, int timeout, void (*sync_cb)(int signum, void *closure), struct sync *sync @@ -568,7 +575,7 @@ static int do_sync( * @return 0 on success or -1 in case of error */ int jobs_enter( - void *group, + const void *group, int timeout, void (*callback)(int signum, void *closure, struct jobloop *jobloop), void *closure @@ -620,7 +627,7 @@ int jobs_leave(struct jobloop *jobloop) * @return 0 in case of success or -1 in case of error */ int jobs_call( - void *group, + const void *group, int timeout, void (*callback)(int, void*), void *arg) @@ -640,19 +647,13 @@ int jobs_call( struct sd_event *jobs_get_sd_event() { struct events *events; - struct thread *me; int rc; pthread_mutex_lock(&mutex); /* search events on stack */ - me = current; - while (me && !me->events) - me = me->upper; - if (me) - /* return the stacked events */ - events = me->events; - else { + events = current_events; + if (!events) { /* search an available events */ events = events_get(); if (!events) { @@ -664,8 +665,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->state = Available; events->next = first_events; first_events = events; } else { @@ -683,18 +683,15 @@ struct sd_event *jobs_get_sd_event() ERROR("creation of sd_event failed: %m"); events = NULL; errno = -rc; - } + } } } } if (events) { - me = current; - if (me) { - events->used = 1; - me->events = events; - } else { + events->state = Modifiable; + if (!current_thread) WARNING("event returned for unknown thread!"); - } + current_events = events; } } pthread_mutex_unlock(&mutex); @@ -724,7 +721,7 @@ int jobs_start(int allowed_count, int start_count, int waiter_count, void (*star pthread_mutex_lock(&mutex); /* check whether already running */ - if (current || allowed) { + if (current_thread || allowed) { ERROR("thread already started"); errno = EINVAL; goto error; @@ -831,7 +828,7 @@ void jobs_terminate() head = job->next; /* search if job is stacked for current */ - t = current; + t = current_thread; while (t && t->job != job) t = t->upper; if (t) {