Exemple #1
0
/** The driver_wait function to work out if we have used more time then available to process one cycle.
    This is written once for either timespec (HAVE_CLOCK_GETTIME) or jack_time_t, see the unified_jack_time.h file.

    This function manages the time now and the next expected time to return. The return happens once per block of time (period_size).

    The general idea of *_driver_wait is to do the following :
    a] Mark the time now if this is the first time through or if an overrun previously happened.
    b] If an overrun is detected (we have exceeded the maximum time held in our audio buffers) then indicate.
    c] If we are late but not dangerously, then keep going.
    d] If we are early then sleep a little to allow clients enough time to process.

    The effect of 'c]' and 'd]' is to create time pumping. Theoretically we will always be either a little over or under time, and it will be difficult to match audio block
    time exactly. This doesn't matter if the time pumping is a small fraction of our block time. This means that the clients will have slightly more or less then audio block
    time to process.
*/
static jack_nframes_t iio_driver_wait(iio_driver_t *driver, int extra_fd, int *status, float *delayed_usecs) {
	jack_nframes_t nframes = driver->period_size;
    //Debugger<<"iio_driver_wait\n";
    *delayed_usecs = 0;
    *status = 0;

    timeType now; getNow(&now); // the time right now

	if (compareTimesLt(NEXT_TIME, now)) { // NEXT_TIME < now  ... this is a problem as the next time should be >= now
        //printf("iio_driver_wait NOT good\n");
        if (compareTimeZero(NEXT_TIME)) { /* first time through */
            //DebuggerLocal<<"iio_driver_first time - OK\n";
            //printf("first time through\n\n\n");
			getNow(&NEXT_TIME); // reset the next time to now, will be incremented later
        } else if (timeDiffUsComp(now, driver->next_wakeup, driver->maxDelayUSecs)) { /* xrun = (now - NEXT_TIME) > maxDelayTime */
            ////Debugger<<"NEXT_TIME "<<NEXT_TIME<<" now "<<now<<endl;
            jack_error("**** iio: xrun of %ju usec", timeDiffUs(now, NEXT_TIME));
            nframes=0; // indicated the xrun
            zeroTime(&NEXT_TIME);  // reset the next time to zero because of the overrun, we don't know when to start again.
            //*status=-1; // xruns are fatal
        } else /* late, but handled by our "buffer" */
            ;
	} else { // now sleep to ensure we give the clients enough time to process
        *status = nanoSleep(NEXT_TIME, delayed_usecs);
        //printf("iio_driver_wait all good\n");
    }

    if (nframes!=0) // if there is no xrun, then indicate the next expected time to land in this funciton.
        NEXT_TIME=addTimes(NEXT_TIME, driver->wait_time);

	driver->last_wait_ust = driver->engine->get_microseconds ();
	driver->engine->transport_cycle_start (driver->engine, driver->last_wait_ust);

	return nframes;
}
static void vmct_shutdown(void)
{
    int i;
    static unsigned char once = 0;

    if (once) {
        return;
    } else {
        once = 1;
    }

    /* socket fd close (HOST TCP - Client)  */
    pthread_mutex_lock(&TcpHostMutex);
    if (tlinkHOST.mode == LINK_MODE_CLIENT) {
        if (tlinkHOST.ListenFD > 0) {
            close(tlinkHOST.ListenFD);
            FD_CLR(tlinkHOST.ListenFD, &allsetHOST);
            tlinkHOST.ListenFD = -1;
        }

    } else if (tlinkHOST.mode == LINK_MODE_SERVER) {
        for (i = 0; i < MAX_LISTENQ; i++) {
            if (alist[i].AcceptFD > 0) {
                close(alist[i].AcceptFD);
                FD_CLR(alist[i].AcceptFD, &allsetHOST);
                alist[i].AcceptFD = -1;
            }
        }
        if (tlinkHOST.ListenFD > 0) {
            close(tlinkHOST.ListenFD);
            FD_CLR(tlinkHOST.ListenFD, &allsetHOST);
            tlinkHOST.ListenFD = -1;
        }

    }
    pthread_mutex_unlock(&TcpHostMutex);

    for (i = 0; i < MAX_PTASK; i++) {
        if (ThreadFlags[i] != TRUE) {
            continue;
        }
        ThreadAlive[i] = FALSE;
        xprint(FMS_VMC | FMS_LOOKS, "%s :: ThreadFlags(%d)\n", __func__, i);
        pthread_cancel(ThreadArray[i]);
        nanoSleep(10);
    }

    pthread_mutex_destroy(&TcpHostMutex);

    close_xprint();
    terminateLog();
    exit(0);
}
void *ResetWatchdogTask(void *argc)
{
    struct timeval tv;
    struct tm ctime;
    int sectime, check1sec = FALSE;

    ThreadAlive[PTASK4] = TRUE;

    pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
    pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
    pthread_cleanup_push(ThreadCleanUp, (void *)NULL);

    gettimeofday(&tv, NULL);
    localtime_r((time_t *)&(tv.tv_sec), &ctime);

    sectime = ctime.tm_sec;

    for (;;) {
        if (ThreadAlive[PTASK4] != TRUE) {
            break;
        }

        gettimeofday(&tv, NULL);
        localtime_r((time_t *)&(tv.tv_sec), &ctime);

        /* check for every sec */
        if (sectime != ctime.tm_sec) {
            if (check1sec != TRUE && CHECK_WATCHDOG_MSEC != 0) {
                xprint(FMS_HST | FMS_INFO5, "%s :: Rest Bypass WatchDog Start\n", __func__);
                /* re-set bypass watchdog */
                ResetBypassWatchdog(); 

                sectime = ctime.tm_sec;
                check1sec = TRUE;
                xprint(FMS_HST | FMS_INFO5, "%s :: Rest Bypass WatchDog End\n", __func__);
            }
        } else {
            check1sec = FALSE;
        }

        nanoSleep(100);


    }

    ThreadAlive[PTASK4] = FALSE;
    ThreadFlags[PTASK4] = FALSE;

    pthread_cleanup_pop(1);

    return(NULL);
}
void *CheckTcpStatusTask(void *argc)
{
    int check1min;
    struct timeval tv;
    struct tm ctime;

    ThreadAlive[PTASK3] = TRUE;

    pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
    pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
    pthread_cleanup_push(ThreadCleanUp, (void *)NULL);

    check1min = FALSE;

    /* tmphandler */
    for (;;) {
        if (ThreadAlive[PTASK3] != TRUE) {
            break;
        }

        gettimeofday(&tv, NULL);
        localtime_r((time_t *)&(tv.tv_sec), &ctime);

        /* every minute */
        if (ctime.tm_sec == 15) {
            if (check1min != TRUE) {
                xprint(FMS_HST | FMS_INFO1, "%s : Check TCP Status START\n", __func__);

                /* TCP status */
                CheckTcpStatus();

                check1min = TRUE;
                xprint(FMS_HST | FMS_INFO1, "%s : Check TCP Status End\n", __func__);
             }

        } else {
            check1min = FALSE;
        }

        nanoSleep(100);
    }

    ThreadAlive[PTASK3] = FALSE;
    ThreadFlags[PTASK3] = FALSE;

    pthread_cleanup_pop(1);

    return(NULL);
}
void *CheckVmStatusTask(void *argc)
{
    int FiveSecCheck = FALSE;
    struct tm ctime;
    struct timeval tv;

    ThreadAlive[PTASK2] = TRUE;

    pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
    pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
    pthread_cleanup_push(ThreadCleanUp, (void *)NULL);

    for (;;) {
        if (ThreadAlive[PTASK2] != TRUE) {
            break;
        }

        nanoSleep(100);

        gettimeofday(&tv, NULL);
        localtime_r((time_t *)&(tv.tv_sec), &ctime);

        /* check  5sec */
        if ((ctime.tm_sec % CHECK_VMCSTATUS_SEC) == 0) {
            if (FiveSecCheck == TRUE) {
                continue;
            }

            xprint(FMS_HST | FMS_INFO1, "Check VM Status %dsec (Bypass Mode : %s [vms(%s) / tcp(%s)]) )\n",
                            CHECK_VMCSTATUS_SEC, (hostConf.bp_mode == BYPASS_MODE_ON) ? "ON" : "OFF",
                            (hostConf.vmc_mode == BYPASS_MODE_ON) ? "ON" : "OFF", 
                            (hostConf.tcp_mode == BYPASS_MODE_ON) ? "ON" : "OFF");

            CheckVmcStatus();

            FiveSecCheck = TRUE;

        } else {
            FiveSecCheck = FALSE;
        }
    }

    ThreadAlive[PTASK2] = FALSE;
    ThreadFlags[PTASK2] = FALSE;

    pthread_cleanup_pop(1);

    return(NULL);
}
bool Timer::_nanosleep(size_t secs_, size_t nsecs_)
{
    size_t secs = 0;
    size_t nsecs = 0;
    
    secs = secs_;
    nsecs = nsecs_;
    
    if(nsecs >= 1000000000){
        secs += nsecs / 1000000000;
        nsecs %= 1000000000;
    }
    
    return nanoSleep(secs, nsecs);
}
int main(int argc, char *argv[])
{
    char *pEnv;

    /*--------------------------------------------------------------------------
      중복 프로세스 체크
      ---------------------------------------------------------------------------*/
    if (dupcheckbyname(argv[0]) != 0) {
        fprintf(stderr, "oops!!! duplicated process(%s). So, exit\n", argv[0]);
        exit(0);
    }

    /*--------------------------------------------------------------------------
      시그널 등록
      ---------------------------------------------------------------------------*/
    setupSignal(vmct_signal_handler);

    /*--------------------------------------------------------------------------
      Init Environment
      ---------------------------------------------------------------------------*/
    /* get environment variable */
    if ((pEnv = getenv(BPAPP_ENV_NAME)) == NULL){
        fprintf(stderr, "'%s' environment variable not found(%s)\n", BPAPP_ENV_NAME, strerror(errno));
        exit(0);
    }

    /*--------------------------------------------------------------------------
      디버그 프린트 및 로그 초기화
      ---------------------------------------------------------------------------*/
#if 0
    InitDebug(pEnv, FMS_VMC | FMS_CLB, FMS_INFO1, DBG_TERMINAL | DBG_FILE | DBG_THIS);
#else
    InitDebug(pEnv, FMS_VMC | FMS_CLB, FMS_INFO1, DBG_FILE | DBG_THIS);
#endif

    xprint(FMS_VMC | FMS_LOOKS, "\n");
    xprint(FMS_VMC | FMS_LOOKS, "*********************************************************************\n");
    xprint(FMS_VMC | FMS_LOOKS, "     BPAPP-VMCT : START \n");
    xprint(FMS_VMC | FMS_LOOKS, "*********************************************************************\n");
    xprint(FMS_VMC | FMS_LOOKS, "\n");

    /* Init Global Variable */
    if (InitVariable() < 0) {
        xprint(FMS_VMC | FMS_FATAL, "Initialize failed, So exit\n");
        terminateLog();
        close_xprint();
        exit(0);
    }

    /* Init config from cfgFile */
    if (read_config(pEnv) < 0) {
        xprint(FMS_VMC | FMS_FATAL, "Global Configuration error, So exit\n");
        close_xprint();
        exit(0);
    }

    /* Init Mutex & MsgQCmdTmr */
    InitMutexCmdTmr();

#ifdef __DEBUG__
    DebugSizeofStruct();
    DebugVmctInfo();
    DebugVmProcessInfo();
#endif

    /*--------------------------------------------------------------------------
      pthread Create
     ---------------------------------------------------------------------------*/
    /* TCP Recv Control (HOST) */
    if (ThreadFlags[PTASK0] == FALSE) {
        pthread_attr_init(&Thread_Attr[PTASK0]);
        pthread_attr_setdetachstate(&Thread_Attr[PTASK0], PTHREAD_CREATE_DETACHED);
        pthread_create(&ThreadArray[PTASK0], &Thread_Attr[PTASK0], TcpRcvTask, NULL);
        pthread_attr_destroy(&Thread_Attr[PTASK0]);
        ThreadFlags[PTASK0] = TRUE;
    }

    /* System Info HOST Send */
    if (ThreadFlags[PTASK1] == FALSE) {
        pthread_attr_init(&Thread_Attr[PTASK1]);
        pthread_attr_setdetachstate(&Thread_Attr[PTASK1], PTHREAD_CREATE_DETACHED);
        pthread_create(&ThreadArray[PTASK1], &Thread_Attr[PTASK1], TcpSessionTask, NULL);
        pthread_attr_destroy(&Thread_Attr[PTASK1]);
        ThreadFlags[PTASK1] = TRUE;
    }

    /* Timer Cmd (TCP Reconnect) */
    if (ThreadFlags[PTASK2] == FALSE) {
        pthread_attr_init(&Thread_Attr[PTASK2]);
        pthread_attr_setdetachstate(&Thread_Attr[PTASK2], PTHREAD_CREATE_DETACHED);
        pthread_create(&ThreadArray[PTASK2], &Thread_Attr[PTASK2], TmrCmdTask, NULL);
        pthread_attr_destroy(&Thread_Attr[PTASK2]);
        ThreadFlags[PTASK2] = TRUE;
    }

    RunState = 1;

    while(RunState != 0) {
        nanoSleep(1000);
    }

    pthread_join(ThreadArray[PTASK0], NULL);
    pthread_join(ThreadArray[PTASK1], NULL);
    pthread_join(ThreadArray[PTASK2], NULL);

    return(0);
}
void *ProcessVmStateTask(void *argc)
{
    struct timeval tv;
    struct tm ctime;
    int check5sec = FALSE;
    char ttime[MAX_TIME_LENGTH];
    int sleep_flag;

    ThreadAlive[PTASK5] = TRUE;

    pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
    pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
    pthread_cleanup_push(ThreadCleanUp, (void *)NULL);

    sleep_flag = 0;

    gettimeofday(&tv, NULL);
    localtime_r((time_t *)&(tv.tv_sec), &ctime);

    for (;;) {
        if (ThreadAlive[PTASK5] != TRUE) {
            break;
        }

        /* Check DB orchehandler, 10s */
        sleep_flag++;
        if (sleep_flag > 50000) {
#if 0
            CheckTimeOrcheHLR();
#endif
            sleep_flag = 0;
        }

        gettimeofday(&tv, NULL);
        localtime_r((time_t *)&(tv.tv_sec), &ctime);

        /* check 5sec */
        if ((ctime.tm_sec % 5) == 2) {
            if (check5sec == TRUE) {
                continue;
            }

            xprint(FMS_VMC | FMS_LOOKS, "%s :: Now Time[= %01d:%02d:%02d]\n", __func__,
                                        ctime.tm_hour, ctime.tm_min, ctime.tm_sec);

            memset(&ttime, 0x00, sizeof(ttime));
            sprintf(ttime, "%04d-%02d-%02d, %02d:%02d:%02d",
                   ctime.tm_year + 1900, ctime.tm_mon + 1, ctime.tm_mday,
                   ctime.tm_hour, ctime.tm_min, ctime.tm_sec-2);

            ProcessVmProcStateInfo(ttime);

            check5sec = TRUE;

        } else {
            check5sec = FALSE;
        }

        nanoSleep(100);
    }

    ThreadAlive[PTASK5] = FALSE;
    ThreadFlags[PTASK5] = FALSE;

    pthread_cleanup_pop(1);

    return(NULL);
}