//------------------------------------------------------------------------------
tOplkError eventkcal_exit(void)
{
    UINT    i = 0;

    instance_l.fInitialized = FALSE;
    instance_l.fStopThread = TRUE;

    NdisSetEvent(&instance_l.kernelWaitEvent);
    NdisSetEvent(&instance_l.userWaitEvent);

    while (instance_l.fThreadIsRunning)
    {
        NdisMSleep(10);
        if (i++ > 1000)
        {
            DEBUG_LVL_EVENTK_TRACE("Event thread is not terminating, continue shutdown...!\n");
            break;
        }
    }

    ZwClose(instance_l.hThreadHandle);

    eventkcal_exitQueueCircbuf(kEventQueueK2U);
    eventkcal_exitQueueCircbuf(kEventQueueU2K);
    eventkcal_exitQueueCircbuf(kEventQueueUInt);
    eventkcal_exitQueueCircbuf(kEventQueueKInt);

    return kErrorOk;
}
//------------------------------------------------------------------------------
tOplkError eventkcal_exit(void)
{
    UINT             i = 0;

    if (instance_l.fInitialized == TRUE)
    {
        instance_l.fStopThread = TRUE;
        while (instance_l.fStopThread == TRUE)
        {
            target_msleep(10);
            if (i++ > 100)
            {
                TRACE("Event Thread is not terminating, continue shutdown...!\n");
                break;
            }
        }

        eventkcal_exitQueueCircbuf(kEventQueueK2U);
        eventkcal_exitQueueCircbuf(kEventQueueU2K);
        eventkcal_exitQueueCircbuf(kEventQueueKInt);

        sem_close(instance_l.semUserData);
        sem_close(instance_l.semKernelData);
    }
    instance_l.fInitialized = FALSE;

    return kErrorOk;
}
//------------------------------------------------------------------------------
tOplkError eventkcal_exit(void)
{
    if (instance_l.fInitialized != FALSE)
    {
        eventkcal_exitQueueCircbuf(kEventQueueKInt);
        eventkcal_exitQueueCircbuf(kEventQueueK2U);
        eventkcal_exitQueueCircbuf(kEventQueueU2K);
    }
    instance_l.fInitialized = FALSE;

    return kErrorOk;
}
//------------------------------------------------------------------------------
tOplkError eventkcal_init(void)
{
    struct sched_param  schedParam;

    OPLK_MEMSET(&instance_l, 0, sizeof(tEventkCalInstance));

    if ((instance_l.semUserData = sem_open("/semUserEvent", O_CREAT | O_RDWR, S_IRWXG, 0)) == SEM_FAILED)
        goto Exit;

    if ((instance_l.semKernelData = sem_open("/semKernelEvent", O_CREAT | O_RDWR, S_IRWXG, 0)) == SEM_FAILED)
        goto Exit;

    if (eventkcal_initQueueCircbuf(kEventQueueK2U) != kErrorOk)
        goto Exit;

    if (eventkcal_initQueueCircbuf(kEventQueueU2K) != kErrorOk)
        goto Exit;

    if (eventkcal_initQueueCircbuf(kEventQueueKInt) != kErrorOk)
        goto Exit;

    eventkcal_setSignalingCircbuf(kEventQueueK2U, signalUserEvent);

    eventkcal_setSignalingCircbuf(kEventQueueKInt, signalKernelEvent);

    instance_l.fStopThread = FALSE;
    if (pthread_create(&instance_l.threadId, NULL, eventThread, (void*)&instance_l) != 0)
        goto Exit;

    schedParam.__sched_priority = KERNEL_EVENT_THREAD_PRIORITY;
    if (pthread_setschedparam(instance_l.threadId, SCHED_FIFO, &schedParam) != 0)
    {
        DEBUG_LVL_ERROR_TRACE("%s(): couldn't set thread scheduling parameters! %d\n",
               __func__, schedParam.__sched_priority);
    }

    instance_l.fInitialized = TRUE;
    return kErrorOk;

Exit:
    if (instance_l.semUserData != SEM_FAILED)
        sem_close(instance_l.semUserData);

    if (instance_l.semKernelData != SEM_FAILED)
        sem_close(instance_l.semKernelData);

    eventkcal_exitQueueCircbuf(kEventQueueK2U);
    eventkcal_exitQueueCircbuf(kEventQueueU2K);
    eventkcal_exitQueueCircbuf(kEventQueueKInt);

    return kErrorNoResource;
}
//------------------------------------------------------------------------------
tOplkError eventkcal_init(void)
{
    OPLK_MEMSET(&instance_l, 0, sizeof(tEventkCalInstance));

    if (eventkcal_initQueueCircbuf(kEventQueueU2K) != kErrorOk)
        goto Exit;

    if (eventkcal_initQueueCircbuf(kEventQueueK2U) != kErrorOk)
        goto Exit;

    if (eventkcal_initQueueCircbuf(kEventQueueKInt) != kErrorOk)
        goto Exit;

    instance_l.fInitialized = TRUE;
    return kErrorOk;

Exit:
    eventkcal_exitQueueCircbuf(kEventQueueKInt);
    eventkcal_exitQueueCircbuf(kEventQueueK2U);
    eventkcal_exitQueueCircbuf(kEventQueueU2K);

    return kErrorNoResource;
}
//------------------------------------------------------------------------------
tOplkError eventkcal_init(void)
{
    ULONG                desiredAccess = DELETE | SYNCHRONIZE;
    OBJECT_ATTRIBUTES    objectAttributes;
    NTSTATUS             ntStatus;

    OPLK_MEMSET(&instance_l, 0, sizeof(tEventkCalInstance));

    NdisInitializeEvent(&instance_l.kernelWaitEvent);
    NdisInitializeEvent(&instance_l.userWaitEvent);

    instance_l.userEventCount = 0;
    instance_l.kernelEventCount = 0;

    if (eventkcal_initQueueCircbuf(kEventQueueK2U) != kErrorOk)
        goto Exit;

    if (eventkcal_initQueueCircbuf(kEventQueueU2K) != kErrorOk)
        goto Exit;

    if (eventkcal_initQueueCircbuf(kEventQueueKInt) != kErrorOk)
        goto Exit;

    if (eventkcal_initQueueCircbuf(kEventQueueUInt) != kErrorOk)
        goto Exit;

    eventkcal_setSignalingCircbuf(kEventQueueK2U, signalUserEvent);

    eventkcal_setSignalingCircbuf(kEventQueueU2K, signalKernelEvent);

    eventkcal_setSignalingCircbuf(kEventQueueUInt, signalUserEvent);

    eventkcal_setSignalingCircbuf(kEventQueueKInt, signalKernelEvent);

    InitializeObjectAttributes(&objectAttributes,
                               NULL,
                               OBJ_KERNEL_HANDLE,
                               NULL,
                               NULL);

    instance_l.fStopThread = FALSE;
    ntStatus = PsCreateSystemThread(&instance_l.hThreadHandle,
                                    desiredAccess,
                                    &objectAttributes,
                                    NULL,
                                    NULL,
                                    eventThread,
                                    &instance_l);

    if (ntStatus != STATUS_SUCCESS)
    {
        DEBUG_LVL_ERROR_TRACE("%s() Unable to create event thread 0x%X\n",
                              __func__,
                              ntStatus);
        goto Exit;
    }

    instance_l.fInitialized = TRUE;

    return kErrorOk;

Exit:
    DEBUG_LVL_ERROR_TRACE("%s() Initialization error!\n", __func__);
    eventkcal_exitQueueCircbuf(kEventQueueK2U);
    eventkcal_exitQueueCircbuf(kEventQueueU2K);
    eventkcal_exitQueueCircbuf(kEventQueueKInt);
    eventkcal_exitQueueCircbuf(kEventQueueUInt);

    return kErrorNoResource;
}