/* Fixed-priority scheduler support. */ #ifndef __FP_COMMON_H__ #define __FP_COMMON_H__ #include #include void fp_domain_init(rt_domain_t* rt, check_resched_needed_t resched, release_jobs_t release); int fp_higher_prio(struct task_struct* first, struct task_struct* second); int fp_ready_order(struct bheap_node* a, struct bheap_node* b); #define FP_PRIO_BIT_WORDS (LITMUS_MAX_PRIORITY / BITS_PER_LONG) #if (LITMUS_MAX_PRIORITY % BITS_PER_LONG) #error LITMUS_MAX_PRIORITY must be a multiple of BITS_PER_LONG #endif /* bitmask-inexed priority queue */ struct fp_prio_queue { unsigned long bitmask[FP_PRIO_BIT_WORDS]; struct bheap queue[LITMUS_MAX_PRIORITY]; }; void fp_prio_queue_init(struct fp_prio_queue* q); static inline void fpq_set(struct fp_prio_queue* q, unsigned int index) { unsigned long *word = q->bitmask + (index / BITS_PER_LONG); __set_bit(index % BITS_PER_LONG, word); } static inline void fpq_clear(struct fp_prio_queue* q, unsigned int index) { unsigned long *word = q->bitmask + (index / BITS_PER_LONG); __clear_bit(index % BITS_PER_LONG, word); } static inline unsigned int fpq_find(struct fp_prio_queue* q) { int i; /* loop optimizer should unroll this */ for (i = 0; i < FP_PRIO_BIT_WORDS; i++) if (q->bitmask[i]) return __ffs(q->bitmask[i]) + i * BITS_PER_LONG; return LITMUS_MAX_PRIORITY; /* nothing found */ } static inline void fp_prio_add(struct fp_prio_queue* q, struct task_struct* t, unsigned int index) { BUG_ON(index >= LITMUS_MAX_PRIORITY); BUG_ON(bheap_node_in_heap(tsk_rt(t)->heap_node)); fpq_set(q, index); bheap_insert(fp_ready_order, &q->queue[index], tsk_rt(t)->heap_node); } static inline void fp_prio_remove(struct fp_prio_queue* q, struct task_struct* t, unsigned int index) { BUG_ON(!is_queued(t)); bheap_delete(fp_ready_order, &q->queue[index], tsk_rt(t)->heap_node); if (likely(bheap_empty(&q->queue[index]))) fpq_clear(q, index); } static inline struct task_struct* fp_prio_peek(struct fp_prio_queue* q) { unsigned int idx = fpq_find(q); struct bheap_node* hn; if (idx < LITMUS_MAX_PRIORITY) { hn = bheap_peek(fp_ready_order, &q->queue[idx]); return bheap2task(hn); } else return NULL; } static inline struct task_struct* fp_prio_take(struct fp_prio_queue* q) { unsigned int idx = fpq_find(q); struct bheap_node* hn; if (idx < LITMUS_MAX_PRIORITY) { hn = bheap_take(fp_ready_order, &q->queue[idx]); if (likely(bheap_empty(&q->queue[idx]))) fpq_clear(q, idx); return bheap2task(hn); } else return NULL; } int fp_preemption_needed(struct fp_prio_queue* q, struct task_struct *t); #endif