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


Ignore:
Timestamp:
2019-08-06T19:23:56Z (6 years ago)
Author:
Matthieu Riolo <matthieu.riolo@…>
Children:
c6d87c10
Parents:
3f05ef7
git-author:
Michal Koutný <xm.koutny+hos@…> (2015-06-20 01:04:31)
git-committer:
Matthieu Riolo <matthieu.riolo@…> (2019-08-06 19:23:56)
Message:

sysman: Using exposees to detect asynchronous start

  • also fixed bug with reference counting of merged jobs
  • add test for the faulty behavior
File:
1 edited

Legend:

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

    r3f05ef7 rdba056b  
    8080        assert(job);
    8181        assert(u);
    82         assert(u->job == NULL);
    8382        memset(job, 0, sizeof(*job));
    8483
     
    178177}
    179178
     179/** Add multiple references to job
     180 *
     181 * Non-atomicity doesn't mind as long as individual increments are atomic.
     182 *
     183 * @note Function is not exported as other modules shouldn't need it.
     184 */
     185static inline void job_add_refs(job_t *job, size_t refs)
     186{
     187        for (size_t i = 0; i < refs; ++i) {
     188                job_add_ref(job);
     189        }
     190}
     191
     192/** Delete multiple references to job
     193 *
     194 * Behavior of concurrent runs with job_add_refs aren't specified.
     195 */
     196static inline void job_del_refs(job_t **job_ptr, size_t refs)
     197{
     198        for (size_t i = 0; i < refs; ++i) {
     199                job_del_ref(job_ptr);
     200        }
     201}
     202
    180203/** Merge two jobs together
    181204 *
     
    212235        trunk->blocked_jobs_count = other->blocked_jobs.size;
    213236
    214         /* All allocation is done in job_pre_merge, cannot fail here. */
     237        /*
     238         * Note, the sysman_move_observers cannot fail here sice all necessary
     239         * allocation is done in job_pre_merge.
     240         */
     241        size_t observers_refs = sysman_observers_count(other);
    215242        int rc = sysman_move_observers(other, trunk);
    216243        assert(rc == EOK);
     244
     245        /* When we move observers, don't forget to pass their references too. */
     246        job_add_refs(trunk, observers_refs);
     247        job_del_refs(&other, observers_refs);
    217248}
    218249
     
    233264}
    234265
     266/** Consistenly add jobs to the queue
     267 *
     268 * @param[in/out]  closure    jobs closure, on success it's emptied, otherwise
     269 *                            you should take care of remaining jobs
     270 *
     271 * @return EOK on success
     272 * @return EBUSY when any job in closure is conflicting
     273 */
    235274int job_queue_add_closure(dyn_array_t *closure)
    236275{
     
    307346
    308347                unit_t *u = job->unit;
    309                 assert(u->bfs_job != NULL);
    310348                assert(u->job == NULL);
    311                 u->job = u->bfs_job;
    312                 u->bfs_job = NULL;
    313 
    314 
     349                /* Pass reference from the closure to the unit */
     350                u->job = job;
     351
     352                /* Enqueue job (new reference) */
    315353                job->state = JOB_PENDING;
    316                 /* We pass reference from the closure to the queue */
     354                job_add_ref(job);
    317355                list_append(&job->job_queue, &job_queue);
    318356        }
     357
     358        /* We've stolen references from the closure, so erase it */
     359        dyn_array_clear(closure);
    319360
    320361        return EOK;
     
    347388        /* Check invariant */
    348389        list_foreach(units, units, unit_t, u) {
    349                 assert(u->bfs_job == false);
     390                assert(u->bfs_job == NULL);
    350391        }
    351392               
     
    390431                }
    391432        }
    392 //      sysman_log(LVL_DEBUG2, "%s(%s):", __func__, unit_name(main_job->unit));
    393 //      dyn_array_foreach(*job_closure, job_t *, job_it) {
    394 //              sysman_log(LVL_DEBUG2, "%s\t%s", __func__, unit_name((*job_it)->unit));
    395 //      }
     433        sysman_log(LVL_DEBUG2, "%s(%s):", __func__, unit_name(main_job->unit));
     434        dyn_array_foreach(*job_closure, job_t *, job_it) {
     435                sysman_log(LVL_DEBUG2, "%s\t%s, refs: %u", __func__,
     436                    unit_name((*job_it)->unit), atomic_get(&(*job_it)->refcnt));
     437        }
    396438        rc = EOK;
    397439
     
    402444                job_del_ref(&u->bfs_job);
    403445                list_remove(cur_link);
     446        }
     447       
     448        /* Clean after ourselves (BFS tag jobs) */
     449        dyn_array_foreach(*job_closure, job_t *, job_it) {
     450                assert(*job_it == (*job_it)->unit->bfs_job);
     451                job_del_ref(&(*job_it)->unit->bfs_job);
     452                (*job_it)->unit->bfs_job = NULL;
    404453        }
    405454
     
    514563        assert(job->state != JOB_FINISHED);
    515564        assert(job->retval != JOB_UNDEFINED_);
    516         assert(job->unit->job == job);
    517 
    518         sysman_log(LVL_DEBUG2, "%s(%p) %s ret %i",
    519             __func__, job, unit_name(job->unit), job->retval);
     565        assert(!job->unit->job || job->unit->job == job);
     566
     567        sysman_log(LVL_DEBUG2, "%s(%p) %s ret %i, ref %i",
     568            __func__, job, unit_name(job->unit), job->retval,
     569            atomic_get(&job->refcnt));
    520570
    521571        job->state = JOB_FINISHED;
     
    528578        dyn_array_clear(&job->blocked_jobs);
    529579
    530         /*
    531          * Remove job from unit and pass the reference from the unit to the
    532          * event.
    533          */
    534         job->unit->job = NULL;
     580        /* Add reference for event handler */
     581        if (job->unit->job == NULL) {
     582                job_add_ref(job);
     583        } else {
     584                /* Pass reference from unit */
     585                job->unit->job = NULL;
     586        }
    535587        sysman_raise_event(&sysman_event_job_finished, job);
    536588}
Note: See TracChangeset for help on using the changeset viewer.