isc_thread_t thread;
unsigned int threadid;
unsigned int tasks_waiting;
+ bool running;
isc__taskmgr_t *manager;
};
isc_mutex_t halt_lock;
isc_condition_t halt_cond;
unsigned int workers;
- atomic_uint_fast32_t tasks_running;
- atomic_uint_fast32_t tasks_ready;
atomic_uint_fast32_t curq;
isc__taskqueue_t *queues;
if (task != NULL) {
DEQUEUE(manager->queues[c].ready_tasks, task, ready_link);
+ INSIST(manager->queues[c].tasks_waiting > 0);
manager->queues[c].tasks_waiting--;
if (ISC_LINK_LINKED(task, ready_priority_link)) {
DEQUEUE(manager->queues[c].ready_priority_tasks, task,
ENQUEUE(manager->queues[c].ready_priority_tasks, task,
ready_priority_link);
}
- atomic_fetch_add_explicit(&manager->tasks_ready, 1,
- memory_order_acquire);
}
static void
* have a task to do. We must reacquire the queue
* lock before exiting the 'if (task != NULL)' block.
*/
+ manager->queues[threadid].running = true;
UNLOCK(&manager->queues[threadid].lock);
- RUNTIME_CHECK(
- atomic_fetch_sub_explicit(&manager->tasks_ready,
- 1, memory_order_release) > 0);
- atomic_fetch_add_explicit(&manager->tasks_running, 1,
- memory_order_acquire);
LOCK(&task->lock);
INSIST(task->state == task_state_ready);
if (finished)
task_finished(task);
- RUNTIME_CHECK(
- atomic_fetch_sub_explicit(&manager->tasks_running,
- 1, memory_order_release) > 0);
LOCK(&manager->queues[threadid].lock);
+ manager->queues[threadid].running = false;
if (requeue) {
/*
* We know we're awake, so we don't have
/*
* If we are in privileged execution mode and there are no
- * tasks remaining on the current ready queue, then
- * we're stuck. Automatically drop privileges at that
- * point and continue with the regular ready queue.
+ * tasks remaining on the current ready queue, we need to check
+ * if maybe we need to drop from privileged to normal mode.
+ * This might seem too heavy with all the locking but
+ * privileged mode is used only during startup and dropped
+ * once - after that this code is never executed.
*/
if (manager->mode != isc_taskmgrmode_normal &&
- atomic_load_explicit(&manager->tasks_running,
- memory_order_acquire) == 0)
+ empty_readyq(manager, threadid))
{
UNLOCK(&manager->queues[threadid].lock);
LOCK(&manager->lock);
* we'll end up in a deadlock over queue locks.
*
*/
- if (manager->mode != isc_taskmgrmode_normal &&
- atomic_load_explicit(&manager->tasks_running,
- memory_order_acquire) == 0)
- {
+ if (manager->mode != isc_taskmgrmode_normal) {
bool empty = true;
unsigned int i;
for (i = 0; i < manager->workers && empty; i++)
{
LOCK(&manager->queues[i].lock);
- empty &= empty_readyq(manager, i);
+ empty &= empty_readyq(manager, i) &&
+ !manager->queues[i].running;
UNLOCK(&manager->queues[i].lock);
}
if (empty) {
manager->queues = isc_mem_get(mctx, workers * sizeof(isc__taskqueue_t));
RUNTIME_CHECK(manager->queues != NULL);
- manager->tasks_running = 0;
- manager->tasks_ready = 0;
manager->curq = 0;
manager->exiting = false;
manager->excl = NULL;
manager->queues[i].manager = manager;
manager->queues[i].threadid = i;
manager->queues[i].tasks_waiting = 0;
+ manager->queues[i].running = false;
RUNTIME_CHECK(isc_thread_create(run, &manager->queues[i],
&manager->queues[i].thread)
== ISC_R_SUCCESS);
TRY0(xmlTextWriterWriteFormatString(writer, "%d", mgr->workers));
TRY0(xmlTextWriterEndElement(writer)); /* worker-threads */
- TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "tasks-running"));
- TRY0(xmlTextWriterWriteFormatString(writer, "%d",
- (int) mgr->tasks_running));
- TRY0(xmlTextWriterEndElement(writer)); /* tasks-running */
-
- TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "tasks-ready"));
- TRY0(xmlTextWriterWriteFormatString(writer, "%d",
- (int) mgr->tasks_ready));
- TRY0(xmlTextWriterEndElement(writer)); /* tasks-ready */
-
TRY0(xmlTextWriterEndElement(writer)); /* thread-model */
TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "tasks"));
CHECKMEM(obj);
json_object_object_add(tasks, "worker-threads", obj);
- obj = json_object_new_int(mgr->tasks_running);
- CHECKMEM(obj);
- json_object_object_add(tasks, "tasks-running", obj);
-
- obj = json_object_new_int(mgr->tasks_ready);
- CHECKMEM(obj);
- json_object_object_add(tasks, "tasks-ready", obj);
-
array = json_object_new_array();
CHECKMEM(array);