#ifndef LITMUS_IKGLP_H
#define LITMUS_IKGLP_H
#include <litmus/litmus.h>
#include <litmus/binheap.h>
#include <litmus/locking.h>
#ifdef CONFIG_LITMUS_AFFINITY_LOCKING
#include <litmus/kexclu_affinity.h>
struct ikglp_affinity;
#endif
typedef struct ikglp_heap_node
{
struct task_struct *task;
struct binheap_node node;
} ikglp_heap_node_t;
struct fifo_queue;
struct ikglp_wait_state;
typedef struct ikglp_donee_heap_node
{
struct task_struct *task;
struct fifo_queue *fq;
struct ikglp_wait_state *donor_info; // cross-linked with ikglp_wait_state_t of donor
struct binheap_node node;
} ikglp_donee_heap_node_t;
// Maintains the state of a request as it goes through the IKGLP
typedef struct ikglp_wait_state {
struct task_struct *task; // pointer back to the requesting task
// Data for while waiting in FIFO Queue
wait_queue_t fq_node;
ikglp_heap_node_t global_heap_node;
ikglp_donee_heap_node_t donee_heap_node;
// Data for while waiting in PQ
ikglp_heap_node_t pq_node;
// Data for while waiting as a donor
ikglp_donee_heap_node_t *donee_info; // cross-linked with donee's ikglp_donee_heap_node_t
struct nested_info prio_donation;
struct binheap_node node;
} ikglp_wait_state_t;
/* struct for semaphore with priority inheritance */
struct fifo_queue
{
wait_queue_head_t wait;
struct task_struct* owner;
// used for bookkeepping
ikglp_heap_node_t global_heap_node;
ikglp_donee_heap_node_t donee_heap_node;
struct task_struct* hp_waiter;
unsigned int count; /* number of waiters + holder */
struct nested_info nest;
};
struct ikglp_semaphore
{
struct litmus_lock litmus_lock;
raw_spinlock_t lock;
raw_spinlock_t real_lock;
unsigned int nr_replicas; // AKA k
unsigned int max_fifo_len; // max len of a fifo queue
unsigned int max_in_fifos; // AKA m
unsigned int nr_in_fifos;
struct binheap top_m; // min heap, base prio
unsigned int top_m_size; // number of nodes in top_m
struct binheap not_top_m; // max heap, base prio
struct binheap donees; // min-heap, base prio
struct fifo_queue *shortest_fifo_queue; // pointer to shortest fifo queue
/* data structures for holding requests */
struct fifo_queue *fifo_queues; // array nr_replicas in length
struct binheap priority_queue; // max-heap, base prio
struct binheap donors; // max-heap, base prio
#ifdef CONFIG_LITMUS_AFFINITY_LOCKING
struct ikglp_affinity *aff_obs;
#endif
};
static inline struct ikglp_semaphore* ikglp_from_lock(struct litmus_lock* lock)
{
return container_of(lock, struct ikglp_semaphore, litmus_lock);
}
int ikglp_lock(struct litmus_lock* l);
int ikglp_unlock(struct litmus_lock* l);
int ikglp_close(struct litmus_lock* l);
void ikglp_free(struct litmus_lock* l);
struct litmus_lock* ikglp_new(unsigned int m, struct litmus_lock_ops*, void* __user arg);
#ifdef CONFIG_LITMUS_AFFINITY_LOCKING
struct ikglp_queue_info
{
struct fifo_queue* q;
lt_t estimated_len;
unsigned int *nr_cur_users;
unsigned int *nr_aff_users;
};
struct ikglp_affinity_ops
{
struct fifo_queue* (*advise_enqueue)(struct ikglp_affinity* aff, struct task_struct* t); // select FIFO
ikglp_wait_state_t* (*advise_steal)(struct ikglp_affinity* aff, struct fifo_queue* dst); // select steal from FIFO
ikglp_donee_heap_node_t* (*advise_donee_selection)(struct ikglp_affinity* aff, struct task_struct* t); // select a donee
ikglp_wait_state_t* (*advise_donor_to_fq)(struct ikglp_affinity* aff, struct fifo_queue* dst); // select a donor to move to PQ
void (*notify_enqueue)(struct ikglp_affinity* aff, struct fifo_queue* fq, struct task_struct* t); // fifo enqueue
void (*notify_dequeue)(struct ikglp_affinity* aff, struct fifo_queue* fq, struct task_struct* t); // fifo dequeue
void (*notify_acquired)(struct ikglp_affinity* aff, struct fifo_queue* fq, struct task_struct* t); // replica acquired
void (*notify_freed)(struct ikglp_affinity* aff, struct fifo_queue* fq, struct task_struct* t); // replica freed
int (*replica_to_resource)(struct ikglp_affinity* aff, struct fifo_queue* fq); // convert a replica # to a GPU (includes offsets and simult user folding)
int (*notify_exit)(struct ikglp_affinity* aff, struct task_struct* t);
};
struct ikglp_affinity
{
struct affinity_observer obs;
struct ikglp_affinity_ops *ops;
struct ikglp_queue_info *q_info;
unsigned int *nr_cur_users_on_rsrc;
unsigned int *nr_aff_on_rsrc;
unsigned int offset;
unsigned int nr_simult;
unsigned int nr_rsrc;
unsigned int relax_max_fifo_len:1;
};
static inline struct ikglp_affinity* ikglp_aff_obs_from_aff_obs(struct affinity_observer* aff_obs)
{
return container_of(aff_obs, struct ikglp_affinity, obs);
}
int ikglp_aff_obs_close(struct affinity_observer*);
void ikglp_aff_obs_free(struct affinity_observer*);
#ifdef CONFIG_LITMUS_NVIDIA
struct affinity_observer* ikglp_gpu_aff_obs_new(struct affinity_observer_ops*,
void* __user arg);
struct affinity_observer* ikglp_simple_gpu_aff_obs_new(struct affinity_observer_ops*,
void* __user arg);
#endif
#endif /* end affinity */
#endif