diff --git a/headers/private/kernel/RunQueueLink.h b/headers/private/kernel/RunQueueLink.h new file mode 100644 index 0000000000..79fdc60a1f --- /dev/null +++ b/headers/private/kernel/RunQueueLink.h @@ -0,0 +1,56 @@ +/* + * Copyright 2013 Haiku, Inc. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Paweł Dziepak, pdziepak@quarnos.org + */ +#ifndef RUN_QUEUE_LINK_H +#define RUN_QUEUE_LINK_H + + +template +struct RunQueueLink { + RunQueueLink(); + + unsigned int fPriority; + Element* fPrevious; + Element* fNext; +}; + +template +class RunQueueLinkImpl { +public: + inline RunQueueLink* GetRunQueueLink(); + +private: + RunQueueLink fRunQueueLink; +}; + + +#if KDEBUG +template +RunQueueLink::RunQueueLink() + : + fPrevious(NULL), + fNext(NULL) +{ +} +#else +template +RunQueueLink::RunQueueLink() +{ +} +#endif + + +template +RunQueueLink* +RunQueueLinkImpl::GetRunQueueLink() +{ + return &fRunQueueLink; +} + + +#endif // RUN_QUEUE_LINK_H + diff --git a/headers/private/kernel/thread_types.h b/headers/private/kernel/thread_types.h index 1c06271a50..637c5bed42 100644 --- a/headers/private/kernel/thread_types.h +++ b/headers/private/kernel/thread_types.h @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -409,7 +410,8 @@ private: }; -struct Thread : TeamThreadIteratorEntry, KernelReferenceable { +struct Thread : TeamThreadIteratorEntry, KernelReferenceable, + RunQueueLinkImpl { int32 flags; // summary of events relevant in interrupt // handlers (signals pending, user debugging // enabled, etc.) diff --git a/src/system/kernel/scheduler/RunQueue.h b/src/system/kernel/scheduler/RunQueue.h new file mode 100644 index 0000000000..9485a1c4f8 --- /dev/null +++ b/src/system/kernel/scheduler/RunQueue.h @@ -0,0 +1,353 @@ +/* + * Copyright 2013 Haiku, Inc. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Paweł Dziepak, pdziepak@quarnos.org + */ +#ifndef RUN_QUEUE_H +#define RUN_QUEUE_H + + +#include +#include + + +template +class RunQueueStandardGetLink { +private: + typedef RunQueueLink Link; + +public: + inline Link* operator()(Element* element) const; +}; + +template Element::*LinkMember> +class RunQueueMemberGetLink { +private: + typedef RunQueueLink Link; + +public: + inline Link* operator()(Element* element) const; +}; + +#define RUN_QUEUE_TEMPLATE_LIST \ + template +#define RUN_QUEUE_CLASS_NAME RunQueue + +template > +class RunQueue { +public: + class ConstIterator { + public: + ConstIterator(); + ConstIterator(const RunQueue* list); + + inline ConstIterator& operator=(const ConstIterator& other); + + bool HasNext() const; + Element* Next(); + + void Rewind(); + + private: + inline void _FindNextPriority(); + + const RUN_QUEUE_CLASS_NAME* fList; + unsigned int fPriority; + Element* fNext; + + static GetLink sGetLink; + }; + + RunQueue(); + + inline status_t GetInitStatus(); + + inline Element* PeekMaximum(); + inline Element* PeekSecondMaximum(); + + inline void PushFront(Element* element, unsigned int priority); + inline void PushBack(Element* elementt, unsigned int priority); + + inline void Remove(Element* element); + + inline Element* GetHead(unsigned int priority) const; + + inline ConstIterator GetConstIterator() const; + +private: + status_t fInitStatus; + + Bitmap fBitmap; + + Element* fHeads[MaxPriority + 1]; + Element* fTails[MaxPriority + 1]; + + static GetLink sGetLink; +}; + + +template +RunQueueLink* +RunQueueStandardGetLink::operator()(Element* element) const +{ + return element->GetRunQueueLink(); +} + + +template Element::*LinkMember> +RunQueueLink* +RunQueueMemberGetLink::operator()(Element* element) const +{ + return &(element->*LinkMember); +} + + +RUN_QUEUE_TEMPLATE_LIST +RUN_QUEUE_CLASS_NAME::ConstIterator::ConstIterator() + : + fList(NULL) +{ +} + + +RUN_QUEUE_TEMPLATE_LIST +RUN_QUEUE_CLASS_NAME::ConstIterator::ConstIterator(const RunQueue* list) + : + fList(list) +{ + Rewind(); +} + + +RUN_QUEUE_TEMPLATE_LIST +typename RUN_QUEUE_CLASS_NAME::ConstIterator& +RUN_QUEUE_CLASS_NAME::ConstIterator::operator=(const ConstIterator& other) +{ + fList = other.fList; + fPriority = other.fPriority; + fNext = other.fNext; + + return *this; +} + + +RUN_QUEUE_TEMPLATE_LIST +bool +RUN_QUEUE_CLASS_NAME::ConstIterator::HasNext() const +{ + return fNext != NULL; +} + + +RUN_QUEUE_TEMPLATE_LIST +Element* +RUN_QUEUE_CLASS_NAME::ConstIterator::Next() +{ + ASSERT(HasNext()); + + Element* current = fNext; + RunQueueLink* link = sGetLink(fNext); + + fNext = link->fNext; + if (fNext == NULL) + _FindNextPriority(); + + return current; +} + + +RUN_QUEUE_TEMPLATE_LIST +void +RUN_QUEUE_CLASS_NAME::ConstIterator::Rewind() +{ + ASSERT(fList != NULL); + + fPriority = MaxPriority; + fNext = fList->GetHead(fPriority); + if (fNext == NULL) + _FindNextPriority(); +} + + +RUN_QUEUE_TEMPLATE_LIST +void +RUN_QUEUE_CLASS_NAME::ConstIterator::_FindNextPriority() +{ + ASSERT(fList != NULL); + + while (fPriority-- > 0) { + fNext = fList->GetHead(fPriority); + if (fNext != NULL) + break; + } +} + + +RUN_QUEUE_TEMPLATE_LIST +RUN_QUEUE_CLASS_NAME::RunQueue() + : + fBitmap(MaxPriority + 1) +{ + fInitStatus = fBitmap.GetInitStatus(); + + memset(fHeads, 0, sizeof(fHeads)); + memset(fTails, 0, sizeof(fTails)); +} + + +RUN_QUEUE_TEMPLATE_LIST +status_t +RUN_QUEUE_CLASS_NAME::GetInitStatus() +{ + return fInitStatus; +} + + +RUN_QUEUE_TEMPLATE_LIST +Element* +RUN_QUEUE_CLASS_NAME::PeekMaximum() +{ + int priority = fBitmap.GetHighestSet(); + if (priority < 0) + return NULL; + + ASSERT((unsigned int)priority <= MaxPriority); + ASSERT(fHeads[priority] != NULL); + + Element* element = fHeads[priority]; + RunQueueLink* elementLink = sGetLink(element); + + ASSERT(elementLink->fPriority == (unsigned int)priority); + ASSERT(fTails[priority] != NULL); + ASSERT(elementLink->fPrevious == NULL); + + return element; +} + + +RUN_QUEUE_TEMPLATE_LIST +Element* +RUN_QUEUE_CLASS_NAME::PeekSecondMaximum() +{ + int priority = fBitmap.GetHighestSet(); + if (priority < 0) + return NULL; + + fBitmap.Clear(priority); + Element* element = PeekMaximum(); + fBitmap.Set(priority); + + return element; +} + + +RUN_QUEUE_TEMPLATE_LIST +void +RUN_QUEUE_CLASS_NAME::PushFront(Element* element, + unsigned int priority) +{ + ASSERT(priority <= MaxPriority); + + RunQueueLink* elementLink = sGetLink(element); + + ASSERT(elementLink->fPrevious == NULL); + ASSERT(elementLink->fNext == NULL); + + ASSERT((fHeads[priority] == NULL && fTails[priority] == NULL) + || (fHeads[priority] != NULL && fTails[priority] != NULL)); + + elementLink->fPriority = priority; + elementLink->fNext = fHeads[priority]; + if (fHeads[priority]) + sGetLink(fHeads[priority])->fPrevious = element; + else + fTails[priority] = element; + fHeads[priority] = element; + + fBitmap.Set(priority); +} + + +RUN_QUEUE_TEMPLATE_LIST +void +RUN_QUEUE_CLASS_NAME::PushBack(Element* element, + unsigned int priority) +{ + ASSERT(priority <= MaxPriority); + + RunQueueLink* elementLink = sGetLink(element); + + ASSERT(elementLink->fPrevious == NULL); + ASSERT(elementLink->fNext == NULL); + + ASSERT((fHeads[priority] == NULL && fTails[priority] == NULL) + || (fHeads[priority] != NULL && fTails[priority] != NULL)); + + elementLink->fPriority = priority; + elementLink->fPrevious = fTails[priority]; + if (fTails[priority]) + sGetLink(fTails[priority])->fNext = element; + else + fHeads[priority] = element; + fTails[priority] = element; + + fBitmap.Set(priority); +} + + +RUN_QUEUE_TEMPLATE_LIST +void +RUN_QUEUE_CLASS_NAME::Remove(Element* element) +{ + RunQueueLink* elementLink = sGetLink(element); + unsigned int priority = elementLink->fPriority; + + ASSERT(elementLink->fPrevious != NULL || fHeads[priority] == element); + ASSERT(elementLink->fNext != NULL || fTails[priority] == element); + + if (elementLink->fPrevious != NULL) + sGetLink(elementLink->fPrevious)->fNext = elementLink->fNext; + else + fHeads[priority] = elementLink->fNext; + if (elementLink->fNext != NULL) + sGetLink(elementLink->fNext)->fPrevious = elementLink->fPrevious; + else + fTails[priority] = elementLink->fPrevious; + + ASSERT((fHeads[priority] == NULL && fTails[priority] == NULL) + || (fHeads[priority] != NULL && fTails[priority] != NULL)); + + if (fHeads[priority] == NULL) + fBitmap.Clear(priority); + +#if KDEBUG + elementLink->fPrevious = NULL; + elementLink->fNext = NULL; +#endif +} + + +RUN_QUEUE_TEMPLATE_LIST +Element* +RUN_QUEUE_CLASS_NAME::GetHead(unsigned int priority) const +{ + ASSERT(priority <= MaxPriority); + return fHeads[priority]; +} + + +RUN_QUEUE_TEMPLATE_LIST +typename RUN_QUEUE_CLASS_NAME::ConstIterator +RUN_QUEUE_CLASS_NAME::GetConstIterator() const +{ + return ConstIterator(this); +} + + +#endif // RUN_QUEUE_H +