Changeset dda2602 in mainline for uspace/srv/sysman/job.c
- Timestamp:
- 2019-08-03T09:41:07Z (5 years ago)
- 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)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/sysman/job.c
rc0e4fc50 rdda2602 27 27 */ 28 28 29 #include <adt/ fifo.h>29 #include <adt/list.h> 30 30 #include <assert.h> 31 31 #include <errno.h> 32 32 #include <stdlib.h> 33 34 #include "configuration.h" 33 35 #include "dep.h" 34 36 #include "job.h" … … 42 44 */ 43 45 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); 46 static 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); 47 50 if (rc != EOK) { 48 51 return ENOMEM; … … 73 76 assert(job); 74 77 assert(u); 78 assert(u->job == NULL); 75 79 memset(job, 0, sizeof(*job)); 76 80 … … 82 86 job->unit = u; 83 87 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); 85 92 job->blocking_jobs = 0; 86 93 job->blocking_job_failed = false; … … 225 232 int job_create_closure(job_t *main_job, dyn_array_t *job_closure) 226 233 { 227 // TODO replace hard-coded FIFO size with resizable FIFO228 FIFO_INITIALIZE_DYNAMIC(jobs_fifo, job_ptr_t, 10);229 void *fifo_data = fifo_create(jobs_fifo);230 234 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 } 246 242 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 247 255 // TODO more sophisticated check? (unit that is in transitional 248 256 // state cannot have currently multiple jobs queued) 249 if (job->target_state == job->unit->state) {257 if (job->target_state == unit->state) { 250 258 /* 251 259 * Job would do nothing, finish it on spot. … … 254 262 job->retval = JOB_OK; 255 263 job_finish(job); 256 job_del_ref(&job);257 264 continue; 258 } else {259 /* No refcount increase, pass it to the closure */260 dyn_array_append(job_closure, job_ptr_t, job);261 265 } 262 266 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); 273 291 } 274 job_add_blocked_job(new_job, job);275 fifo_push(jobs_fifo, new_job);292 293 job_add_blocked_job(blocking_job, job); 276 294 } 277 295 } 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 } 278 300 rc = EOK; 279 301 280 302 finish: 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 } 286 307 return rc; 287 308 } 288 309 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 */ 289 319 job_t *job_create(unit_t *u, unit_state_t target_state) 290 320 { … … 293 323 job_init(job, u, target_state); 294 324 295 /* Start withone reference for the creator */325 /* Add one reference for the creator */ 296 326 job_add_ref(job); 297 327 } … … 354 384 } 355 385 if (rc != EOK) { 386 sysman_log(LVL_DEBUG, "%s(%p), %s -> %i, error: %i", 387 __func__, job, unit_name(u), job->target_state, rc); 356 388 goto fail; 357 389 } … … 378 410 assert(job->state != JOB_FINISHED); 379 411 assert(job->retval != JOB_UNDEFINED_); 412 assert(job->unit->job == job); 380 413 381 414 sysman_log(LVL_DEBUG2, "%s(%p) %s -> %i", … … 390 423 dyn_array_clear(&job->blocked_jobs); 391 424 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; 394 430 sysman_raise_event(&sysman_event_job_finished, job); 395 431 }
Note:
See TracChangeset
for help on using the changeset viewer.