blob: c6e36ef7b484117c829e74c926ec089498da1e45 [file] [log] [blame]
// SPDX-License-Identifier: GPL-2.0-only
/*
* Priority queue impletation with BigOcean
*
* Copyright 2021 Google LLC.
*
* Author: Ruofei Ma <ruofeim@google.com>
*/
#include <linux/kthread.h>
#include <linux/module.h>
#include "bigo_prioq.h"
int enqueue_prioq(struct bigo_core *core, struct bigo_inst *inst)
{
struct bigo_job *job = &inst->job;
if(!core || !inst)
return -EINVAL;
mutex_lock(&core->prioq.lock);
list_add_tail(&job->list, &core->prioq.queue[inst->priority]);
set_bit(inst->priority, &core->prioq.bitmap);
mutex_unlock(&core->prioq.lock);
wake_up(&core->worker);
return 0;
}
bool dequeue_prioq(struct bigo_core *core, struct bigo_job **job,
bool *should_stop)
{
int high_prio;
struct bigo_job *j = NULL;
struct list_head *queue;
if (!core || !job || !should_stop)
return false;
*should_stop = false;
if(kthread_should_stop()) {
*should_stop = true;
return true;
}
mutex_lock(&core->prioq.lock);
high_prio = ffs(core->prioq.bitmap) - 1;
if (high_prio < 0)
goto exit;
queue = &core->prioq.queue[high_prio];
j = list_first_entry_or_null(queue, struct bigo_job, list);
if (j) {
list_del(&j->list);
if (list_empty(queue))
clear_bit(high_prio, &core->prioq.bitmap);
}
exit:
mutex_unlock(&core->prioq.lock);
*job = j;
return *job != NULL;
}
void clear_job_from_prioq(struct bigo_core *core, struct bigo_inst *inst)
{
int i;
struct bigo_job *curr, *next;
struct bigo_inst *curr_inst;
mutex_lock(&core->prioq.lock);
for (i = 0; i < BO_MAX_PRIO; i++) {
list_for_each_entry_safe(curr, next, &core->prioq.queue[i], list) {
curr_inst = container_of(curr, struct bigo_inst, job);
if (inst == curr_inst)
list_del(&curr->list);
}
}
mutex_unlock(&core->prioq.lock);
}
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Ruofei Ma <ruofeim@google.com>");