示例#1
0
void * fonction_thread ()
{
    cpt=100;

       while (cpt--) {
            le_sem_Wait(GSemPtr);
            fprintf(stdout, "\n%d : thread '%s' has %s %d\n",
                    cpt,le_thread_GetMyName(),SEM_NAME_1,le_sem_GetValue(GSemPtr));
            CU_PASS("thread GSemPtr get");
            le_sem_Wait(GSem2Ptr);
            fprintf(stdout, "\n%d : thread '%s' has %s %d\n",
                    cpt,le_thread_GetMyName(),SEM_NAME_2,le_sem_GetValue(GSem2Ptr));
            CU_PASS("thread GSem2Ptr get");
            usleep(10000);
            le_sem_Post(GSem2Ptr);
            fprintf(stdout, "\n%d : thread '%s' release %s %d\n",
                    cpt,le_thread_GetMyName(),SEM_NAME_2,le_sem_GetValue(GSem2Ptr));
            CU_PASS("thread GSemPtr2 UnLocked");
            le_sem_Post(GSemPtr);
            fprintf(stdout, "\n%d : thread '%s' release %s %d\n",
                    cpt,le_thread_GetMyName(),SEM_NAME_1,le_sem_GetValue(GSemPtr));
            CU_PASS("thread GSemPtr UnLocked");
    }

    return NULL;
}
示例#2
0
// A thread "main" function which creates a series of sems.
static void* ThreadCreateSem
(
    void* context
)
{
    char semNameBuffer[LIMIT_MAX_SEMAPHORE_NAME_BYTES] = {0};


    LE_INFO("Thread [%s] has started. Waiting on a semaphore.", le_thread_GetMyName());

    le_mutex_Lock(SemIndexMutexRef);

    snprintf(semNameBuffer, LIMIT_MAX_SEMAPHORE_NAME_BYTES, "[%s]Sem%ld",
             le_thread_GetMyName(), SemCreateIdx);

    le_sem_Ref_t sem = le_sem_Create(semNameBuffer, 0);

    SemRefArray[SemCreateIdx] = (SemRef_t){le_thread_GetCurrent(), sem};

    SemCreateIdx++;

    le_mutex_Unlock(SemIndexMutexRef);

    LE_INFO("In thread [%s], about to wait sem", le_thread_GetMyName());

    // notify the calling thread that this thread is about to wait on its sema.
    le_sem_Post(SemaRef);

    le_sem_Wait(sem);
    LE_INFO("In thread [%s], sema is posted", le_thread_GetMyName());

    le_event_RunLoop();
    return NULL;
}
示例#3
0
//--------------------------------------------------------------------------------------------------
le_result_t le_sem_TryWait
(
    le_sem_Ref_t    semaphorePtr   ///< [IN] Pointer to the semaphore
)
{
//     TODO: Implement this.
//     if (semaphorePtr->isTraceable)
//     {
//     }
//     else
    {
        int result;

        result = sem_trywait(&semaphorePtr->semaphore);

        if (result != 0)
        {
            if ( errno == EAGAIN ) {
                return LE_WOULD_BLOCK;
            } else {
                LE_FATAL("Thread '%s' failed to trywait on semaphore '%s'. Error code %d (%m).",
                        le_thread_GetMyName(),
                        semaphorePtr->nameStr,
                        result);
            }
        }
    }

    return LE_OK;
}
示例#4
0
//--------------------------------------------------------------------------------------------------
void le_sem_Wait
(
    le_sem_Ref_t    semaphorePtr   ///< [IN] Pointer to the semaphore
)
{
//     TODO: Implement this:
//     if (semaphorePtr->isTraceable)
//     {
//     }
//     else
    {
        int result;

        sem_ThreadRec_t* perThreadRecPtr = thread_GetSemaphoreRecPtr();

        ListOfSemaphoresChgCnt++;
        perThreadRecPtr->waitingOnSemaphore = semaphorePtr;
        AddToWaitingList(semaphorePtr, perThreadRecPtr);

        result = sem_wait(&semaphorePtr->semaphore);

        RemoveFromWaitingList(semaphorePtr, perThreadRecPtr);
        ListOfSemaphoresChgCnt++;
        perThreadRecPtr->waitingOnSemaphore = NULL;

        LE_FATAL_IF( (result!=0), "Thread '%s' failed to wait on semaphore '%s'. Error code %d (%m).",
                    le_thread_GetMyName(),
                    semaphorePtr->nameStr,
                    result);
    }
}
示例#5
0
// Delete from 1 to n-1 for all threads
static void DelMutex1toNMinus1PerThread
(
    void* param1,
    void* param2
)
{
    LE_INFO("DelMutex1toNMinus1PerThread in thread [%s]", le_thread_GetMyName());
    DelMutexes(0, 1);
}
示例#6
0
// -------------------------------------------------------------------------------------------------
static void IncrementCounter(void)
// -------------------------------------------------------------------------------------------------
{
    Lock();

    Counter++;

    LE_INFO("Thread '%s' incremented counter to %zu.", le_thread_GetMyName(), Counter);

    Unlock();
}
示例#7
0
// -------------------------------------------------------------------------------------------------
static void ThreadDestructor
(
    void* destructorContext
)
// -------------------------------------------------------------------------------------------------
{
    Context_t* contextPtr = destructorContext;

    LE_TEST_INFO("Thread '%s' destructor running.", le_thread_GetMyName());

    le_mem_Release(contextPtr);
}
示例#8
0
//--------------------------------------------------------------------------------------------------
le_result_t le_sem_WaitWithTimeOut
(
    le_sem_Ref_t    semaphorePtr,   ///< [IN] Pointer to the semaphore.
    le_clk_Time_t   timeToWait      ///< [IN] Time to wait
)
{
//     TODO: Implement this.
//     if (semaphorePtr->isTraceable)
//     {
//     }
//     else
    {
        struct timespec timeOut;
        int result;

        // Prepare the timer
        le_clk_Time_t currentUtcTime = le_clk_GetAbsoluteTime();
        le_clk_Time_t wakeUpTime = le_clk_Add(currentUtcTime,timeToWait);
        timeOut.tv_sec = wakeUpTime.sec;
        timeOut.tv_nsec = wakeUpTime.usec;

        // Retrieve reference thread
        sem_ThreadRec_t* perThreadRecPtr = thread_GetSemaphoreRecPtr();
        // Save into waiting list
        ListOfSemaphoresChgCnt++;
        perThreadRecPtr->waitingOnSemaphore = semaphorePtr;
        AddToWaitingList(semaphorePtr, perThreadRecPtr);

        result = sem_timedwait(&semaphorePtr->semaphore,&timeOut);

        // Remove from waiting list
        RemoveFromWaitingList(semaphorePtr, perThreadRecPtr);
        ListOfSemaphoresChgCnt++;
        perThreadRecPtr->waitingOnSemaphore = NULL;

        if (result != 0)
        {
            if ( errno == ETIMEDOUT ) {
                return LE_TIMEOUT;
            } else {
                LE_FATAL("Thread '%s' failed to wait on semaphore '%s'. Error code %d (%m).",
                        le_thread_GetMyName(),
                        semaphorePtr->nameStr,
                        result);
            }
        }
    }

    return LE_OK;
}
示例#9
0
// -------------------------------------------------------------------------------------------------
static void* ThreadMainFunction
(
    void* objPtr
)
// -------------------------------------------------------------------------------------------------
{
    Context_t* contextPtr = objPtr;

    LE_INFO("Thread '%s' started.", le_thread_GetMyName());

    IncrementCounter();

    if (contextPtr->depth < DEPTH)
    {
        LE_INFO("Thread '%s' spawning children.", le_thread_GetMyName());

        SpawnChildren(contextPtr->depth + 1, contextPtr->completionObjPtr);
    }

    LE_INFO("Thread '%s' terminating.", le_thread_GetMyName());

    return contextPtr->completionObjPtr;
}
示例#10
0
// A thread "main" function which creates a series of mutexes.
static void* ThreadCreateMutex
(
    void* context
)
{
    long mutexCount = (long)context;
    char mutexNameBuffer[MAX_NAME_BYTES] = {0};

    MutexRefArray_t mra;
    mra.size = mutexCount;
    mra.mutexRefArray = malloc(mutexCount * sizeof(le_mutex_Ref_t));

    LE_INFO("Thread [%s] has started. Creating %ld mutexes.", le_thread_GetMyName(), mutexCount);

    le_mutex_Lock(MutexIndexMutexRef);
    long cnt = 0;
    while (cnt < mutexCount)
    {
        snprintf(mutexNameBuffer, MAX_NAME_BYTES, "[%s]Mutex%ld",
                 le_thread_GetMyName(), MutexCreateIdx);

        mra.mutexRefArray[cnt] = le_mutex_CreateNonRecursive(mutexNameBuffer);
        le_mutex_Lock(mra.mutexRefArray[cnt]);

        MutexCreateIdx++;
        cnt++;
    }
    le_mutex_Unlock(MutexIndexMutexRef);

    // Save the list of mutex refs in the thread's local storage.
    (void) pthread_setspecific(TsdMutexRefKey, &mra);

    le_sem_Post(SemaRef);

    le_event_RunLoop();
    return NULL;
}
示例#11
0
// Delete all mutexes for the first thread.
static void DelAllMutexesFor1stThread
(
    void* param1,
    void* param2
)
{
    LE_INFO("DelAllMutexesFor1stThread in thread [%s]", le_thread_GetMyName());

    // Determine if this is the "1st" thread on the thread list. If so, delete all mutexes.
    if (le_thread_GetCurrent() == ThreadRefArray[0])
    {
        LE_INFO("This thread is the 1st thread in the thread list - deleting all mutexes.");
        DelMutexes(0, 0);
    }
}
示例#12
0
// -------------------------------------------------------------------------------------------------
static void IncrementCounter(void)
// -------------------------------------------------------------------------------------------------
{
    Lock();

    Counter++;

    LE_TEST_INFO("Thread '%s' incremented counter to %u.", le_thread_GetMyName(), Counter);

    if (Counter == ExpectedCounterValue)
    {
        le_sem_Post(CounterSemRef);
    }

    Unlock();
}
示例#13
0
// Delete all mutexes for a thread in the middle.
static void DelAllMutexesForMidThread
(
    void* param1,
    void* param2
)
{
    LE_INFO("DelAllMutexesForMidThread in thread [%s]", le_thread_GetMyName());

    long midIdx = ThreadNum / 2;

    // Determine if this is the "mid" thread on the thread list. If so, delete all mutexes.
    if (le_thread_GetCurrent() == ThreadRefArray[midIdx])
    {
        LE_INFO("This thread is the mid thread in the thread list - deleting all mutexes.");
        DelMutexes(0, 0);
    }
}
示例#14
0
//--------------------------------------------------------------------------------------------------
void le_sig_SetEventHandler
(
    int sigNum,                                 ///< The signal to set the event handler for.  See
                                                ///  parameter documentation in comments above.
    le_sig_EventHandlerFunc_t sigEventHandler   ///< The event handler to call when a signal is
                                                ///  received.
)
{
    // Check parameters.
    if ( (sigNum == SIGKILL) || (sigNum == SIGSTOP) || (sigNum == SIGFPE) || (sigNum == SIGILL) ||
         (sigNum == SIGSEGV) || (sigNum == SIGBUS) || (sigNum == SIGABRT) || (sigNum == SIGIOT) ||
         (sigNum == SIGTRAP) || (sigNum == SIGSYS) )
    {
        LE_FATAL("Signal event handler for %s is not allowed.", strsignal(sigNum));
    }

    // Get the monitor object for this thread.
    MonitorObj_t* monitorObjPtr = pthread_getspecific(SigMonKey);

    if (monitorObjPtr == NULL)
    {
        if (sigEventHandler == NULL)
        {
            // Event handler already does not exist so we don't need to do anything, just return.
            return;
        }
        else
        {
            // Create the monitor object
            monitorObjPtr = le_mem_ForceAlloc(MonitorObjPool);
            monitorObjPtr->handlerObjList = LE_DLS_LIST_INIT;
            monitorObjPtr->fd = -1;
            monitorObjPtr->monitorRef = NULL;

            // Add it to the thread's local data.
            LE_ASSERT(pthread_setspecific(SigMonKey, monitorObjPtr) == 0);
        }
    }

    // See if a handler for this signal already exists.
    HandlerObj_t* handlerObjPtr = FindHandlerObj(sigNum, &(monitorObjPtr->handlerObjList));

    if (handlerObjPtr == NULL)
    {
        if (sigEventHandler == NULL)
        {
            // Event handler already does not exist so we don't need to do anything, just return.
            return;
        }
        else
        {
            // Create the handler object.
            handlerObjPtr = le_mem_ForceAlloc(HandlerObjPool);

            // Set the handler.
            handlerObjPtr->link = LE_DLS_LINK_INIT;
            handlerObjPtr->handler = sigEventHandler;
            handlerObjPtr->sigNum = sigNum;

            // Add the handler object to the list.
            le_dls_Queue(&(monitorObjPtr->handlerObjList), &(handlerObjPtr->link));
        }
    }
    else
    {
        if (sigEventHandler == NULL)
        {
            // Remove the handler object from the list.
            le_dls_Remove(&(monitorObjPtr->handlerObjList), &(handlerObjPtr->link));
        }
        else
        {
            // Just update the handler.
            handlerObjPtr->handler = sigEventHandler;
        }
    }

    // Recreate the signal mask.
    sigset_t sigSet;
    LE_ASSERT(sigemptyset(&sigSet) == 0);

    le_dls_Link_t* handlerLinkPtr = le_dls_Peek(&(monitorObjPtr->handlerObjList));
    while (handlerLinkPtr != NULL)
    {
        HandlerObj_t* handlerObjPtr = CONTAINER_OF(handlerLinkPtr, HandlerObj_t, link);

        LE_ASSERT(sigaddset(&sigSet, handlerObjPtr->sigNum) == 0);

        handlerLinkPtr = le_dls_PeekNext(&(monitorObjPtr->handlerObjList), handlerLinkPtr);
    }

    // Update or create the signal fd.
    monitorObjPtr->fd = signalfd(monitorObjPtr->fd, &sigSet, SFD_NONBLOCK);

    if (monitorObjPtr->fd == -1)
    {
        LE_FATAL("Could not set signal event handler: %m");
    }

    // Create a monitor fd if it doesn't already exist.
    if (monitorObjPtr->monitorRef == NULL)
    {
        // Create the monitor name using SIG_STR + thread name.
        char monitorName[LIMIT_MAX_THREAD_NAME_BYTES + sizeof(SIG_STR)] = SIG_STR;

        LE_ASSERT(le_utf8_Copy(monitorName + sizeof(SIG_STR),
                               le_thread_GetMyName(),
                               LIMIT_MAX_THREAD_NAME_BYTES + sizeof(SIG_STR),
                               NULL) == LE_OK);

        // Create the monitor.
        monitorObjPtr->monitorRef = le_fdMonitor_Create(monitorName,
                                                        monitorObjPtr->fd,
                                                        OurSigHandler,
                                                        POLLIN);
    }
}
示例#15
0
// -------------------------------------------------------------------------------------------------
static void SpawnChildren
(
    size_t depth,           // Indicates what nesting level the thread is at.
                            // 1 = children of the process main thread.

    void*  completionObjPtr // Ptr to the object whose ref count is used to terminate the test.
)
// -------------------------------------------------------------------------------------------------
{
    int i;
    char childName[32];
    le_thread_Ref_t children[FAN_OUT];

    // Create and start all the children.
    for (i = 0; i < FAN_OUT; i++)
    {
        le_thread_Ref_t threadRef;

        Context_t* contextPtr = le_mem_ForceAlloc(ContextPoolRef);
        contextPtr->depth = depth;
        contextPtr->completionObjPtr = completionObjPtr;
        le_mem_AddRef(completionObjPtr);

        snprintf(childName, sizeof(childName), "%s-%d", le_thread_GetMyName(), i + 1);

        LE_INFO("Spawning thread '%s'.", childName);

        threadRef = le_thread_Create(childName, ThreadMainFunction, contextPtr);

        LE_INFO("Thread '%s' created.", childName);

        // Create a thread destructor that will release the Context object and the
        // Test Completion Object that we are going to pass to the child.
        le_thread_AddChildDestructor(threadRef, ThreadDestructor, contextPtr);

        LE_INFO("Thread '%s' destructor added.", childName);

        // Make every third child thread non-joinable and the rest joinable.
        if (((i + 1) % 3) != 0)
        {
            le_thread_SetJoinable(threadRef);
        }

        LE_INFO("Thread '%s' joinability set.", childName);

        // Start the child thread.
        le_thread_Start(threadRef);

        LE_INFO("Thread '%s' started.", childName);

        // Remember the child's thread reference for later join attempt.
        children[i] = threadRef;
    }

    // Join with all the children.
    for (i = 0; i < FAN_OUT; i++)
    {
        void* threadReturnValue;

        snprintf(childName, sizeof(childName), "%s-%d", le_thread_GetMyName(), i + 1);
        LE_INFO("Joining with thread '%s'.", childName);

        le_result_t result = le_thread_Join(children[i], &threadReturnValue);

        if (result != LE_OK)
        {
            LE_INFO("Failed to join with thread '%s'.", childName);
            LE_FATAL_IF(((i + 1) % 3) != 0, "Failed to join with joinable thread '%s'!", childName);
        }
        else
        {
            LE_INFO("Successfully joined with thread '%s', which returned %p.",
                    childName,
                    threadReturnValue);
            LE_FATAL_IF(((i + 1) % 3) == 0, "Joined with non-joinable thread '%s'!", childName);
            LE_FATAL_IF(threadReturnValue != completionObjPtr,
                        "Thread returned strange value %p.  Expected %p.",
                        threadReturnValue,
                        completionObjPtr);
        }
    }
}
示例#16
0
// -------------------------------------------------------------------------------------------------
static void SpawnChildren
(
    size_t depth            // Indicates what nesting level the thread is at.
                            // 1 = children of the process main thread.
)
// -------------------------------------------------------------------------------------------------
{
    int i, j, k;
    char childName[32];
    le_thread_Ref_t children[FAN_OUT];
    const char* threadName = le_thread_GetMyName();

    if (depth == 2)
    {
        LE_ASSERT(sscanf(threadName, "%*[^-]-%d", &j) == 1);
        // switch to zero-based
        j--;
        LE_TEST_INFO("depth 2: j=%d", j);
    }
    else if (depth == 3)
    {
        LE_ASSERT(sscanf(threadName, "%*[^-]-%d-%d", &k, &j) == 2);
        // switch to zero based
        k--;
        j--;
        LE_TEST_INFO("depth 3: j=%d,k=%d", j, k);
    }

    // Create and start all the children.
    for (i = 0; i < FAN_OUT; i++)
    {
        le_thread_Ref_t threadRef;

        Context_t* contextPtr = le_mem_ForceAlloc(ContextPoolRef);
        contextPtr->depth = depth;

        int item = 0;
        if (depth == 1)
        {
            item = i*(FAN_OUT+1)*(FAN_OUT+1);
        }
        if (depth == 2)
        {
            item = (j*(FAN_OUT+1)+(i+1))*(FAN_OUT+1);
        }
        else if (depth == 3)
        {
            item = (k*(FAN_OUT+1) + (j+1))*(FAN_OUT+1) + (i+1);
        }
        if (item >= FAN_OUT*(FAN_OUT+1)*(FAN_OUT+1))
        {
            LE_TEST_FATAL("Result index %d outside test result array size %d!",
                item, FAN_OUT*(FAN_OUT+1)*(FAN_OUT+1));
        }

        snprintf(childName, sizeof(childName), "%s-%d", threadName, i + 1);
        LE_TEST_INFO("Spawning thread '%s' (item %d).", childName, item);

        threadRef = le_thread_Create(childName, ThreadMainFunction, contextPtr);

        TestResults[item].createOk = !!threadRef;

        // Create a thread destructor that will release the Context object and the
        // Test Completion Object that we are going to pass to the child.
        le_thread_AddChildDestructor(threadRef, ThreadDestructor, contextPtr);

        LE_TEST_INFO("Thread '%s' destructor added.", childName);

        // Make every third leaf thread non-joinable and the rest joinable.
        // Non-leaves must be joinable to ensure join
        if (IsThreadJoinable(depth, i))
        {
            le_thread_SetJoinable(threadRef);
            LE_TEST_INFO("Thread '%s' joinability set.", childName);
        }


        // Start the child thread.
        le_thread_Start(threadRef);

        LE_TEST_INFO("Thread '%s' started.", childName);

        // Remember the child's thread reference for later join attempt.
        children[i] = threadRef;
    }

    // Join with all the children.
    for (i = 0; i < FAN_OUT; i++)
    {
        void* threadReturnValue;
        int item = 0;
        if (depth == 1)
        {
            item = i*(FAN_OUT+1)*(FAN_OUT+1);
        }
        if (depth == 2)
        {
            item = (j*(FAN_OUT+1)+(i+1))*(FAN_OUT+1);
        }
        else if (depth == 3)
        {
            item = (k*(FAN_OUT+1)+(j+1))*(FAN_OUT+1) + (i+1);
        }
        if (item >= FAN_OUT*(FAN_OUT+1)*(FAN_OUT+1))
        {
            LE_TEST_FATAL("Result index %d outside test result array size %d!",
                item, FAN_OUT*(FAN_OUT+1)*(FAN_OUT+1));
        }

        snprintf(childName, sizeof(childName), "%s-%d", le_thread_GetMyName(), i + 1);

        if (IsThreadJoinable(depth, i))
        {
            le_result_t result = le_thread_Join(children[i], &threadReturnValue);
            TestResults[item].joinOk = (result == LE_OK);

            if (result != LE_OK)
            {
                LE_TEST_INFO("Failed to join with thread '%s'.", childName);
            }
            else
            {
                LE_TEST_INFO("Successfully joined with thread '%s', which returned %p.",
                             childName,
                             threadReturnValue);
                TestResults[item].expectedJoin = (void*)depth;
                TestResults[item].actualJoin = threadReturnValue;
            }
        }
        else
        {
            // Do not try to join non-joinable threads.  Result is undefined as thread
            // could have exited in the meantime and been recycled.
            TestResults[item].joinOk = false;
        }
    }
}