blob: abef0d9e94ff6333f15f1de0bc1aec561b2d4d02 [file] [log] [blame]
#ifdef CONFIG_FAST_TRACK
#include <linux/sched.h>
#include <linux/list.h>
#include <linux/rwsem.h>
#include <cpu/ftt/ftt.h>
enum rwsem_waiter_type {
RWSEM_WAITING_FOR_WRITE,
RWSEM_WAITING_FOR_READ
};
struct rwsem_waiter {
struct list_head list;
struct task_struct *task;
enum rwsem_waiter_type type;
};
#define RWSEM_READER_OWNED ((struct task_struct *)1UL)
static inline bool rwsem_owner_is_writer(struct task_struct *owner)
{
return owner && owner != RWSEM_READER_OWNED;
}
static void rwsem_list_add_ftt(struct list_head *entry, struct list_head *head)
{
struct list_head *pos = NULL;
struct rwsem_waiter *waiter = NULL;
list_for_each(pos, head) {
waiter = list_entry(pos, struct rwsem_waiter, list);
if (!is_ftt(&waiter->task->se)) {
list_add(entry, waiter->list.prev);
return;
}
}
if (pos == head) {
list_add_tail(entry, head);
}
}
void rwsem_list_add(struct task_struct *tsk, struct list_head *entry, struct list_head *head)
{
if (unlikely(tsk == NULL))
return;
if (is_ftt(&tsk->se)) {
rwsem_list_add_ftt(entry, head);
} else {
list_add_tail(entry, head);
}
}
void rwsem_dynamic_ftt_enqueue(struct task_struct *tsk, struct task_struct *waiter_task, struct task_struct *owner, struct rw_semaphore *sem)
{
if (unlikely(tsk == NULL) || unlikely(waiter_task == NULL || owner == NULL))
return;
if (is_ftt(&tsk->se)) {
if (rwsem_owner_is_writer(owner) && !is_ftt(&owner->se) && sem && !sem->ftt_dep_task) {
dynamic_ftt_enqueue(owner, DYNAMIC_FTT_RWSEM);
sem->ftt_dep_task = owner;
}
}
}
void rwsem_dynamic_ftt_dequeue(struct rw_semaphore *sem, struct task_struct *tsk)
{
if (tsk && sem && sem->ftt_dep_task == tsk) {
dynamic_ftt_dequeue(tsk, DYNAMIC_FTT_RWSEM);
sem->ftt_dep_task = NULL;
}
}
#endif