SMP: reproduce finalized test case

Test case for threads abort issue.

Signed-off-by: Eugeniy Paltsev <Eugeniy.Paltsev@synopsys.com>
Signed-off-by: Evgeniy Paltsev <PaltsevEvgeniy@gmail.com>
diff --git a/tests/kernel/smp/src/main.c b/tests/kernel/smp/src/main.c
index 0e98d22..0adf705 100644
--- a/tests/kernel/smp/src/main.c
+++ b/tests/kernel/smp/src/main.c
@@ -276,6 +276,84 @@
 	}
 }
 
+static void __no_optimization thread_ab_entry(void *p1, void *p2, void *p3)
+{
+	ARG_UNUSED(p1);
+	ARG_UNUSED(p2);
+	ARG_UNUSED(p3);
+
+	while (true) {
+	}
+}
+
+#define SPAWN_AB_PRIO K_PRIO_COOP(10)
+
+/**
+ * @brief Verify the code path when we do context switch in k_thread_abort on SMP system
+ *
+ * @ingroup kernel_smp_tests
+ *
+ * @details test logic:
+ * - The ztest thread has cooperative priority.
+ * - From ztest thread we spawn N number of cooperative threads, where N = number of CPUs.
+ *   - The spawned cooperative are executing infinite loop (so they occupy CPU core until they are
+ *     aborted).
+ *   - We have (number of CPUs - 1) spawned threads run and executing infinite loop, as current CPU
+ *     is occupied by ztest cooperative thread. Due to that the last of spawned threads is ready but
+ *     not executing.
+ * - We abort spawned threads one-by-one from the ztest thread.
+ *   - At the first k_thread_abort call the ztest thread will be preempted by the remaining spawned
+ *     thread which has higher priority than ztest thread.
+ *     But... k_thread_abort call should has destroyed one of the spawned threads, so ztest thread
+ *     should have a CPU available to run on.
+ * - We expect that all spawned threads will be aborted successfully.
+ *
+ * This was the test case for zephyrproject-rtos/zephyr#58040 issue where this test caused system
+ * hang.
+ */
+
+ZTEST(smp, test_coop_switch_in_abort)
+{
+	k_tid_t tid[MAX_NUM_THREADS];
+	unsigned int num_threads = arch_num_cpus();
+	unsigned int i;
+
+	zassert_true(_current->base.prio < 0, "test case relies on ztest thread be cooperative");
+	zassert_true(_current->base.prio > SPAWN_AB_PRIO,
+		     "spawn test need to have higher priority than ztest thread");
+
+	/* Spawn N number of cooperative threads, where N = number of CPUs */
+	for (i = 0; i < num_threads; i++) {
+		tid[i] = k_thread_create(&tthread[i], tstack[i],
+					 STACK_SIZE, thread_ab_entry,
+					 NULL, NULL, NULL,
+					 SPAWN_AB_PRIO, 0, K_NO_WAIT);
+	}
+
+	/* Wait for some time to let spawned threads on other cores run and start executing infinite
+	 * loop.
+	 */
+	k_busy_wait(DELAY_US * 4);
+
+	/* At this time we have (number of CPUs - 1) spawned threads run and executing infinite loop
+	 * on other CPU cores, as current CPU is occupied by this ztest cooperative thread.
+	 * Due to that the last of spawned threads is ready but not executing.
+	 */
+
+	/* Abort all spawned threads one-by-one. At the first k_thread_abort call the context
+	 * switch will happen and the last 'spawned' thread will start.
+	 * We should successfully abort all threads.
+	 */
+	for (i = 0; i < num_threads; i++) {
+		k_thread_abort(tid[i]);
+	}
+
+	/* Cleanup */
+	for (i = 0; i < num_threads; i++) {
+		zassert_equal(k_thread_join(tid[i], K_FOREVER), 0);
+	}
+}
+
 /**
  * @brief Test cooperative threads non-preemption
  *