In some cases the license-identification header was missing, so I added that as well. Replaced the remaining headers that specifically identified "Versions 3.13.7 and higher". Makefiles and the build system were deliberately excluded.
178 lines
3.9 KiB
C
178 lines
3.9 KiB
C
/*************************************************************************\
|
|
* Copyright (c) 2012 ITER Organization
|
|
* Copyright (c) 2012 UChicago Argonne LLC, as Operator of Argonne
|
|
* National Laboratory.
|
|
*
|
|
* SPDX-License-Identifier: EPICS
|
|
* EPICS BASE is distributed subject to a Software License Agreement found
|
|
* in file LICENSE that is included with this distribution.
|
|
\*************************************************************************/
|
|
|
|
/* epicsThreadHooksTest.c */
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "epicsThread.h"
|
|
#include "epicsExit.h"
|
|
#include "epicsEvent.h"
|
|
#include "epicsMutex.h"
|
|
#include "errlog.h"
|
|
#include "epicsUnitTest.h"
|
|
#include "testMain.h"
|
|
|
|
#define MAX_THREADS 16
|
|
#define TEST_THREADS 8
|
|
#define NUM_HOOKS 4
|
|
|
|
static int order[MAX_THREADS][NUM_HOOKS];
|
|
static int cnt[MAX_THREADS];
|
|
static int mine[MAX_THREADS];
|
|
static int mapped[MAX_THREADS];
|
|
static epicsThreadId tid[MAX_THREADS];
|
|
|
|
static epicsMutexId tidLock;
|
|
static epicsEventId shutdown[TEST_THREADS];
|
|
|
|
static int newThreadIndex(epicsThreadId id)
|
|
{
|
|
int i = 0;
|
|
|
|
if (epicsMutexLock(tidLock))
|
|
testAbort("newThreadIndex: Locking problem");
|
|
|
|
while (i < MAX_THREADS && tid[i] != 0)
|
|
i++;
|
|
if (i < MAX_THREADS)
|
|
tid[i] = id;
|
|
else
|
|
testAbort("newThreadIndex: Too many threads!");
|
|
|
|
epicsMutexUnlock(tidLock);
|
|
return i;
|
|
}
|
|
|
|
static int findThreadIndex(epicsThreadId id)
|
|
{
|
|
int i = 0;
|
|
|
|
while (i < MAX_THREADS && tid[i] != id)
|
|
i++;
|
|
return i;
|
|
}
|
|
|
|
static void atExitHook1 (void *arg)
|
|
{
|
|
int no = findThreadIndex(epicsThreadGetIdSelf());
|
|
|
|
if (no < MAX_THREADS)
|
|
order[no][3] = cnt[no]++;
|
|
}
|
|
|
|
static void atExitHook2 (void *arg)
|
|
{
|
|
int no = findThreadIndex(epicsThreadGetIdSelf());
|
|
|
|
if (no < MAX_THREADS)
|
|
order[no][2] = cnt[no]++;
|
|
}
|
|
|
|
static void startHook1 (epicsThreadId id)
|
|
{
|
|
int no = newThreadIndex(id);
|
|
|
|
if (no < MAX_THREADS)
|
|
order[no][0] = cnt[no]++;
|
|
epicsAtThreadExit(atExitHook1, NULL);
|
|
}
|
|
|
|
static void startHook2 (epicsThreadId id)
|
|
{
|
|
int no = findThreadIndex(id);
|
|
|
|
if (no < MAX_THREADS)
|
|
order[no][1] = cnt[no]++;
|
|
epicsAtThreadExit(atExitHook2, NULL);
|
|
}
|
|
|
|
static void my_thread (void *arg)
|
|
{
|
|
int no = findThreadIndex(epicsThreadGetIdSelf());
|
|
|
|
if (no < MAX_THREADS)
|
|
mine[no] = 1;
|
|
epicsEventMustWait((epicsEventId) arg);
|
|
}
|
|
|
|
static void mapper (epicsThreadId id)
|
|
{
|
|
int no = findThreadIndex(id);
|
|
|
|
if (no < MAX_THREADS)
|
|
mapped[no]++;
|
|
}
|
|
|
|
MAIN(epicsThreadHooksTest)
|
|
{
|
|
int i;
|
|
int ok;
|
|
|
|
testPlan(TEST_THREADS + 1);
|
|
|
|
tidLock = epicsMutexMustCreate();
|
|
|
|
if (epicsThreadHookAdd(startHook1))
|
|
testAbort("startHook1 registration failed");
|
|
if (epicsThreadHookAdd(startHook2))
|
|
testAbort("startHook2 registration failed");
|
|
|
|
for (i = 0; i < TEST_THREADS; i++) {
|
|
char name[10];
|
|
|
|
shutdown[i] = epicsEventCreate(epicsEventEmpty);
|
|
sprintf(name, "t%d", (int) i);
|
|
epicsThreadCreate(name, epicsThreadPriorityMedium,
|
|
epicsThreadGetStackSize(epicsThreadStackMedium),
|
|
my_thread, shutdown[i]);
|
|
}
|
|
epicsThreadSleep(1.0);
|
|
|
|
epicsThreadMap(mapper);
|
|
|
|
ok = 1;
|
|
for (i = 0; i < MAX_THREADS; i++) {
|
|
if (!mine[i]) continue;
|
|
|
|
if (mapped[i] != 1) {
|
|
ok = 0;
|
|
testDiag("mapped[%d] = %d", i, mapped[i]);
|
|
}
|
|
}
|
|
testOk(ok, "All my tasks covered once by epicsThreadMap");
|
|
|
|
for (i = 0; i < TEST_THREADS; i++) {
|
|
epicsEventSignal(shutdown[i]);
|
|
}
|
|
|
|
epicsThreadSleep(1.0);
|
|
|
|
for (i = 0; i < MAX_THREADS; i++) {
|
|
int j;
|
|
|
|
if (!mine[i]) continue;
|
|
|
|
ok = 1;
|
|
for (j = 0; j < NUM_HOOKS; j++) {
|
|
if (order[i][j] != j) {
|
|
ok = 0;
|
|
testDiag("order[%d][%d] = %d", i, j, order[i][j]);
|
|
}
|
|
}
|
|
testOk(ok, "All hooks for task %d called in correct order", i);
|
|
}
|
|
|
|
epicsThreadHookDelete(startHook1);
|
|
epicsThreadHookDelete(startHook2);
|
|
|
|
return testDone();
|
|
}
|