Skip to content

Commit

Permalink
kfdtest: Add test for multiple thread event wait
Browse files Browse the repository at this point in the history
Multiple threads wait for the same event may cause race conditions.
This means that one thread may sleep until timeout for missing
event interrupt. This test simulates the 2nd thread missed the
event interrupt. New feature with even age tracking added in
hsaKmtWaitOnMultipleEvents_Ext can help elimating this race conditions.

Change-Id: Icab43240fd127208b18abbd7542d6444127ef0c7
Signed-off-by: James Zhu <James.Zhu@amd.com>
  • Loading branch information
James Zhu authored and James Zhu committed Jun 6, 2023
1 parent efdbf6c commit 1820ae0
Showing 1 changed file with 62 additions and 0 deletions.
62 changes: 62 additions & 0 deletions tests/kfdtest/src/KFDEventTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,68 @@ TEST_F(KFDEventTest, SignalEvent) {
TEST_END;
}

struct ThreadParams {
HsaEvent *m_pHsaEvent;
bool signaled_flag;
};

static unsigned int SignalThread(void* p) {
struct ThreadParams* pArgs = reinterpret_cast<struct ThreadParams*>(p);
uint64_t event_age = 1;

EXPECT_SUCCESS(hsaKmtWaitOnEvent_Ext(pArgs->m_pHsaEvent, HSA_EVENTTIMEOUT_INFINITE, &event_age));
pArgs->signaled_flag = true;
return 0;
}

TEST_F(KFDEventTest, SignalMultiThreadEventWait) {
TEST_START(TESTPROFILE_RUNALL);

if (m_VersionInfo.KernelInterfaceMajorVersion <= 1 &&
m_VersionInfo.KernelInterfaceMinorVersion < 14) {
LOG() << "event age tracking isn't supported in KFD. Exiting." << std::endl;
return;
}

PM4Queue queue;
HSAuint64 threadId[2];
struct ThreadParams params[2];

int defaultGPUNode = m_NodeInfo.HsaDefaultGPUNode();
ASSERT_GE(defaultGPUNode, 0) << "failed to get default GPU Node";

ASSERT_SUCCESS(CreateQueueTypeEvent(false, false, defaultGPUNode, &m_pHsaEvent));
ASSERT_NE(0, m_pHsaEvent->EventData.HWData2);

ASSERT_SUCCESS(queue.Create(defaultGPUNode));

params[0].m_pHsaEvent = m_pHsaEvent;
params[1].m_pHsaEvent = m_pHsaEvent;
params[0].signaled_flag = false;
params[1].signaled_flag = false;

ASSERT_EQ(true, StartThread(&SignalThread, &params[0], threadId[0]));
/* Wait for 1st thread sleep */
sleep(1);

queue.PlaceAndSubmitPacket(PM4ReleaseMemoryPacket(m_FamilyId, false,
m_pHsaEvent->EventData.HWData2, m_pHsaEvent->EventId));

/* Wait for 1st thread wake up */
while (params[0].signaled_flag == false) sleep(1);

/* start 2nd thread after interrupt already fired */
ASSERT_EQ(true, StartThread(&SignalThread, &params[1], threadId[1]));

WaitForThread(threadId[0]);
WaitForThread(threadId[1]);
EXPECT_SUCCESS(queue.Destroy());

ASSERT_EQ(true, params[1].signaled_flag);

TEST_END;
}

static uint64_t gettime() {
struct timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts);
Expand Down

0 comments on commit 1820ae0

Please sign in to comment.