in testing/ostest/signest.c [239:561]
void signest_test(void)
{
struct sched_param param;
pid_t waiterpid;
pid_t interferepid;
int total_signals;
int total_handled;
int total_nested;
int even_signals;
int odd_signals;
int prio;
int ret;
int i;
int j;
sem_init(&g_waiter_sem, 0, 0);
sem_init(&g_interferer_sem, 0, 0);
sem_init(&g_sem_thread_started, 0, 0);
sem_init(&g_sem_signal_finish, 0, 0);
g_waiter_running = false;
g_interferer_running = false;
g_done = false;
g_nestlevel = 0;
even_signals = 0;
odd_signals = 0;
g_even_handled = 0;
g_odd_handled = 0;
g_even_nested = 0;
g_odd_nested = 0;
g_nest_level = 0;
ret = sched_getparam(0, ¶m);
if (ret < 0)
{
printf("signest_test: ERROR sched_getparam() failed\n");
ASSERT(false);
param.sched_priority = PTHREAD_DEFAULT_PRIORITY;
}
/* Start waiter thread */
prio = param.sched_priority + 1;
printf("signest_test: Starting signal waiter task at priority %d\n", prio);
waiterpid = task_create("waiter", prio, STACKSIZE,
waiter_main, NULL);
if (waiterpid == ERROR)
{
printf("signest_test: ERROR failed to start waiter_main\n");
ASSERT(false);
return;
}
printf("signest_test: Started waiter_main pid=%d\n", waiterpid);
/* Start interfering thread */
prio++;
printf("signest_test: Starting interfering task at priority %d\n", prio);
interferepid = task_create("interfere", prio, STACKSIZE,
interfere_main, NULL);
if (interferepid == ERROR)
{
printf("signest_test: ERROR failed to start interfere_main\n");
ASSERT(false);
goto errout_with_waiter;
}
printf("signest_test: Started interfere_main pid=%d\n", interferepid);
/* Wait a bit */
FFLUSH();
sem_wait(&g_sem_thread_started);
/* Then signal the waiter thread with back-to-back signals, one masked
* and the other unmasked.
*/
for (i = 0; i < 10; i++)
{
for (j = 1; j < MAX_SIGNO; j += 2)
{
if (signest_catchable(j))
{
kill(waiterpid, j);
odd_signals++;
}
if (signest_catchable(j + 1))
{
kill(waiterpid, j + 1);
even_signals++;
}
wait_finish(waiterpid, j);
/* Even then odd */
if (signest_catchable(j + 1))
{
kill(waiterpid, j + 1);
even_signals++;
}
if (signest_catchable(j))
{
kill(waiterpid, j);
odd_signals++;
}
wait_finish(waiterpid, j);
}
}
/* Check the test results so far */
total_signals = odd_signals + even_signals;
total_handled = g_odd_handled + g_even_handled;
total_nested = g_odd_nested + g_even_nested;
printf("signest_test: Simple case:\n");
printf(" Total signalled %-3d Odd=%-3d Even=%-3d\n",
total_signals, odd_signals, even_signals);
printf(" Total handled %-3d Odd=%-3d Even=%-3d\n",
total_handled, g_odd_handled, g_even_handled);
printf(" Total nested %-3d Odd=%-3d Even=%-3d\n",
total_nested, g_odd_nested, g_even_nested);
/* Then signal the waiter thread with two signals pending. The
* sched_lock() assures that the first signal was not processed
* before the second was delivered.
*/
for (i = 0; i < 10; i++)
{
for (j = 1; j < MAX_SIGNO; j += 2)
{
/* Odd then even */
sched_lock();
if (signest_catchable(j))
{
kill(waiterpid, j);
odd_signals++;
}
if (signest_catchable(j + 1))
{
kill(waiterpid, j + 1);
even_signals++;
}
sched_unlock();
wait_finish(waiterpid, j);
/* Even then odd */
sched_lock();
if (signest_catchable(j + 1))
{
kill(waiterpid, j + 1);
even_signals++;
}
if (signest_catchable(j))
{
kill(waiterpid, j);
odd_signals++;
}
sched_unlock();
wait_finish(waiterpid, j);
}
}
/* Check the test results so far */
total_signals = odd_signals + even_signals;
total_handled = g_odd_handled + g_even_handled;
total_nested = g_odd_nested + g_even_nested;
printf("signest_test: With task locking\n");
printf(" Total signalled %-3d Odd=%-3d Even=%-3d\n",
total_signals, odd_signals, even_signals);
printf(" Total handled %-3d Odd=%-3d Even=%-3d\n",
total_handled, g_odd_handled, g_even_handled);
printf(" Total nested %-3d Odd=%-3d Even=%-3d\n",
total_nested, g_odd_nested, g_even_nested);
/* Then do it all over again with the interfering thread. */
for (i = 0; i < 10; i++)
{
for (j = 1; j < MAX_SIGNO; j += 2)
{
/* Odd then even */
sched_lock();
if (signest_catchable(j))
{
kill(waiterpid, j);
odd_signals++;
}
sem_post(&g_interferer_sem);
if (signest_catchable(j + 1))
{
kill(waiterpid, j + 1);
even_signals++;
}
sched_unlock();
wait_finish(waiterpid, j);
/* Even then odd */
sched_lock();
if (signest_catchable(j + 1))
{
kill(waiterpid, j + 1);
even_signals++;
}
sem_post(&g_interferer_sem);
if (signest_catchable(j))
{
kill(waiterpid, j);
odd_signals++;
}
sched_unlock();
wait_finish(waiterpid, j);
}
}
/* Stop the threads */
errout_with_waiter:
g_done = true;
sem_post(&g_waiter_sem);
sem_post(&g_interferer_sem);
do
{
usleep(500 * 1000L);
}
while (g_waiter_running || g_interferer_running);
/* Check the final test results */
total_signals = odd_signals + even_signals;
total_handled = g_odd_handled + g_even_handled;
total_nested = g_odd_nested + g_even_nested;
printf("signest_test: With intefering thread\n");
printf(" Total signalled %-3d Odd=%-3d Even=%-3d\n",
total_signals, odd_signals, even_signals);
printf(" Total handled %-3d Odd=%-3d Even=%-3d\n",
total_handled, g_odd_handled, g_even_handled);
printf(" Total nested %-3d Odd=%-3d Even=%-3d\n",
total_nested, g_odd_nested, g_even_nested);
/* Check for error */
if (g_waiter_running)
{
printf("signest_test: ERROR waiter is still running\n");
ASSERT(false);
}
if (g_interferer_running)
{
printf("signest_test: ERROR interferer is still running\n");
ASSERT(false);
}
if (total_signals != total_handled)
{
printf("signest_test: ERROR only %d of %d signals were handled\n",
total_handled, total_signals);
ASSERT(false);
}
if (odd_signals != g_odd_handled)
{
printf("signest_test: ERROR only %d of %d ODD signals were handled\n",
g_odd_handled, odd_signals);
ASSERT(false);
}
if (even_signals != g_even_handled)
{
printf("signest_test: ERROR only %d of %d EVEN signals were handled\n",
g_even_handled, even_signals);
ASSERT(false);
}
if (g_odd_nested > 0)
{
printf("signest_test: ERROR %d ODD signals were nested\n",
g_odd_nested);
ASSERT(false);
}
sem_destroy(&g_waiter_sem);
sem_destroy(&g_interferer_sem);
sem_destroy(&g_sem_thread_started);
sem_destroy(&g_sem_signal_finish);
printf("signest_test: done\n");
FFLUSH();
}