Changeset dda2602 in mainline for uspace/srv/sysman/job.c


Ignore:
Timestamp:
2019-08-03T09:41:07Z (5 years ago)
Author:
Matthieu Riolo <matthieu.riolo@…>
Children:
dd5c623
Parents:
c0e4fc50
git-author:
Michal Koutný <xm.koutny+hos@…> (2015-05-08 11:10:06)
git-committer:
Matthieu Riolo <matthieu.riolo@…> (2019-08-03 09:41:07)
Message:

sysman: Create units to start up to compositor

  • add necessary units to support basic GUI (barber, vterm)
  • lacking autostart is compensated with explicit dependencies
  • IPC_FLAG_AUTOSTART in compositor and locsrv fix
  • paths to v* binaries
  • refactored job closure creation

Conflicts:

boot/Makefile.common
uspace/app/vlaunch/vlaunch.c
uspace/srv/hid/compositor/compositor.c
uspace/srv/locsrv/locsrv.c

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/srv/sysman/job.c

    rc0e4fc50 rdda2602  
    2727 */
    2828
    29 #include <adt/fifo.h>
     29#include <adt/list.h>
    3030#include <assert.h>
    3131#include <errno.h>
    32 
     32#include <stdlib.h>
     33
     34#include "configuration.h"
    3335#include "dep.h"
    3436#include "job.h"
     
    4244 */
    4345
    44 static int job_add_blocked_job(job_t *job, job_t *blocked_job)
    45 {
    46         int rc = dyn_array_append(&job->blocked_jobs, job_ptr_t, blocked_job);
     46static int job_add_blocked_job(job_t *blocking_job, job_t *blocked_job)
     47{
     48        int rc = dyn_array_append(&blocking_job->blocked_jobs, job_ptr_t,
     49            blocked_job);
    4750        if (rc != EOK) {
    4851                return ENOMEM;
     
    7376        assert(job);
    7477        assert(u);
     78        assert(u->job == NULL);
    7579        memset(job, 0, sizeof(*job));
    7680
     
    8286        job->unit = u;
    8387
    84         dyn_array_initialize(&job->blocked_jobs, job_ptr_t, 0);
     88        u->job = job;
     89        job_add_ref(job);
     90
     91        (void)dyn_array_initialize(&job->blocked_jobs, job_ptr_t, 0);
    8592        job->blocking_jobs = 0;
    8693        job->blocking_job_failed = false;
     
    225232int job_create_closure(job_t *main_job, dyn_array_t *job_closure)
    226233{
    227         // TODO replace hard-coded FIFO size with resizable FIFO
    228         FIFO_INITIALIZE_DYNAMIC(jobs_fifo, job_ptr_t, 10);
    229         void *fifo_data = fifo_create(jobs_fifo);
    230234        int rc;
    231         if (fifo_data == NULL) {
    232                 rc = ENOMEM;
    233                 goto finish;
    234         }
    235 
    236         /*
    237          * Traverse dependency graph in BFS fashion and create jobs for every
    238          * necessary unit.
    239          * Closure keeps reference to each job. We've to add reference to the
    240          * main job, other newly created jobs are pased to the closure.
    241          */
    242         fifo_push(jobs_fifo, main_job);
    243         job_add_ref(main_job);
    244         while (jobs_fifo.head != jobs_fifo.tail) {
    245                 job_t *job = fifo_pop(jobs_fifo);
     235        list_t units_fifo;
     236        list_initialize(&units_fifo);
     237
     238        /* Zero BFS tags before use */
     239        list_foreach(units, units, unit_t, u) {
     240                u->bfs_tag = false;
     241        }
    246242               
     243        unit_t *unit = main_job->unit;
     244        list_append(&unit->bfs_link, &units_fifo);
     245        unit->bfs_tag = true;
     246       
     247        while (!list_empty(&units_fifo)) {
     248                unit = list_get_instance(list_first(&units_fifo), unit_t,
     249                    bfs_link);
     250                assert(unit->job);
     251                list_remove(&unit->bfs_link);
     252                job_t *job = unit->job;
     253
     254
    247255                // TODO more sophisticated check? (unit that is in transitional
    248256                //      state cannot have currently multiple jobs queued)
    249                 if (job->target_state == job->unit->state) {
     257                if (job->target_state == unit->state) {
    250258                        /*
    251259                         * Job would do nothing, finish it on spot.
     
    254262                        job->retval = JOB_OK;
    255263                        job_finish(job);
    256                         job_del_ref(&job);
    257264                        continue;
    258                 } else {
    259                         /* No refcount increase, pass it to the closure */
    260                         dyn_array_append(job_closure, job_ptr_t, job);
    261265                }
    262266
    263                 /* Traverse dependencies edges */
    264                 unit_t *u = job->unit;
    265                 list_foreach(u->dependencies, dependencies, unit_dependency_t, dep) {
    266                         // TODO prepare for reverse edge direction and
    267                         //      non-identity state mapping
    268                         job_t *new_job =
    269                             job_create(dep->dependency, job->target_state);
    270                         if (new_job == NULL) {
    271                                 rc = ENOMEM;
    272                                 goto finish;
     267                job_add_ref(job);
     268                dyn_array_append(job_closure, job_ptr_t, job);
     269
     270                /*
     271                 * Traverse dependencies edges
     272                 * Depending on dependency type and edge direction create
     273                 * appropriate jobs.
     274                 */
     275                list_foreach(unit->dependencies, dependencies, unit_dependency_t, dep) {
     276                        unit_t *u = dep->dependency;
     277                        job_t *blocking_job;
     278                        if (u->bfs_tag) {
     279                                assert(u->job);
     280                                blocking_job = u->job;
     281                        } else {
     282                                u->bfs_tag = true;
     283                                blocking_job = job_create(u, job->target_state);
     284                                if (blocking_job == NULL) {
     285                                        rc = ENOMEM;
     286                                        goto finish;
     287                                }
     288                                /* Reference to job is kept in unit */
     289                                job_del_ref(&blocking_job);
     290                                list_append(&u->bfs_link, &units_fifo);
    273291                        }
    274                         job_add_blocked_job(new_job, job);
    275                         fifo_push(jobs_fifo, new_job);
     292                       
     293                        job_add_blocked_job(blocking_job, job);
    276294                }
    277295        }
     296        sysman_log(LVL_DEBUG2, "%s(%s):", __func__, unit_name(main_job->unit));
     297        dyn_array_foreach(*job_closure, job_ptr_t, job_it) {
     298                sysman_log(LVL_DEBUG2, "%s\t%s", __func__, unit_name((*job_it)->unit));
     299        }
    278300        rc = EOK;
    279301
    280302finish:
    281         free(fifo_data);
    282         /*
    283          * Newly created jobs are already passed to the closure, thus not
    284          * deleting reference to them here.
    285          */
     303        /* Any unprocessed jobs may be referenced by units */
     304        list_foreach(units_fifo, bfs_link, unit_t, u) {
     305                job_del_ref(&u->job);
     306        }
    286307        return rc;
    287308}
    288309
     310/** Create job assigned to the unit
     311 *
     312 * @param[in]  unit          unit to be modified, its job must be empty
     313 * @param[in]  target_state
     314 *
     315 * @return NULL or newly created job
     316 *         There are two references to the job, one set in the unit and second
     317 *         is the return value.
     318 */
    289319job_t *job_create(unit_t *u, unit_state_t target_state)
    290320{
     
    293323                job_init(job, u, target_state);
    294324
    295                 /* Start with one reference for the creator */
     325                /* Add one reference for the creator */
    296326                job_add_ref(job);
    297327        }
     
    354384        }
    355385        if (rc != EOK) {
     386                sysman_log(LVL_DEBUG, "%s(%p), %s -> %i, error: %i",
     387                    __func__, job, unit_name(u), job->target_state, rc);
    356388                goto fail;
    357389        }
     
    378410        assert(job->state != JOB_FINISHED);
    379411        assert(job->retval != JOB_UNDEFINED_);
     412        assert(job->unit->job == job);
    380413
    381414        sysman_log(LVL_DEBUG2, "%s(%p) %s -> %i",
     
    390423        dyn_array_clear(&job->blocked_jobs);
    391424
    392         /* Add reference for the event */
    393         job_add_ref(job);
     425        /*
     426         * Remove job from unit and pass the reference from the unit to the
     427         * event.
     428         */
     429        job->unit->job = NULL;
    394430        sysman_raise_event(&sysman_event_job_finished, job);
    395431}
Note: See TracChangeset for help on using the changeset viewer.