STAILQ_HEAD(validation_tasks, validation_task);
/* Queued, not yet claimed tasks */
-static struct validation_tasks tasks;
+static struct validation_tasks waiting;
/* Queued, but not yet available for claiming */
-static struct validation_tasks busy;
-/* Active tasks (length(@tasks) + length(@busy) + number of running tasks) */
-static int active;
+static struct validation_tasks dormant;
+/*
+ * Total currently existing tasks
+ * (length(@waiting) + length(@dormant) + total active tasks)
+ */
+static int ntasks;
static bool enabled = true;
void
task_setup(void)
{
- STAILQ_INIT(&tasks);
- STAILQ_INIT(&busy);
- active = 0;
+ STAILQ_INIT(&waiting);
+ STAILQ_INIT(&dormant);
+ ntasks = 0;
enabled = true;
panic_on_fail(pthread_mutex_init(&lock, NULL), "pthread_mutex_init");
panic_on_fail(pthread_cond_init(&awakener, NULL), "pthread_cond_init");
cleanup(void)
{
enabled = false;
- active = 0;
- cleanup_tasks(&tasks);
- cleanup_tasks(&busy);
+ ntasks = 0;
+ cleanup_tasks(&waiting);
+ cleanup_tasks(&dormant);
}
void
/*
* Defers a task for later.
* Call task_wakeup() once you've queued all your tasks.
+ * Returns number of deferred tasks.
*/
unsigned int
task_enqueue(struct cache_mapping *map, struct rpki_certificate *parent)
mutex_lock(&lock);
if (enabled) {
- STAILQ_INSERT_TAIL(&tasks, task, lh);
+ STAILQ_INSERT_TAIL(&waiting, task, lh);
task = NULL;
- active++;
+ ntasks++;
}
mutex_unlock(&lock);
return 1;
}
+/* Steals ownership of @task. */
void
-task_requeue_busy(struct validation_task *task)
+task_requeue_dormant(struct validation_task *task)
{
mutex_lock(&lock);
if (enabled) {
- STAILQ_INSERT_TAIL(&busy, task, lh);
+ STAILQ_INSERT_TAIL(&dormant, task, lh);
task = NULL;
}
mutex_unlock(&lock);
task_free(task); /* Couldn't queue */
}
-/* Wakes up threads currently waiting for tasks. */
+/* Wakes up all sleeping task threads. */
void
task_wakeup(void)
{
mutex_unlock(&lock);
}
+/* Upgrades all dormant tasks, and wakes up all sleeping task threads. */
void
-task_wakeup_busy(void)
+task_wakeup_dormants(void)
{
mutex_lock(&lock);
- STAILQ_CONCAT(&tasks, &busy);
+ STAILQ_CONCAT(&waiting, &dormant);
panic_on_fail(pthread_cond_broadcast(&awakener),
"pthread_cond_broadcast");
mutex_unlock(&lock);
* Frees the @prev previous task, and returns the next one.
*
* If no task is available yet, will sleep until someone calls task_wakeup() or
- * task_wakeup_busy().
+ * task_wakeup_dormants().
* If all the tasks are done, returns NULL.
*
+ * Steals ownership of @prev.
* Assumes at least one task has been queued before the first dequeue.
*/
struct validation_task *
goto end;
if (prev) {
- active--;
- if (active < 0)
- pr_crit("active < 0: %d", active);
+ ntasks--;
+ if (ntasks < 0)
+ pr_crit("active < 0: %d", ntasks);
}
- while (active > 0) {
- pr_op_debug("task_dequeue(): %u tasks active.", active);
+ while (ntasks > 0) {
+ pr_op_debug("task_dequeue(): %u existing tasks.", ntasks);
- task = STAILQ_FIRST(&tasks);
+ task = STAILQ_FIRST(&waiting);
if (task != NULL) {
- STAILQ_REMOVE_HEAD(&tasks, lh);
+ STAILQ_REMOVE_HEAD(&waiting, lh);
mutex_unlock(&lock);
pr_op_debug("task_dequeue(): Claimed task '%s'.",
task->ca->map.url);
static STAILQ_HEAD(test_task_list, test_task) test_tasks;
static pthread_mutex_t test_tasks_lock = PTHREAD_MUTEX_INITIALIZER;
-static bool return_busy;
+static bool return_dormant;
static void
populate_test_tasks(void)
if (n != 0)
task_wakeup();
- if (return_busy && (rand() & 3) == 0)
+ if (return_dormant && (rand() & 3) == 0)
return EBUSY; /* Return "busy" 25% of the time */
return 0;
if (certificate_traverse_mock(task->ca, thid) == EBUSY) {
printf("+ th%d: Requeuing '%s'\n",
thid, task->ca->map.url);
- task_requeue_busy(task);
+ task_requeue_dormant(task);
task = NULL;
}
}
START_TEST(test_queue_multiuser)
{
- return_busy = false;
+ return_dormant = false;
task_setup();
task_start();
END_TEST
static void *
-release_busies(void *arg)
+upgrade_dormants(void *arg)
{
unsigned int i;
for (i = 0; i < 2; i++) {
sleep(1);
- printf("Waking up busy tasks!\n");
- task_wakeup_busy();
+ printf("Upgrading dormant tasks!\n");
+ task_wakeup_dormants();
}
sleep(1);
- return_busy = false;
- printf("Waking up busy tasks for the last time!\n");
- task_wakeup_busy();
+ return_dormant = false;
+ printf("Upgrading dormant tasks for the last time!\n");
+ task_wakeup_dormants();
return NULL;
}
{
pthread_t thr;
- return_busy = true;
+ return_dormant = true;
task_setup();
task_start();
- ck_assert_int_eq(0, pthread_create(&thr, NULL, release_busies, NULL));
+ ck_assert_int_eq(0, pthread_create(&thr, NULL, upgrade_dormants, NULL));
populate_test_tasks();
run_threads();