aboutsummaryrefslogtreecommitdiffstats
path: root/include/distortos/internal/scheduler/ThreadControlBlock.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'include/distortos/internal/scheduler/ThreadControlBlock.hpp')
-rw-r--r--include/distortos/internal/scheduler/ThreadControlBlock.hpp336
1 files changed, 336 insertions, 0 deletions
diff --git a/include/distortos/internal/scheduler/ThreadControlBlock.hpp b/include/distortos/internal/scheduler/ThreadControlBlock.hpp
new file mode 100644
index 0000000..6d6f458
--- /dev/null
+++ b/include/distortos/internal/scheduler/ThreadControlBlock.hpp
@@ -0,0 +1,336 @@
+/**
+ * \file
+ * \brief ThreadControlBlock class header
+ *
+ * \author Copyright (C) 2014-2015 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
+ *
+ * \par License
+ * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
+ * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDE_DISTORTOS_INTERNAL_SCHEDULER_THREADCONTROLBLOCK_HPP_
+#define INCLUDE_DISTORTOS_INTERNAL_SCHEDULER_THREADCONTROLBLOCK_HPP_
+
+#include "distortos/internal/scheduler/RoundRobinQuantum.hpp"
+#include "distortos/internal/scheduler/ThreadListNode.hpp"
+
+#include "distortos/internal/synchronization/MutexList.hpp"
+
+#include "distortos/architecture/Stack.hpp"
+
+#include "distortos/SchedulingPolicy.hpp"
+#include "distortos/ThreadState.hpp"
+
+#include "estd/TypeErasedFunctor.hpp"
+
+namespace distortos
+{
+
+class SignalsReceiver;
+
+namespace internal
+{
+
+class SignalsReceiverControlBlock;
+class ThreadList;
+class ThreadGroupControlBlock;
+
+/// ThreadControlBlock class is a simple description of a Thread
+class ThreadControlBlock : public ThreadListNode
+{
+public:
+
+ /// reason of thread unblocking
+ enum class UnblockReason : uint8_t
+ {
+ /// explicit request to unblock the thread - normal unblock
+ unblockRequest,
+ /// timeout - unblock via software timer
+ timeout,
+ /// signal handler - unblock to deliver unmasked signal
+ signal,
+ };
+
+ /// UnblockFunctor is a functor executed when unblocking the thread, it receives two parameter - a reference to
+ /// ThreadControlBlock that is being unblocked and the reason of thread unblocking
+ class UnblockFunctor : public estd::TypeErasedFunctor<void(ThreadControlBlock&, UnblockReason)>
+ {
+
+ };
+
+ /**
+ * \brief ThreadControlBlock constructor.
+ *
+ * \param [in] stack is an rvalue reference to architecture::Stack object which will be adopted for this thread
+ * \param [in] priority is the thread's priority, 0 - lowest, UINT8_MAX - highest
+ * \param [in] schedulingPolicy is the scheduling policy of the thread
+ * \param [in] threadGroupControlBlock is a pointer to ThreadGroupControlBlock to which this object will be added,
+ * nullptr to inherit thread group from currently running thread
+ * \param [in] signalsReceiver is a pointer to SignalsReceiver object for this thread, nullptr to disable reception
+ * of signals for this thread
+ * \param [in] owner is a reference to Thread object that owns this ThreadControlBlock
+ */
+
+ ThreadControlBlock(architecture::Stack&& stack, uint8_t priority, SchedulingPolicy schedulingPolicy,
+ ThreadGroupControlBlock* threadGroupControlBlock, SignalsReceiver* signalsReceiver, Thread& owner);
+
+ /**
+ * \brief ThreadControlBlock's destructor
+ */
+
+ ~ThreadControlBlock();
+
+ /**
+ * \brief Hook function executed when thread is added to scheduler.
+ *
+ * If threadGroupControlBlock_ is nullptr, it is inherited from currently running thread. Then this object is added
+ * to the thread group (if it is valid).
+ *
+ * \attention This function should be called only by Scheduler::addInternal().
+ *
+ * \return 0 on success, error code otherwise:
+ * - EINVAL - inherited thread group is invalid;
+ */
+
+ int addHook();
+
+ /**
+ * \brief Block hook function of thread
+ *
+ * Saves pointer to UnblockFunctor.
+ *
+ * \attention This function should be called only by Scheduler::blockInternal().
+ *
+ * \param [in] unblockFunctor is a pointer to UnblockFunctor which will be executed in unblockHook()
+ */
+
+ void blockHook(const UnblockFunctor* const unblockFunctor)
+ {
+ unblockFunctor_ = unblockFunctor;
+ }
+
+ /**
+ * \return pointer to list that has this object
+ */
+
+ ThreadList* getList() const
+ {
+ return list_;
+ }
+
+ /**
+ * \return reference to list of mutexes (mutex control blocks) with enabled priority protocol owned by this thread
+ */
+
+ MutexList& getOwnedProtocolMutexList()
+ {
+ return ownedProtocolMutexList_;
+ }
+
+ /**
+ * \return reference to Thread object that owns this ThreadControlBlock
+ */
+
+ Thread& getOwner() const
+ {
+ return owner_;
+ }
+
+ /**
+ * \return reference to internal RoundRobinQuantum object
+ */
+
+ RoundRobinQuantum& getRoundRobinQuantum()
+ {
+ return roundRobinQuantum_;
+ }
+
+ /**
+ * \return scheduling policy of the thread
+ */
+
+ SchedulingPolicy getSchedulingPolicy() const
+ {
+ return schedulingPolicy_;
+ }
+
+ /**
+ * \return pointer to SignalsReceiverControlBlock object for this thread, nullptr if this thread cannot receive
+ * signals
+ */
+
+ SignalsReceiverControlBlock* getSignalsReceiverControlBlock() const
+ {
+ return signalsReceiverControlBlock_;
+ }
+
+ /**
+ * \return reference to internal Stack object
+ */
+
+ architecture::Stack& getStack()
+ {
+ return stack_;
+ }
+
+ /**
+ * \return current state of object
+ */
+
+ ThreadState getState() const
+ {
+ return state_;
+ }
+
+ /**
+ * \brief Sets the list that has this object.
+ *
+ * \param [in] list is a pointer to list that has this object
+ */
+
+ void setList(ThreadList* const list)
+ {
+ list_ = list;
+ }
+
+ /**
+ * \brief Changes priority of thread.
+ *
+ * If the priority really changes, the position in the thread list is adjusted and context switch may be requested.
+ *
+ * \param [in] priority is the new priority of thread
+ * \param [in] alwaysBehind selects the method of ordering when lowering the priority
+ * - false - the thread is moved to the head of the group of threads with the new priority (default),
+ * - true - the thread is moved to the tail of the group of threads with the new priority.
+ */
+
+ void setPriority(uint8_t priority, bool alwaysBehind = {});
+
+ /**
+ * \param [in] priorityInheritanceMutexControlBlock is a pointer to MutexControlBlock (with PriorityInheritance
+ * protocol) that blocks this thread
+ */
+
+ void setPriorityInheritanceMutexControlBlock(const MutexControlBlock* const priorityInheritanceMutexControlBlock)
+ {
+ priorityInheritanceMutexControlBlock_ = priorityInheritanceMutexControlBlock;
+ }
+
+ /**
+ * param [in] schedulingPolicy is the new scheduling policy of the thread
+ */
+
+ void setSchedulingPolicy(SchedulingPolicy schedulingPolicy);
+
+ /**
+ * \param [in] state is the new state of object
+ */
+
+ void setState(const ThreadState state)
+ {
+ state_ = state;
+ }
+
+ /**
+ * \brief Hook function called when context is switched to this thread.
+ *
+ * Sets global _impure_ptr (from newlib) to thread's \a reent_ member variable.
+ *
+ * \attention This function should be called only by Scheduler::switchContext().
+ */
+
+ void switchedToHook()
+ {
+ _impure_ptr = &reent_;
+ }
+
+ /**
+ * \brief Unblock hook function of thread
+ *
+ * Resets round-robin's quantum and executes unblock functor saved in blockHook().
+ *
+ * \attention This function should be called only by Scheduler::unblockInternal().
+ *
+ * \param [in] unblockReason is the new reason of unblocking of the thread
+ */
+
+ void unblockHook(UnblockReason unblockReason);
+
+ /**
+ * \brief Updates boosted priority of the thread.
+ *
+ * This function should be called after all operations involving this thread and a mutex with enabled priority
+ * protocol.
+ *
+ * \param [in] boostedPriority is the initial boosted priority, this should be effective priority of the thread that
+ * is about to be blocked on a mutex owned by this thread, default - 0
+ */
+
+ void updateBoostedPriority(uint8_t boostedPriority = {});
+
+ ThreadControlBlock(const ThreadControlBlock&) = delete;
+ ThreadControlBlock(ThreadControlBlock&&) = default;
+ const ThreadControlBlock& operator=(const ThreadControlBlock&) = delete;
+ ThreadControlBlock& operator=(ThreadControlBlock&&) = delete;
+
+private:
+
+ /**
+ * \brief Repositions the thread on the list it's currently on.
+ *
+ * This function should be called when thread's effective priority changes.
+ *
+ * \attention list_ must not be nullptr
+ *
+ * \param [in] loweringBefore selects the method of ordering when lowering the priority (it must be false when the
+ * priority is raised!):
+ * - true - the thread is moved to the head of the group of threads with the new priority, this is accomplished by
+ * temporarily boosting effective priority by 1,
+ * - false - the thread is moved to the tail of the group of threads with the new priority.
+ */
+
+ void reposition(bool loweringBefore);
+
+ /// internal stack object
+ architecture::Stack stack_;
+
+ /// reference to Thread object that owns this ThreadControlBlock
+ Thread& owner_;
+
+ /// list of mutexes (mutex control blocks) with enabled priority protocol owned by this thread
+ MutexList ownedProtocolMutexList_;
+
+ /// pointer to MutexControlBlock (with PriorityInheritance protocol) that blocks this thread
+ const MutexControlBlock* priorityInheritanceMutexControlBlock_;
+
+ /// pointer to list that has this object
+ ThreadList* list_;
+
+ /// pointer to ThreadGroupControlBlock with which this object is associated
+ ThreadGroupControlBlock* threadGroupControlBlock_;
+
+ /// functor executed in unblockHook()
+ const UnblockFunctor* unblockFunctor_;
+
+ /// pointer to SignalsReceiverControlBlock object for this thread, nullptr if this thread cannot receive signals
+ SignalsReceiverControlBlock* signalsReceiverControlBlock_;
+
+ /// newlib's _reent structure with thread-specific data
+ _reent reent_;
+
+ /// round-robin quantum
+ RoundRobinQuantum roundRobinQuantum_;
+
+ /// scheduling policy of the thread
+ SchedulingPolicy schedulingPolicy_;
+
+ /// current state of object
+ ThreadState state_;
+};
+
+} // namespace internal
+
+} // namespace distortos
+
+#endif // INCLUDE_DISTORTOS_INTERNAL_SCHEDULER_THREADCONTROLBLOCK_HPP_