Changeset 8432ae1 in mainline
- Timestamp:
- 2019-08-03T08:33:31Z (5 years ago)
- Children:
- 4b1c6a4b
- Parents:
- 095d03c
- git-author:
- Michal Koutny <xm.koutny+hos@…> (2015-04-25 00:29:51)
- git-committer:
- Matthieu Riolo <matthieu.riolo@…> (2019-08-03 08:33:31)
- Location:
- uspace/srv/sysman
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/sysman/job.c
r095d03c r8432ae1 48 48 return ENOMEM; 49 49 } 50 51 50 job_add_ref(blocked_job); 51 52 52 blocked_job->blocking_jobs += 1; 53 53 54 54 return EOK; 55 } 56 57 /** Remove blocking_job from blocked job structure 58 * 59 * @note Caller must remove blocked_job from collection of blocked_jobs 60 */ 61 static void job_unblock(job_t *blocked_job, job_t *blocking_job) 62 { 63 if (blocking_job->retval == JOB_FAILED) { 64 blocked_job->blocking_job_failed = true; 65 } 66 blocked_job->blocking_jobs -= 1; 67 68 job_del_ref(&blocked_job); 55 69 } 56 70 … … 62 76 link_initialize(&job->job_queue); 63 77 64 /* Start with one reference for the creator */ 65 atomic_set(&job->refcnt, 1); 78 atomic_set(&job->refcnt, 0); 66 79 67 80 job->target_state = target_state; … … 100 113 job_t *job = data; 101 114 115 /* 116 * We have one reference from caller for our disposal, * 117 * if needed, pass it to observer. 118 */ 102 119 if (job_eval_retval(job)) { 103 120 job_finish(job); 121 job_del_ref(&job); 104 122 } else { 105 123 // TODO place for timeout 106 // TODO add reference to job?107 124 sysman_object_observer(u, &job_check, job); 108 125 } … … 110 127 111 128 112 static void job_unblock(job_t *blocked_job, job_t *blocking_job) 113 { 114 if (blocking_job->retval == JOB_FAILED) { 115 blocked_job->blocking_job_failed = true; 116 } 117 blocked_job->blocking_jobs -= 1; 118 } 129 119 130 120 131 static void job_destroy(job_t **job_ptr) … … 126 137 127 138 assert(!link_used(&job->job_queue)); 139 140 dyn_array_foreach(job->blocked_jobs, job_ptr_t, job_it) { 141 job_del_ref(&(*job_it)); 142 } 128 143 dyn_array_destroy(&job->blocked_jobs); 129 // TODO I should decrease referece of blocked jobs130 144 131 145 free(job); … … 164 178 (*job_it)->state = JOB_QUEUED; 165 179 list_append(&(*job_it)->job_queue, &job_queue); 166 // TODO explain this reference 167 job_add_ref(*job_it); 180 /* We pass reference from the closure to the queue */ 168 181 } 169 182 … … 203 216 204 217 if (result) { 205 / / TODO update refcount218 /* Remove job from queue and pass refernce to caller */ 206 219 list_remove(&result->job_queue); 207 220 result->state = JOB_DEQUEUED; … … 225 238 * Traverse dependency graph in BFS fashion and create jobs for every 226 239 * necessary unit. 240 * Closure keeps reference to each job. We've to add reference to the 241 * main job, other newly created jobs are pased to the closure. 227 242 */ 228 243 fifo_push(jobs_fifo, main_job); 229 244 job_t *job; 245 job_add_ref(main_job); 230 246 while ((job = fifo_pop(jobs_fifo)) != NULL) { 231 /* 232 * Do not increase reference count of job, as we're passing it 233 * to the closure. 234 */ 247 /* No refcount increase, pass it to the closure */ 235 248 dyn_array_append(job_closure, job_ptr_t, job); 236 249 … … 256 269 /* 257 270 * Newly created jobs are already passed to the closure, thus not 258 * deleting them here.271 * deleting reference to them here. 259 272 */ 260 273 return rc; … … 266 279 if (job != NULL) { 267 280 job_init(job, u, target_state); 281 282 /* Start with one reference for the creator */ 283 job_add_ref(job); 268 284 } 269 285 … … 271 287 } 272 288 289 /** Add one reference to job 290 * 291 * Usage: 292 * - adding observer which references the job, 293 * - raising and event that references the job, 294 * - anytime any other new reference is made. 295 */ 273 296 void job_add_ref(job_t *job) 274 297 { … … 276 299 } 277 300 301 /** Remove one reference from job, last remover destroys the job 302 * 303 * Usage: 304 * - inside observer callback that references the job, 305 * - inside event handler that references the job, 306 * - anytime you dispose a reference to the job. 307 */ 278 308 void job_del_ref(job_t **job_ptr) 279 309 { 280 310 job_t *job = *job_ptr; 281 if (job == NULL) { 282 return; 283 } 284 311 312 assert(job != NULL); 285 313 assert(atomic_get(&job->refcnt) > 0); 286 314 if (atomic_predec(&job->refcnt) == 0) { … … 295 323 296 324 unit_t *u = job->unit; 297 sysman_log(LVL_DEBUG, "%s , %s -> %i",298 __func__, unit_name(u), job->target_state);325 sysman_log(LVL_DEBUG, "%s(%p), %s -> %i", 326 __func__, job, unit_name(u), job->target_state); 299 327 300 328 /* Propagate failure */ … … 316 344 } 317 345 346 /* 347 * job_check deletes reference, we want job to remain to caller, thus 348 * add one dummy ref 349 */ 350 job_add_ref(job); 318 351 job_check(job->unit, job); 319 352 return; … … 333 366 assert(job->retval != JOB_UNDEFINED_); 334 367 335 sysman_log(LVL_DEBUG2, "%s(% s)-> %i",336 __func__, unit_name(job->unit), job->retval);368 sysman_log(LVL_DEBUG2, "%s(%p) %s -> %i", 369 __func__, job, unit_name(job->unit), job->retval); 337 370 338 371 job->state = JOB_FINISHED; 339 372 340 /* Job finished*/373 /* First remove references, then clear the array */ 341 374 dyn_array_foreach(job->blocked_jobs, job_ptr_t, job_it) { 342 375 job_unblock(*job_it, job); 343 376 } 344 // TODO remove reference from blocked jobs 345 346 // TODO should reference be added (for the created event) 377 dyn_array_clear(&job->blocked_jobs); 378 379 /* Add reference for the event */ 380 job_add_ref(job); 347 381 sysman_raise_event(&sysman_event_job_changed, job); 348 382 } -
uspace/srv/sysman/job.h
r095d03c r8432ae1 85 85 extern void job_del_ref(job_t **); 86 86 87 88 87 extern void job_run(job_t *); 89 88 extern void job_finish(job_t *); -
uspace/srv/sysman/main.c
r095d03c r8432ae1 149 149 150 150 /* Queue first job for processing */ 151 job_add_ref(first_job); 151 152 sysman_object_observer(first_job, &first_job_handler, NULL); 153 job_add_ref(first_job); 152 154 sysman_raise_event(&sysman_event_job_process, first_job); 155 156 /* 157 * Releasing our own reference (could be merged with previous add_ref, 158 * this is more explicit though. 159 */ 160 job_del_ref(&first_job); 153 161 154 162 /* Start sysman server */ -
uspace/srv/sysman/sysman.c
r095d03c r8432ae1 150 150 151 151 /* Process event */ 152 sysman_log(LVL_DEBUG2, "process(%p, %p)", event->handler, event->data); 152 153 event->handler(event->data); 153 154 free(event); … … 157 158 void sysman_raise_event(event_handler_t handler, void *data) 158 159 { 160 sysman_log(LVL_DEBUG2, "%s(%p, %p)", __func__, handler, data); 159 161 event_t *event = malloc(sizeof(event_t)); 160 162 if (event == NULL) { … … 237 239 } 238 240 241 /* 242 * If jobs are queued, reference is passed from closure to the queue, 243 * otherwise, we still have the reference. 244 */ 239 245 rc = job_queue_add_jobs(&job_closure); 240 246 if (rc != EOK) { 241 // TODO job_queue_add_jobs should log message242 247 goto fail; 243 248 } 249 /* We don't need job anymore */ 250 job_del_ref(&job); 244 251 245 252 // TODO explain why calling asynchronously … … 250 257 job->retval = JOB_FAILED; 251 258 job_finish(job); 252 // TODO clarify refcount to the main job 259 job_del_ref(&job); 260 253 261 dyn_array_foreach(job_closure, job_ptr_t, closure_job) { 254 262 job_del_ref(&(*closure_job)); … … 263 271 while ((job = job_queue_pop_runnable())) { 264 272 job_run(job); 273 job_del_ref(&job); 265 274 } 266 275 } … … 269 278 { 270 279 notify_observers(object); 271 } 280 /* Unreference the event data */ 281 job_t *job = object; 282 job_del_ref(&job); 283 }
Note:
See TracChangeset
for help on using the changeset viewer.