예제 #1
0
//--------------------------------------------------------------------------------------------------
static void DispatchToHandler
(
    void* param1Ptr,    ///< FD Monitor safe reference.
    void* param2Ptr     ///< FD event type.
)
//--------------------------------------------------------------------------------------------------
{
    le_event_FdEventType_t eventType = (le_event_FdEventType_t)param2Ptr;
    event_PerThreadRec_t* perThreadRecPtr = thread_GetEventRecPtr();

    LOCK

    // Get a pointer to the FD Monitor object for this fd.
    FdMonitor_t* fdMonitorPtr = le_ref_Lookup(FdMonitorRefMap, param1Ptr);

    UNLOCK

    // If the FD Monitor object has been deleted, we can just ignore this.
    if (fdMonitorPtr != NULL)
    {
        LE_ASSERT(perThreadRecPtr == fdMonitorPtr->threadRecPtr);

        Handler_t* handlerPtr = &(fdMonitorPtr->handlerArray[eventType]);

        if (handlerPtr->handlerFunc != NULL)
        {
            // Set the thread's Context Pointer.
            event_SetCurrentContextPtr(handlerPtr->contextPtr);

            // Call the handler function.
            handlerPtr->handlerFunc(fdMonitorPtr->fd);
        }
        else
        {
            TRACE("Discarding event %s for FD Monitor %s (fd %d).",
                  GetFdEventTypeName(eventType),
                  fdMonitorPtr->name,
                  fdMonitorPtr->fd);

            // If this is a write hang-up, then we need to tell epoll to stop monitoring
            // this fd, because otherwise we could end up wasting power and spamming the
            // log with debug messages while we detect and discard this event over and over.
            if (eventType == LE_EVENT_FD_WRITE_HANG_UP)
            {
                StopMonitoringFd(fdMonitorPtr);
            }
        }
    }
    else
    {
        TRACE("Discarding event %s for non-existent FD Monitor.", GetFdEventTypeName(eventType));
    }
}
예제 #2
0
파일: fdMonitor.c 프로젝트: tegoo/legato-af
//--------------------------------------------------------------------------------------------------
static void DispatchToHandler
(
    void* param1Ptr,    ///< FD Monitor safe reference.
    void* param2Ptr     ///< epoll() event flags.
)
//--------------------------------------------------------------------------------------------------
{
    uint32_t epollEventFlags = (uint32_t)(size_t)param2Ptr;

    LOCK

    // Get a pointer to the FD Monitor object for this fd.
    FdMonitor_t* fdMonitorPtr = le_ref_Lookup(FdMonitorRefMap, param1Ptr);

    UNLOCK

    // If the FD Monitor object has been deleted, we can just ignore this.
    if (fdMonitorPtr == NULL)
    {
        TRACE("Discarding events for non-existent FD Monitor %p.", param1Ptr);
        return;
    }

    // Sanity check: The FD monitor must belong to the current thread.
    LE_ASSERT(thread_GetEventRecPtr() == fdMonitorPtr->threadRecPtr);

    // Mask out any events that have been disabled since epoll_wait() reported these events to us.
    epollEventFlags &= (fdMonitorPtr->epollEvents | EPOLLERR | EPOLLHUP | EPOLLRDHUP);

    // If there's nothing left to report to the handler, don't call it.
    if (epollEventFlags == 0)
    {
        // Note: if the fd is always ready to read or write (is not supported by epoll()), then
        //       we will only end up in here if both POLLIN and POLLOUT are disabled, in which case
        //       returning now will prevent re-queuing of DispatchToHandler(), which is what we
        //       want.  When either POLLIN or POLLOUT are re-enabled, le_fdMonitor_Enable() will
        //       call fdMon_Report() to get things going again.
        return;
    }

    // Translate the epoll() events into poll() events.
    short pollEvents = EPollToPoll(epollEventFlags);

    if (IS_TRACE_ENABLED())
    {
        char eventsTextBuff[128];

        TRACE("Calling event handler for FD Monitor %s (fd %d, events %s).",
              fdMonitorPtr->name,
              fdMonitorPtr->fd,
              GetPollEventsText(eventsTextBuff, sizeof(eventsTextBuff), pollEvents));
    }

    // Increment the reference count on the Monitor object in case the handler deletes it.
    le_mem_AddRef(fdMonitorPtr);

    // Store a pointer to the FD Monitor as thread-specific data so le_fdMonitor_GetMonitor()
    // and le_fdMonitor_GetContextPtr() can find it.
    LE_ASSERT(pthread_setspecific(FDMonitorPtrKey, fdMonitorPtr) == 0);

    // Set the thread's event loop Context Pointer.
    event_SetCurrentContextPtr(fdMonitorPtr->contextPtr);

    // Call the handler function.
    fdMonitorPtr->handlerFunc(fdMonitorPtr->fd, pollEvents);

    // Clear the thread-specific pointer to the FD Monitor.
    LE_ASSERT(pthread_setspecific(FDMonitorPtrKey, NULL) == 0);

    // If this fd is always ready (is not supported by epoll) and either POLLIN or POLLOUT
    // are enabled, then queue up another dispatcher for this FD Monitor.
    // If neither are enabled, then le_fdMonitor_Enable() will queue the dispatcher
    // when one of them is re-enabled.
    if ((fdMonitorPtr->isAlwaysReady) && (fdMonitorPtr->epollEvents & (EPOLLIN | EPOLLOUT)))
    {
        fdMon_Report(fdMonitorPtr->safeRef, fdMonitorPtr->epollEvents & (EPOLLIN | EPOLLOUT));
    }

    // Release our reference.  We don't need the Monitor object anymore.
    le_mem_Release(fdMonitorPtr);
}