Changeset 5559712 in mainline for uspace/srv/sysman/job.c
- Timestamp:
- 2019-08-03T09:28:50Z (6 years ago)
- Children:
- c0e4fc50
- Parents:
- 2dda1d4
- git-author:
- Michal Koutný <xm.koutny+hos@…> (2015-05-07 11:49:47)
- git-committer:
- Matthieu Riolo <matthieu.riolo@…> (2019-08-03 09:28:50)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/sysman/job.c
r2dda1d4 r5559712 73 73 assert(job); 74 74 assert(u); 75 memset(job, 0, sizeof(*job)); 75 76 76 77 link_initialize(&job->job_queue); … … 101 102 return false; 102 103 } 103 }104 105 static bool job_is_runnable(job_t *job)106 {107 return job->state == JOB_QUEUED && job->blocking_jobs == 0;108 104 } 109 105 … … 126 122 } 127 123 128 129 130 131 124 static void job_destroy(job_t **job_ptr) 132 125 { … … 145 138 free(job); 146 139 *job_ptr = NULL; 140 } 141 142 static bool job_is_runnable(job_t *job) 143 { 144 return job->state == JOB_QUEUED && job->blocking_jobs == 0; 145 } 146 147 /** Pop next runnable job 148 * 149 * @return runnable job or NULL when there's none 150 */ 151 static job_t *job_queue_pop_runnable(void) 152 { 153 job_t *result = NULL; 154 155 /* Select first runnable job */ 156 list_foreach(job_queue, job_queue, job_t, candidate) { 157 if (job_is_runnable(candidate)) { 158 result = candidate; 159 break; 160 } 161 } 162 if (result) { 163 /* Remove job from queue and pass reference to caller */ 164 list_remove(&result->job_queue); 165 result->state = JOB_DEQUEUED; 166 } 167 168 return result; 147 169 } 148 170 … … 163 185 /* 164 186 * Currently we have strict strategy not permitting 165 * multiple jobs for one unit in the queue .187 * multiple jobs for one unit in the queue at a time. 166 188 */ 167 189 if ((*new_job_it)->unit == queued_job->unit) { 168 190 sysman_log(LVL_ERROR, 169 "Cannot queue multiple jobs fo or unit '%s'",191 "Cannot queue multiple jobs for unit '%s'", 170 192 unit_name((*new_job_it)->unit)); 171 193 return EEXIST; … … 184 206 } 185 207 186 /** Pop next runnable job 187 * 188 * @return runnable job or NULL when there's none 189 */ 190 job_t *job_queue_pop_runnable(void) 191 { 192 job_t *result = NULL; 193 link_t *first_link = list_first(&job_queue); 194 bool first_iteration = true; 195 196 list_foreach_safe(job_queue, cur_link, next_link) { 197 result = list_get_instance(cur_link, job_t, job_queue); 198 if (job_is_runnable(result)) { 199 break; 200 } else if (!first_iteration && cur_link == first_link) { 201 result = NULL; 202 break; 203 } else { 204 /* 205 * We make no assuptions about ordering of jobs in the 206 * queue, so just move the job to the end of the queue. 207 * If there are exist topologic ordering, eventually 208 * jobs will be reordered. Furthermore when if there 209 * exists any runnable job, it's always found. 210 */ 211 list_remove(cur_link); 212 list_append(cur_link, &job_queue); 213 } 214 first_iteration = false; 215 } 216 217 if (result) { 218 /* Remove job from queue and pass refernce to caller */ 219 list_remove(&result->job_queue); 220 result->state = JOB_DEQUEUED; 221 } 222 223 return result; 208 /** Process all jobs that aren't transitively blocked 209 * 210 * Job can be blocked either by another job or by an incoming event, that will 211 * be queued after this job_queue_process call. 212 * 213 * TODO Write down rules from where this function can be called, to avoid stack 214 * overflow. 215 */ 216 void job_queue_process(void) 217 { 218 job_t *job; 219 while ((job = job_queue_pop_runnable())) { 220 job_run(job); 221 job_del_ref(&job); 222 } 224 223 } 225 224 … … 242 241 */ 243 242 fifo_push(jobs_fifo, main_job); 244 job_t *job;245 243 job_add_ref(main_job); 246 while ((job = fifo_pop(jobs_fifo)) != NULL) { 247 /* No refcount increase, pass it to the closure */ 248 dyn_array_append(job_closure, job_ptr_t, job); 244 while (jobs_fifo.head != jobs_fifo.tail) { 245 job_t *job = fifo_pop(jobs_fifo); 246 247 // TODO more sophisticated check? (unit that is in transitional 248 // state cannot have currently multiple jobs queued) 249 if (job->target_state == job->unit->state) { 250 /* 251 * Job would do nothing, finish it on spot. 252 * No need to continue BFS search from it. 253 */ 254 job->retval = JOB_OK; 255 job_finish(job); 256 job_del_ref(&job); 257 continue; 258 } else { 259 /* No refcount increase, pass it to the closure */ 260 dyn_array_append(job_closure, job_ptr_t, job); 261 } 249 262 250 263 /* Traverse dependencies edges */ … … 379 392 /* Add reference for the event */ 380 393 job_add_ref(job); 381 sysman_raise_event(&sysman_event_job_ changed, job);382 } 383 394 sysman_raise_event(&sysman_event_job_finished, job); 395 } 396
Note:
See TracChangeset
for help on using the changeset viewer.