Changeset dba056b in mainline
- Timestamp:
- 2019-08-06T19:23:56Z (5 years ago)
- 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)
- Location:
- uspace/srv/sysman
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/sysman/job.c
r3f05ef7 rdba056b 80 80 assert(job); 81 81 assert(u); 82 assert(u->job == NULL);83 82 memset(job, 0, sizeof(*job)); 84 83 … … 178 177 } 179 178 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 */ 185 static 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 */ 196 static 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 180 203 /** Merge two jobs together 181 204 * … … 212 235 trunk->blocked_jobs_count = other->blocked_jobs.size; 213 236 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); 215 242 int rc = sysman_move_observers(other, trunk); 216 243 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); 217 248 } 218 249 … … 233 264 } 234 265 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 */ 235 274 int job_queue_add_closure(dyn_array_t *closure) 236 275 { … … 307 346 308 347 unit_t *u = job->unit; 309 assert(u->bfs_job != NULL);310 348 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) */ 315 353 job->state = JOB_PENDING; 316 /* We pass reference from the closure to the queue */354 job_add_ref(job); 317 355 list_append(&job->job_queue, &job_queue); 318 356 } 357 358 /* We've stolen references from the closure, so erase it */ 359 dyn_array_clear(closure); 319 360 320 361 return EOK; … … 347 388 /* Check invariant */ 348 389 list_foreach(units, units, unit_t, u) { 349 assert(u->bfs_job == false);390 assert(u->bfs_job == NULL); 350 391 } 351 392 … … 390 431 } 391 432 } 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 } 396 438 rc = EOK; 397 439 … … 402 444 job_del_ref(&u->bfs_job); 403 445 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; 404 453 } 405 454 … … 514 563 assert(job->state != JOB_FINISHED); 515 564 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)); 520 570 521 571 job->state = JOB_FINISHED; … … 528 578 dyn_array_clear(&job->blocked_jobs); 529 579 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 } 535 587 sysman_raise_event(&sysman_event_job_finished, job); 536 588 } -
uspace/srv/sysman/sysman.c
r3f05ef7 rdba056b 196 196 /** Create and queue job for unit 197 197 * 198 * If unit already has the same job assigned callback is setto it.198 * If unit already has the same job assigned callback is moved to it. 199 199 * 200 200 * @param[in] callback (optional) callback must explicitly delete reference … … 213 213 if (callback != NULL) { 214 214 job_add_ref(job); 215 //TODO sysman_object_observer is not fibril-safe CANNOT BE CALLED HERE! 215 216 sysman_object_observer(job, callback, callback_arg); 216 217 } … … 328 329 } 329 330 331 size_t sysman_observers_count(void *object) 332 { 333 ht_link_t *ht_link = hash_table_find(&observed_objects, &object); 334 335 if (ht_link == NULL) { 336 return 0; 337 } 338 339 observed_object_t *observed_object = 340 hash_table_get_inst(ht_link, observed_object_t, ht_link); 341 342 return list_count(&observed_object->callbacks); 343 } 344 330 345 331 346 /* … … 355 370 goto fail; 356 371 } 372 357 373 /* We don't need job anymore */ 358 374 job_del_ref(&job); -
uspace/srv/sysman/sysman.h
r3f05ef7 rdba056b 45 45 extern int sysman_object_observer(void *, callback_handler_t, void *); 46 46 extern int sysman_move_observers(void *, void *); 47 extern size_t sysman_observers_count(void *); 47 48 48 49 -
uspace/srv/sysman/test/job_queue.c
r3f05ef7 rdba056b 152 152 } 153 153 154 PCUT_TEST(merge_jobs_with_callback) { 155 /* Setup mock behavior */ 156 unit_type_vmts[UNIT_SERVICE]->start = &mock_unit_vmt_start_async; 157 unit_type_vmts[UNIT_SERVICE]->exposee_created = 158 &mock_unit_vmt_exposee_created; 159 160 /* Define mock units */ 161 unit_t *s0 = mock_units[UNIT_SERVICE][0]; 162 163 /* Create and start first job */ 164 job_t *j0 = NULL; 165 int rc = sysman_run_job(s0, STATE_STARTED, &job_finished_cb, &j0); 166 PCUT_ASSERT_INT_EQUALS(EOK, rc); 167 168 sysman_process_queue(); 169 /* Job not finished */ 170 PCUT_ASSERT_NULL(j0); 171 172 173 /* 174 * While s0 is starting in j0, create second job that should be merged 175 * into the existing one. 176 */ 177 job_t *j1 = NULL; 178 rc = sysman_run_job(s0, STATE_STARTED, &job_finished_cb, &j1); 179 PCUT_ASSERT_INT_EQUALS(EOK, rc); 180 181 sysman_process_queue(); 182 /* Job not finished */ 183 PCUT_ASSERT_NULL(j1); 184 185 sysman_raise_event(&sysman_event_unit_exposee_created, s0); 186 sysman_process_queue(); 187 188 PCUT_ASSERT_NOT_NULL(j0); 189 PCUT_ASSERT_NOT_NULL(j1); 190 191 /* 192 * Jobs were, merged so both callbacks should have been called with the 193 * same job 194 */ 195 PCUT_ASSERT_EQUALS(j0, j1); 196 197 /* And there should be exactly two references (per each callback) */ 198 job_del_ref(&j0); 199 job_del_ref(&j0); 200 201 PCUT_ASSERT_NULL(j0); 202 } 203 154 204 155 205 PCUT_EXPORT(job_queue); -
uspace/srv/sysman/units/unit_svc.c
r3f05ef7 rdba056b 100 100 * in a moment. Applies to naming service only. 101 101 */ 102 // TODO this is even hack in the workaround, exposees doesn't work properly 103 if (true || str_cmp(unit->name, "devman.svc") == 0 || 102 if (str_cmp(unit->name, "devman.svc") == 0 || 104 103 str_cmp(unit->name, "logger.svc") == 0 || 105 104 str_cmp(unit->name, "irc.svc") == 0) {
Note:
See TracChangeset
for help on using the changeset viewer.