Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions preempt/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,7 @@ target_link_libraries(preempt
PRIVATE sched
PRIVATE protocol
)

if(BUILD_TEST)
add_subdirectory(test)
endif()
Comment on lines +44 to +46
14 changes: 14 additions & 0 deletions preempt/src/xqueue/xqueue.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,14 @@ XResult XQueueManager::Add(XQueueHandle *xq_hp, HwQueueHandle hwq_h, int64_t lev
return kXSchedErrorNotFound;
}

if (level > hwq_shptr->GetMaxSupportedLevel()) {
XWARN("preempt level %d is not supported by HwQueue 0x" FMT_64X
", max supported level is %d",
static_cast<int>(level), hwq_h,
hwq_shptr->GetMaxSupportedLevel());
return kXSchedErrorNotSupported;
}
Comment on lines +27 to +33

if (hwq_shptr->GetXQueue() != nullptr) {
XQueueHandle xq_h = hwq_shptr->GetXQueue()->GetHandle();
auto it = xqs_.find(xq_h);
Expand Down Expand Up @@ -285,6 +293,12 @@ EXPORT_C_FUNC XResult XQueueSetPreemptLevel(XQueueHandle xq, XPreemptLevel level
XWARN("XQueue with handle 0x" FMT_64X " does not support dynamic level", xq);
return kXSchedErrorNotSupported;
}
const auto hwq_shptr = xq_shptr->GetHwQueue();
if (hwq_shptr == nullptr || level > hwq_shptr->GetMaxSupportedLevel()) {
XWARN("preempt level %d is not supported by XQueue 0x" FMT_64X,
level, xq);
return kXSchedErrorNotSupported;
}
Comment on lines +296 to +301
xq_shptr->SetPreemptLevel(level);
return kXSchedSuccess;
}
Expand Down
14 changes: 14 additions & 0 deletions preempt/test/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
add_executable(preempt_level_capability_test
preempt_level_capability_test.cpp
)
target_compile_options(preempt_level_capability_test PRIVATE
-Wall
-Wextra
-Werror
)
target_link_libraries(preempt_level_capability_test PRIVATE
preempt
utils
)
add_test(NAME preempt_level_capability_test
COMMAND preempt_level_capability_test)
90 changes: 90 additions & 0 deletions preempt/test/preempt_level_capability_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
#include <iostream>
#include <memory>
#include <string>

#include "xsched/preempt/hal/hw_queue.h"
#include "xsched/xqueue.h"

namespace
{

using namespace xsched::preempt;

class CapabilityQueue final : public HwQueue
{
public:
virtual void Launch(std::shared_ptr<HwCommand>) override { }
virtual void Synchronize() override { }
virtual void Deactivate() override { ++deactivate_count; }
virtual void Reactivate(const CommandLog &) override
{
++reactivate_count;
}

virtual XDevice GetDevice() override { return 0; }
virtual HwQueueHandle GetHandle() override { return kHandle; }
virtual bool SupportDynamicLevel() override { return true; }
virtual XPreemptLevel GetMaxSupportedLevel() override
{
return kPreemptLevelDeactivate;
}

static constexpr HwQueueHandle kHandle = 0xc0ffee;
int deactivate_count = 0;
int reactivate_count = 0;
};

bool Expect(bool condition, const std::string &message)
{
if (condition) return true;
std::cerr << "FAIL: " << message << '\n';
return false;
}

} // namespace

int main()
{
using namespace xsched::preempt;

auto queue = std::make_shared<CapabilityQueue>();
bool ok = Expect(
HwQueueManager::Add(CapabilityQueue::kHandle,
[queue]() { return queue; })
== kXSchedSuccess,
"register Level-2 HwQueue");

XQueueHandle xqueue = 0;
ok &= Expect(XQueueCreate(&xqueue, CapabilityQueue::kHandle,
kPreemptLevelInterrupt,
kQueueCreateFlagNone)
== kXSchedErrorNotSupported,
"reject Level-3 creation on a Level-2 HwQueue");
ok &= Expect(XQueueCreate(&xqueue, CapabilityQueue::kHandle,
kPreemptLevelDeactivate,
kQueueCreateFlagNone)
== kXSchedSuccess,
"create Level-2 XQueue");
if (xqueue != 0) {
ok &= Expect(XQueueSetPreemptLevel(xqueue,
kPreemptLevelInterrupt)
== kXSchedErrorNotSupported,
"reject dynamic upgrade beyond Level-2");
ok &= Expect(XQueueSuspend(xqueue, kQueueSuspendFlagNone) == kXSchedSuccess,
"suspend Level-2 XQueue");
ok &= Expect(queue->deactivate_count == 1,
"suspend must call Deactivate");
ok &= Expect(XQueueResume(xqueue, kQueueResumeFlagNone) == kXSchedSuccess,
"resume Level-2 XQueue");
ok &= Expect(queue->reactivate_count == 1,
"resume must call Reactivate");
ok &= Expect(XQueueDestroy(xqueue) == kXSchedSuccess,
"destroy Level-2 XQueue");
}
ok &= Expect(HwQueueDestroy(CapabilityQueue::kHandle) == kXSchedSuccess,
"destroy Level-2 HwQueue");

if (!ok) return 1;
std::cout << "HwQueue preemption capability tests passed.\n";
return 0;
}