Esempio n. 1
0
void *_laytube_toFile(void *args){

    long unsigned int expansion_size;
    void *pause_after;
    tubeID *pTube;
    rohrStation sendingStation;
    rohrStation receivingStation;

    pTube = (tubeID *) args;


    /* Populate Station Information */
    sendingStation.stationSize = comedi_get_buffer_size(pTube->dev, pTube->subdev);
    receivingStation.stationSize = _file_size(pTube->tail);
    expansion_size = 64 * sysconf(_SC_PAGESIZE); /* Set file expansion size to a mulitple of memory page size */
    if (expansion_size < sendingStation.stationSize){
        pTube->tubeStatus = pTube->tubeStatus | TUBE_FAILED;
        pthread_exit(NULL);
    }

    /* Check for empty file */
    if (receivingStation.stationSize < 1){
        receivingStation.stationSize = expansion_size; /*  Let's make the file one page-size in length */
        ftruncate(pTube->tail, receivingStation.stationSize);
    }

    /* Set up COMEDI ring buffer memory map */
    sendingStation.firstByte = mmap(NULL, sendingStation.stationSize, PROT_READ, MAP_SHARED, pTube->mouth, 0);
    if (sendingStation.firstByte == MAP_FAILED){
        pTube->tubeStatus = pTube->tubeStatus | TUBE_FAILED;
        pthread_exit(NULL);
    }
    sendingStation.address = sendingStation.firstByte;
    sendingStation.lastByte = sendingStation.firstByte + sendingStation.stationSize - 1; /* Last valid byte */

    /* Set up HDD file memory map */
    receivingStation.firstByte = mmap(NULL, receivingStation.stationSize, PROT_WRITE | MAP_HUGETLB, MAP_SHARED, pTube->tail, 0);
    if (receivingStation.firstByte == MAP_FAILED){
        pTube->tubeStatus = pTube->tubeStatus | TUBE_FAILED;
        pthread_exit(NULL);
    }
    receivingStation.address = receivingStation.firstByte;
    receivingStation.lastByte = receivingStation.firstByte + receivingStation.stationSize - 1; /* Last valid byte */


    /* Stations are setup... set status and command flags... */
    pTube->tubeCmd = 0x00;
    pTube->tubeStatus = TUBE_INPLACE; /* <-- un-blocks laytube_toFile to return to calling function */

    /* Core algorithm - This while loop handles the data transfer from ring buffer to disk */
    while( !(pTube->tubeCmd & TUBE_STOP) ){

        /* Check if the storage file is out or about to be out of space */
        if (sendingStation.stationSize >= (receivingStation.lastByte - receivingStation.address) ){
           if (_growStation(&receivingStation, pTube->tail, expansion_size) == -1){
                pTube->tubeStatus = pTube->tubeStatus | TUBE_FAILED;
                pthread_exit(NULL);
           }
        }

        pause_after = sendingStation.firstByte + comedi_get_buffer_contents(pTube->dev, pTube->subdev) - 1;

        if (pause_after < sendingStation.address){
            pTube->bytesMoved = receivingStation.address - receivingStation.firstByte;
            /* comedi_poll(pTube->dev, pTube->subdev)); */
            usleep(10); /* TODO: optimize by setting sleep number to best guess at when data might show up again */
        }
        else if (pause_after < sendingStation.lastByte) /* Confirm COMEDI ring buffer has not aliased */
        {
            do {
                *((CARRIER *)receivingStation.address++) = *((CARRIER *)sendingStation.address++);
            } while(sendingStation.address <= pause_after);
        }
        else if (pause_after >= sendingStation.lastByte) /* COMEDI ring buffer has aliased... copy up to end of ring buffer and reset */
        {
            do {
                *((CARRIER *)receivingStation.address++) = *((CARRIER *)sendingStation.address++);
            } while(sendingStation.address <= sendingStation.lastByte);

            comedi_mark_buffer_read(pTube->dev, pTube->subdev, sendingStation.stationSize); /* Reset the ring buffer mark */
            sendingStation.address = sendingStation.firstByte;
        }
        else
        {
            pTube->tubeStatus = pTube->tubeStatus | TUBE_FAILED;
            pthread_exit(0);
        }
    }

    /* Clean up Stations, truncate file, flush tube */
    expansion_size = receivingStation.address - receivingStation.firstByte; /* 'address' should point to one byte past last byte written */
    ftruncate(pTube->tail, expansion_size);
    fsync(pTube->tail);
    pTube->bytesMoved = expansion_size;

    pTube->tubeStatus = pTube->tubeStatus | TUBE_EXIT;

    pthread_exit(0);
}
Esempio n. 2
0
int myBoard_distributeData( int board ) {

    MY_BOARD_HARDWARE *pBoardHard = myBoard_getHardwareBoard( board );
    MY_BOARD_SOFTWARE *pBoardSoft = myBoard_getSoftwareBoard( board );

    if (pBoardHard == NULL || pBoardSoft == NULL) {
        return 0;
    }

    int numAvailableByte = comedi_get_buffer_contents(
        pBoardHard->p_comediFileHandle,
        pBoardHard->subDeviceNumber
    );

    if (numAvailableByte >= pBoardHard->buffer_size_in_byte) {
        fprintf( stderr, "processing too slow, lost data for board[%d]\n", board );
    }

    size_t dataSize = (pBoardHard->valueIsLsampl_t)?sizeof(lsampl_t):sizeof(sampl_t);

    int numAvailableSample = numAvailableByte / dataSize;

    int numInput = pBoardSoft->numberOfActiveAnalogInputs;
    /* we only deal with whole scans */
    int numScan = numAvailableSample / numInput;

    int odd = numAvailableSample % numInput;

    /* fprintf( stderr, "checking data: numAvailableSample=%d, numScan=%d odd=%d\n", numAvailableSample, numScan, odd ); */

    if (numScan <= 0) {
        return 0;
    }

    numAvailableSample = numInput * numScan;

    int i;

    epicsMutexMustLock( pBoardSoft->boardLock );

    if (pBoardHard->valueIsLsampl_t) {
        lsampl_t *pBuffer = (lsampl_t*)pBoardHard->buffer;

        for (i = 0; i < numAvailableSample; ++i) {
            int offset = pBoardHard->indexRead++ % pBoardHard->buffer_size_in_sample;
            double vRaw = pBuffer[offset];
            int indexChannel = i % numInput;
            double v = vRaw * pBoardHard->channelRawToVoltA[indexChannel]
            + pBoardHard->channelRawToVoltB[indexChannel];

            appendDataToMyRingBuffer( pBoardSoft->channel_buffer + indexChannel, v, 0 );
        }
    } else {
        sampl_t *pBuffer = (sampl_t*)pBoardHard->buffer;

        for (i = 0; i < numAvailableSample; ++i) {
            int offset = pBoardHard->indexRead++ % pBoardHard->buffer_size_in_sample;
            double vRaw = pBuffer[offset];
            int indexChannel = i % numInput;
            double v = vRaw * pBoardHard->channelRawToVoltA[indexChannel]
            + pBoardHard->channelRawToVoltB[indexChannel];

            appendDataToMyRingBuffer( pBoardSoft->channel_buffer + indexChannel, v, 0 );
        }
    }

    epicsMutexUnlock( pBoardSoft->boardLock );

    int numReadByte = numAvailableSample * dataSize;
    comedi_mark_buffer_read(
        pBoardHard->p_comediFileHandle,
        pBoardHard->subDeviceNumber,
        numReadByte
    );
    scanIoRequest( pBoardSoft->ioScanPvt );

    return numScan;
}