/*-------------------------------------------------------------------------*/ void *scheduler_get(scheduler_t *sched, int id) { void *task = 0; pthread_mutex_t *mutex = sched->mutex; pthread_cond_t *cond = sched->cond; list_t **queue = sched->queue; /* We wait until an executable task is available. Although the semaphore might suggest that there are still some tasks in the queues, there might be actually nothing left. This might happen if, for example, during a pause, the scheduler has been reset. We therefore add a while in order to guaranty that when the function exits, a task is returned. */ while (task == 0) { sem_wait(sched->sem); pthread_mutex_lock(mutex); /* If we are in pause mode, then we wait until the conditional variable is signaled. */ if (sched->pause) { message_pause(); pthread_cond_wait(cond, mutex); } /* Pick a task from the high priority queue if it is not empty. */ if (queue[high]->size > 0) task = list_rem_head(queue[high]); /* Otherwise, if the disk queue is not empty and nobody is accessing the disk at the moment, then pick a task from the disk queue. */ else if (queue[disk]->size > 0 && sched->disk == -1) { sched->disk = id; task = list_rem_head(queue[disk]); } /* Finally, if none of the above cases where taken, then pick a task from the low priority queue. */ else task = list_rem_head(queue[low]); pthread_mutex_unlock(mutex); } return task; }
/* Code coverage test for Node and List functions. */ void test_task_f(void *user_data) { List l; Node n1; Node n2; list_init(&l); n1.prio = 3; n1.name = "one"; n2.prio = 8; n2.name = "two"; assert(true == list_is_empty(&l)); assert(NULL == list_get_head(&l)); list_add_tail(&l, &n1); assert(false == list_is_empty(&l)); assert(&n1 == list_get_head(&l)); list_add_tail(&l, &n2); assert(&n1 == list_get_head(&l)); assert(&n1 == list_find(&l, "one")); assert(&n2 == list_find(&l, "two")); list_rem_head(&l); assert(&n2 == list_get_head(&l)); assert(NULL == list_find(&l, "one")); list_rem_head(&l); list_enqueue(&l, &n1); assert(&n1 == list_get_head(&l)); list_enqueue(&l, &n2); assert(&n2 == list_get_head(&l)); list_unlink(&n1); assert(&n2 == list_get_head(&l)); list_enqueue(&l, &n1); assert(&n2 == list_get_head(&l)); assert(&n2 == list_rem_head(&l)); assert(&n1 == list_rem_head(&l)); assert(NULL == list_rem_head(&l)); assert(NULL == list_rem_head(&l)); assert(3 == n1.prio); assert(8 == n2.prio); assert(NULL == list_find(&l, "one")); assert(NULL == list_find(&l, "two")); test_pass(); }
/*-------------------------------------------------------------------------*/ void fsm_handle_start(fsm_t *fsm) { /* At this point, no work task is running or scheduled. If the brute force is restarted or disabled, then it is safe to delete some hashes. */ if (fsm->bforce || fsm->arg->bforce == 0) { list_t *htoremove = fsm->htoremove; while (htoremove->size > 0) { hash_t *hsh = (hash_t*)list_rem_head(htoremove); hash_free(hsh); } } /* Create and launch a preload task. */ fsm_launch_preload(fsm); /* Create and launch a brute force task. */ if (fsm->bforce) fsm_launch_bforce(fsm); fsm->state = st_preload; }