You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
170 lines
4.5 KiB
170 lines
4.5 KiB
/*
|
|
* Copyright 2002-2019 Intel Corporation.
|
|
*
|
|
* This software is provided to you as Sample Source Code as defined in the accompanying
|
|
* End User License Agreement for the Intel(R) Software Development Products ("Agreement")
|
|
* section 1.L.
|
|
*
|
|
* This software and the related documents are provided as is, with no express or implied
|
|
* warranties, other than those that are expressly stated in the License.
|
|
*/
|
|
|
|
#include <iostream>
|
|
#include <sched.h>
|
|
#include <pthread.h>
|
|
#include <unistd.h>
|
|
#include <sys/types.h>
|
|
#include <sys/syscall.h>
|
|
#include <cstdlib>
|
|
#include "atomic.hpp"
|
|
|
|
using std::cout;
|
|
using std::cerr;
|
|
using std::endl;
|
|
using std::flush;
|
|
|
|
|
|
volatile unsigned int threadCount = 0;
|
|
volatile bool go = false;
|
|
volatile unsigned int stillRunning = 0;
|
|
volatile bool done = false;
|
|
|
|
|
|
pid_t GetTid()
|
|
{
|
|
return syscall(__NR_gettid);
|
|
}
|
|
|
|
|
|
extern "C"
|
|
{
|
|
|
|
void SecondaryThreadInit(unsigned int threadNum, pid_t tid)
|
|
{
|
|
ATOMIC::OPS::Store(&stillRunning, (unsigned int)tid);
|
|
cout << "APP: Thread #" << threadNum << " (" << tid << ") started." << endl << flush;
|
|
}
|
|
|
|
|
|
static void SecondaryThreadWork()
|
|
{
|
|
ATOMIC::OPS::Store(&stillRunning, (unsigned int)GetTid());
|
|
sched_yield();
|
|
}
|
|
|
|
|
|
void SecondaryThreadFini(unsigned int threadNum, pid_t tid)
|
|
{
|
|
ATOMIC::OPS::Store(&stillRunning, (unsigned int)tid);
|
|
cout << "APP: Thread #" << threadNum << " (" << tid << ") finished." << endl << flush;
|
|
}
|
|
|
|
} // extern "C"
|
|
|
|
|
|
static void* SecondaryThreadMain(void* v)
|
|
{
|
|
unsigned int threadNum = ATOMIC::OPS::Increment<unsigned int>(&threadCount, 1);
|
|
pid_t tid = GetTid();
|
|
|
|
// Per-thread init
|
|
SecondaryThreadInit(threadNum, tid);
|
|
while (!go) sched_yield();
|
|
|
|
// Stress test
|
|
for (unsigned int i = 0; i < 1000; ++i)
|
|
{
|
|
SecondaryThreadWork();
|
|
}
|
|
|
|
// Per-thread fini
|
|
SecondaryThreadFini(threadNum, tid);
|
|
return NULL;
|
|
}
|
|
|
|
|
|
static void* MonitorThreadMain(void* v)
|
|
{
|
|
// Make sure that the test is not deadlocked:
|
|
// When a thread completes a step, it assigns a non-zero value to "stillRunning" (tid or pthread id).
|
|
// If the monitor thread wakes up and finds that "stillRunning" is zero, it assumes a deadlock and
|
|
// terminates the application. After a successful check ("stillRunning" is true), the monitor thread
|
|
// resets "stillRunning" to false. A 10-second sleep period should suffice even on the most overloaded
|
|
// system.
|
|
//
|
|
// Special case: The monitor thread sleeps for one 10-second period before it begins to monitor the
|
|
// application to allow the main thread to begin its work creating threads.
|
|
sleep(10);
|
|
unsigned int i = 0;
|
|
while (!done)
|
|
{
|
|
volatile unsigned int isRunning = ATOMIC::OPS::Load(&stillRunning);
|
|
cout << "APP: monitor iteration " << ++i << ", stillRunning: " << stillRunning << endl << flush;
|
|
if (0 == isRunning)
|
|
{
|
|
cerr << "APP ERROR: Timeout reached" << endl;
|
|
exit(5);
|
|
}
|
|
ATOMIC::OPS::Store(&stillRunning, (unsigned int)0);
|
|
sleep(10);
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
|
|
extern "C"
|
|
{
|
|
void ReleaseThreads(volatile bool* doRelease)
|
|
{
|
|
if (false == go)
|
|
{
|
|
cerr << "APP ERROR: The tool should have instrumented ReleaseThreads and released the threads" << endl;
|
|
exit(3);
|
|
}
|
|
}
|
|
} // extern "C"
|
|
|
|
|
|
static void CreateThreads()
|
|
{
|
|
static const unsigned int numOfThreads = 50;
|
|
pthread_t tids[numOfThreads];
|
|
for (unsigned int i = 0; i < numOfThreads; ++i)
|
|
{
|
|
if (0 != pthread_create(&tids[i], NULL, SecondaryThreadMain, (void*)i))
|
|
{
|
|
cerr << "APP ERROR: Failed to create secondary thread #" << i << endl;
|
|
exit(2);
|
|
}
|
|
ATOMIC::OPS::Store(&stillRunning, (unsigned int)tids[i]);
|
|
}
|
|
cout << "APP: All threads created successfully, waiting for them to be ready." << endl;
|
|
while (threadCount < numOfThreads) sched_yield();
|
|
ReleaseThreads(&go);
|
|
cout << "APP: All threads are ready, waiting for them to exit." << endl;
|
|
for (unsigned int i = 0; i < numOfThreads; ++i)
|
|
{
|
|
if (0 != pthread_join(tids[i], NULL))
|
|
{
|
|
cerr << "APP ERROR: Secondary thread #" << i << " failed to join"<< endl;
|
|
exit(4);
|
|
}
|
|
ATOMIC::OPS::Store(&stillRunning, (unsigned int)tids[i]);
|
|
}
|
|
done = true;
|
|
}
|
|
|
|
|
|
int main()
|
|
{
|
|
pthread_t monitor;
|
|
if (0 != pthread_create(&monitor, NULL, MonitorThreadMain, NULL))
|
|
{
|
|
cerr << "APP ERROR: Failed to create the monitor thread" << endl;
|
|
exit(1);
|
|
}
|
|
CreateThreads();
|
|
cout << "APP: Test completed successfully." << endl;
|
|
return 0;
|
|
}
|