/* * Copyright 2014, General Dynamics C4 Systems * * This software may be distributed and modified according to the terms of * the GNU General Public License version 2. Note that NO WARRANTY is provided. * See "LICENSE_GPLv2.txt" for details. * * @TAG(GD_GPL) */ #ifndef __KERNEL_THREAD_H #define __KERNEL_THREAD_H #include #include #include #include static inline CONST word_t ready_queues_index(word_t dom, word_t prio) { if (CONFIG_NUM_DOMAINS > 1) { return dom * CONFIG_NUM_PRIORITIES + prio; } else { assert(dom == 0); return prio; } } static inline CONST word_t prio_to_l1index(word_t prio) { return (prio >> wordRadix); } static inline CONST word_t l1index_to_prio(word_t l1index) { return (l1index << wordRadix); } static inline bool_t PURE isRunnable(const tcb_t *thread) { switch (thread_state_get_tsType(thread->tcbState)) { case ThreadState_Running: case ThreadState_Restart: #ifdef CONFIG_VTX case ThreadState_RunningVM: #endif return true; default: return false; } } static inline CONST word_t invert_l1index(word_t l1index) { word_t inverted = (L2_BITMAP_SIZE - 1 - l1index); assert(inverted < L2_BITMAP_SIZE); return inverted; } static inline prio_t getHighestPrio(word_t dom) { word_t l1index; word_t l2index; word_t l1index_inverted; /* it's undefined to call clzl on 0 */ assert(NODE_STATE(ksReadyQueuesL1Bitmap)[dom] != 0); l1index = wordBits - 1 - clzl(NODE_STATE(ksReadyQueuesL1Bitmap)[dom]); l1index_inverted = invert_l1index(l1index); assert(NODE_STATE(ksReadyQueuesL2Bitmap)[dom][l1index_inverted] != 0); l2index = wordBits - 1 - clzl(NODE_STATE(ksReadyQueuesL2Bitmap)[dom][l1index_inverted]); return (l1index_to_prio(l1index) | l2index); } static inline bool_t isHighestPrio(word_t dom, prio_t prio) { return NODE_STATE(ksReadyQueuesL1Bitmap)[dom] == 0 || prio >= getHighestPrio(dom); } void configureIdleThread(tcb_t *tcb); void activateThread(void); void suspend(tcb_t *target); void restart(tcb_t *target); void doIPCTransfer(tcb_t *sender, endpoint_t *endpoint, word_t badge, bool_t grant, tcb_t *receiver); void doReplyTransfer(tcb_t *sender, tcb_t *receiver, cte_t *slot, bool_t grant); void doNormalTransfer(tcb_t *sender, word_t *sendBuffer, endpoint_t *endpoint, word_t badge, bool_t canGrant, tcb_t *receiver, word_t *receiveBuffer); void doFaultTransfer(word_t badge, tcb_t *sender, tcb_t *receiver, word_t *receiverIPCBuffer); void doNBRecvFailedTransfer(tcb_t *thread); void schedule(void); void chooseThread(void); void switchToThread(tcb_t *thread); void switchToIdleThread(void); void setDomain(tcb_t *tptr, dom_t dom); void setPriority(tcb_t *tptr, prio_t prio); void setMCPriority(tcb_t *tptr, prio_t mcp); void scheduleTCB(tcb_t *tptr); void possibleSwitchTo(tcb_t *tptr); void setThreadState(tcb_t *tptr, _thread_state_t ts); void timerTick(void); void rescheduleRequired(void); /* declare that the thread has had its registers (in its user_context_t) modified and it * should ignore any 'efficient' restores next time it is run, and instead restore all * registers into their correct place */ void Arch_postModifyRegisters(tcb_t *tptr); #endif