test: cover schedTest
This commit is contained in:
1 parent
c31ac87199
commit
6c6c8d8b1a
1 file changed
+153
+153
@@ -942,3 +942,156 @@ KTEST(threadStopEarlyWakesAParentGenuinelyBlockedWaitingForSigChldOnStop)
|
||||
KT_NE(t, child, threadInvalidId);
|
||||
threadAt(child)->parentId = parent;
|
||||
|
||||
/* Same real-handler-required setup as
|
||||
threadKillEarlyWakesAParentGenuinelyBlockedWaitingForSigChld above --
|
||||
sigChld's default disposition is Ignore, so sigWouldDeliver would
|
||||
(correctly) decline to early-wake without one. */
|
||||
sigSetHandler(threadAt(parent), sigChld, 0x40005000ull, 0, 0);
|
||||
|
||||
threadAt(parent)->state = threadBlocked;
|
||||
threadAt(parent)->waitChannel = &channel;
|
||||
|
||||
KT_TRUE(t, threadStop(child));
|
||||
KT_EQ(t, threadAt(parent)->state, threadRunnable);
|
||||
|
||||
KT_TRUE(t, threadContinue(child));
|
||||
KT_TRUE(t, threadDiscard(child));
|
||||
KT_TRUE(t, threadDiscard(parent));
|
||||
}
|
||||
|
||||
KTEST(threadContinueRaisesSigChldAgainstParentIdOnTheActualResumeTransition)
|
||||
{
|
||||
uint32 parent = threadCreate("contChldParent", noopThreadEntry);
|
||||
KT_NE(t, parent, threadInvalidId);
|
||||
uint32 child = threadCreate("contChldVictim", noopThreadEntry);
|
||||
KT_NE(t, child, threadInvalidId);
|
||||
threadAt(child)->parentId = parent;
|
||||
|
||||
KT_TRUE(t, threadStop(child));
|
||||
/* Drain the stop's own notification first (see the "already stopped"
|
||||
test above for why) so the assertion below is unambiguously about
|
||||
threadContinue's OWN raise, not a leftover bit from the stop. */
|
||||
threadAt(parent)->sigPending &= ~(1ull << sigChld);
|
||||
|
||||
KT_TRUE(t, threadContinue(child));
|
||||
KT_EQU(t, threadAt(parent)->sigPending & (1ull << sigChld), (1ull << sigChld));
|
||||
|
||||
KT_TRUE(t, threadDiscard(child));
|
||||
KT_TRUE(t, threadDiscard(parent));
|
||||
}
|
||||
|
||||
KTEST(threadContinueOnATargetThatWasNeverStoppedRaisesNothing)
|
||||
{
|
||||
uint32 parent = threadCreate("contChldParent2", noopThreadEntry);
|
||||
KT_NE(t, parent, threadInvalidId);
|
||||
uint32 child = threadCreate("contChldVictim2", noopThreadEntry);
|
||||
KT_NE(t, child, threadInvalidId);
|
||||
threadAt(child)->parentId = parent;
|
||||
|
||||
KT_EQ(t, threadAt(child)->state, threadRunnable);
|
||||
KT_FALSE(t, threadContinue(child));
|
||||
KT_EQU(t, threadAt(parent)->sigPending & (1ull << sigChld), 0ull);
|
||||
|
||||
KT_TRUE(t, threadDiscard(child));
|
||||
KT_TRUE(t, threadDiscard(parent));
|
||||
}
|
||||
|
||||
KTEST(threadStopAgainstAnOrphanWithADeadParentIdRaisesNothing)
|
||||
{
|
||||
uint32 deadParent = threadCreate("stopDeadParent", noopThreadEntry);
|
||||
KT_NE(t, deadParent, threadInvalidId);
|
||||
KT_TRUE(t, threadKill(deadParent));
|
||||
KT_EQ(t, threadAt(deadParent)->state, threadDead);
|
||||
|
||||
uint32 orphan = threadCreate("stopOrphan", noopThreadEntry);
|
||||
KT_NE(t, orphan, threadInvalidId);
|
||||
threadAt(orphan)->parentId = deadParent;
|
||||
|
||||
/* Same sigRaise targetId-state guard as
|
||||
threadKillAgainstAnOrphanWithADeadParentIdRaisesNothing above -- an
|
||||
orphan whose spawning parent already died has nowhere for its own
|
||||
stop notification to land either. */
|
||||
KT_TRUE(t, threadStop(orphan));
|
||||
KT_EQ(t, threadAt(orphan)->state, threadStopped);
|
||||
KT_EQU(t, threadAt(deadParent)->sigPending & (1ull << sigChld), 0ull);
|
||||
|
||||
KT_TRUE(t, threadContinue(orphan));
|
||||
KT_TRUE(t, threadReap(deadParent));
|
||||
KT_TRUE(t, threadDiscard(orphan));
|
||||
}
|
||||
|
||||
KTEST(threadWakeForSignalRejectsIdleOutOfRangeAndNeverCreatedSlots)
|
||||
{
|
||||
KT_FALSE(t, threadWakeForSignal(0));
|
||||
KT_FALSE(t, threadWakeForSignal(threadCapacity()));
|
||||
KT_FALSE(t, threadWakeForSignal(threadCapacity() + 1000));
|
||||
|
||||
uint32 neverUsed = threadCount();
|
||||
if (neverUsed < threadCapacity())
|
||||
KT_FALSE(t, threadWakeForSignal(neverUsed));
|
||||
}
|
||||
|
||||
KTEST(threadWakeForSignalMovesSleepingOrBlockedThreadToRunnable)
|
||||
{
|
||||
uint32 id = threadCreate("wakeFromSleep", noopThreadEntry);
|
||||
KT_NE(t, id, threadInvalidId);
|
||||
|
||||
threadAt(id)->state = threadSleeping;
|
||||
KT_TRUE(t, threadWakeForSignal(id));
|
||||
KT_EQ(t, threadAt(id)->state, threadRunnable);
|
||||
|
||||
threadAt(id)->state = threadBlocked;
|
||||
KT_TRUE(t, threadWakeForSignal(id));
|
||||
KT_EQ(t, threadAt(id)->state, threadRunnable);
|
||||
|
||||
KT_TRUE(t, threadDiscard(id));
|
||||
}
|
||||
|
||||
KTEST(threadWakeForSignalIsNoOpOnRunnableRunningStoppedDeadAndUnused)
|
||||
{
|
||||
uint32 id = threadCreate("wakeNoOp", noopThreadEntry);
|
||||
KT_NE(t, id, threadInvalidId);
|
||||
|
||||
/* Already Runnable/Running: nothing to force. */
|
||||
KT_EQ(t, threadAt(id)->state, threadRunnable);
|
||||
KT_FALSE(t, threadWakeForSignal(id));
|
||||
KT_EQ(t, threadAt(id)->state, threadRunnable);
|
||||
|
||||
threadAt(id)->state = threadRunning;
|
||||
KT_FALSE(t, threadWakeForSignal(id));
|
||||
KT_EQ(t, threadAt(id)->state, threadRunning);
|
||||
|
||||
/* Stopped is the one deliberately EXCLUDED state -- an ordinary signal
|
||||
must never undo job control's SIGSTOP; only threadContinue (an
|
||||
explicit SIGCONT) may ever move a Stopped thread. This is what
|
||||
signal.c's sigRaise relies on for a signal raised against a Stopped
|
||||
target: sigWouldDeliver may say yes, but threadWakeForSignal still
|
||||
refuses. */
|
||||
KT_TRUE(t, threadStop(id));
|
||||
KT_FALSE(t, threadWakeForSignal(id));
|
||||
KT_EQ(t, threadAt(id)->state, threadStopped);
|
||||
KT_TRUE(t, threadContinue(id));
|
||||
|
||||
threadAt(id)->state = threadDead;
|
||||
KT_FALSE(t, threadWakeForSignal(id));
|
||||
KT_TRUE(t, threadReap(id));
|
||||
|
||||
/* threadUnused again after reap: still rejected. */
|
||||
KT_FALSE(t, threadWakeForSignal(id));
|
||||
}
|
||||
|
||||
KTEST(threadKillAcceptsStoppedThreadLikeRealSigkillOnAStoppedProcess)
|
||||
{
|
||||
uint32 id = threadCreate("killStopped", noopThreadEntry);
|
||||
KT_NE(t, id, threadInvalidId);
|
||||
|
||||
KT_TRUE(t, threadStop(id));
|
||||
KT_EQ(t, threadAt(id)->state, threadStopped);
|
||||
|
||||
KT_TRUE(t, threadKill(id));
|
||||
KT_EQ(t, threadAt(id)->state, threadDead);
|
||||
KT_EQU(t, threadAt(id)->exitCode, threadKilledExitCode);
|
||||
|
||||
KT_TRUE(t, threadReap(id));
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user