/* =====================================================================
 * Wait for the turn of the thread denoted by 'tid' to do its checking
 * ===================================================================== */
void WaitForThisThreadToBeActive(THREADID tid)
{
    // Waits for the turn of this thread
    while (VecThreadIds[ActiveThreadIndex] != tid)
    {
        PIN_MutexUnlock(&MtxActiveThread);
        YIELD();
        PIN_MutexLock(&MtxActiveThread);
    }

    // At this point it's the turn of the current thread to do the checking
    // the previous thread release the mutex MtxActiveThread.
    // We still need to wait (for at most 10 seconds) for the previous thread
    // to stop at the debugger
    time_t startWaitingTime = time(NULL);
    if (ActiveThreadIndex > 0)
    {
        THREADID prevTid = VecThreadIds[ActiveThreadIndex - 1];
        while (!PIN_IsThreadStoppedInDebugger(prevTid))
        {
            ASSERT((time(NULL) - startWaitingTime) < 10, "Timeout waiting for thread " + hexstr(prevTid) + " to stop in debugger");
            YIELD();
        }
    }
}
Example #2
0
static void DoTestMutexTryStress(THREAD_INFO *info, UINT32 *done)
{
    // Try to acquire / release PIN_MUTEX as fast as possible, using "try".

    if (PIN_MutexTryLock(&Mutex))
        PIN_MutexUnlock(&Mutex);
    CheckIfDone(info, done);
}
Example #3
0
static void DoTestMutexStress(THREAD_INFO *info, UINT32 *done)
{
    // This test just tries to acquire and release PIN_MUTEX as fast as possible
    // to see if we can provoke a deadlock due to missing a wakeup.

    PIN_MutexLock(&Mutex);
    PIN_MutexUnlock(&Mutex);
    CheckIfDone(info, done);
}
Example #4
0
static void DoTestSemaphore(THREAD_INFO *info, UINT32 *done)
{
    // This test assumes exactly two threads.  The two threads take turns pinging
    // each other's semaphore.  We make sure that a thread does not wake up from
    // the semaphore unless it is set.  We also check for deadlocks due to missing
    // wakeups.

    if (info->_workerId == 0)
    {
        PIN_SemaphoreWait(&Sem1);

        if (!PIN_SemaphoreIsSet(&Sem1))
        {
            std::cout << "SemaphoreWait returned, but semaphore is not set" << std::endl;
            PIN_ExitProcess(1);
        }

        PIN_MutexLock(&Mutex);
        PIN_SemaphoreClear(&Sem1);
        PIN_SemaphoreSet(&Sem2);
        PIN_MutexUnlock(&Mutex);
    }
    else
    {
        PIN_SemaphoreWait(&Sem2);

        if (!PIN_SemaphoreIsSet(&Sem2))
        {
            std::cout << "SemaphoreWait returned, but semaphore is not set" << std::endl;
            PIN_ExitProcess(1);
        }

        PIN_MutexLock(&Mutex);
        PIN_SemaphoreClear(&Sem2);
        PIN_SemaphoreSet(&Sem1);
        PIN_MutexUnlock(&Mutex);
    }

    if (CheckIfDone(info, done))
    {
        PIN_SemaphoreSet(&Sem1);
        PIN_SemaphoreSet(&Sem2);
    }
}
Example #5
0
/*
 * GetReadId
 * Returns the unique read id
 */
long unsigned int GetReadId()
{
	long unsigned int ret;

	PIN_MutexLock(&readid_lock);
	ret = readid;
	readid++;
	PIN_MutexUnlock(&readid_lock);

	return ret;
}
/* =====================================================================
 * Called on DoBreakpoint() for each thread.
 * Waits for all the threads to reach this point, filling the vector of
 * the created thread IDs, and then release all the threads.
 * ===================================================================== */
static void WaitForAllThreadsToStart(THREADID tid)
{
    PIN_MutexLock(&MtxVecThreadIds);
    VecThreadIds.push_back(tid);
    if (VecThreadIds.size() >= KnobThreads.Value())
    {
        PrintAllThreadIDs();
        AllThreadsWereStarted = true;
        PIN_SemaphoreSet(&SemAllThreadStarted);
    }
    PIN_MutexUnlock(&MtxVecThreadIds);
    PIN_SemaphoreWait(&SemAllThreadStarted);
}
/* =====================================================================
 * Called on each thread when it calls GlobalFunction()
 * ===================================================================== */
static void DoBreakpoint(THREADID tid, CONTEXT *context)
{
    // If all thread were started then this is the second time we're entering
    // this function for the thread 'tid'.
    // We enter this function twice for the same thread because we hit the same
    // instrumentation we the debugger was returned from the break-point that
    // we mock to the same address. In this case we need to return and don't
    // repeat the test (unless we'll end up with an infinite test).
    if (AllThreadsWereStarted)
        return;

    WaitForAllThreadsToStart(tid);
    // All threads are synchronized to this point

    PIN_MutexLock(&MtxActiveThread);

    WaitForThisThreadToBeActive(tid);

    Out << "Performing check on thread ID " << tid << std::endl;

    for (unsigned i = 0; i < KnobThreads.Value(); i++)
    {
        THREADID otherTid = VecThreadIds[i];
        if (i < ActiveThreadIndex)
        {
            // All threads that were already active should be stopped in the debugger
            ASSERT(PIN_IsThreadStoppedInDebugger(otherTid), "Thread " + decstr(otherTid) + " should be stopped");
        }
        else
        {
            // All threads that weren't already active should be running
            ASSERT(!PIN_IsThreadStoppedInDebugger(otherTid), "Thread " + decstr(otherTid) + " shouldn't be stopped");
        }
    }

    ActiveThreadIndex++;
    PIN_MutexUnlock(&MtxActiveThread);

    // Stop this thread in the debugger
    // Note that because we add the instrumentation at IPOINT_AFTER, the program counter
    // at 'context' will not lead us to run this instrumentation function again
    PIN_ApplicationBreakpoint(context, tid, FALSE, "Stopping in Worker Thread " + decstr(tid) + "\n");
}
Example #8
0
static void DoTestMutexIntegrity(THREADID tid, THREAD_INFO *info, UINT32 *done)
{
    // This test checks to see if two threads can be in the PIN_MUTEX mutex
    // simultaneously.

    PIN_MutexLock(&Mutex);
    THREADID owner = HasLock;
    HasLock = tid;

    if (owner != INVALID_THREADID)
    {
        std::cout << "Two theads in mutex simultaneously: " << std::dec << tid <<
            " and " << owner << std::endl;
        PIN_ExitProcess(1);
    }

    ATOMIC::OPS::Delay(DELAY_COUNT);

    HasLock = INVALID_THREADID;
    PIN_MutexUnlock(&Mutex);

    CheckIfDone(info, done);
}