Program Listing for File cmem_buffer.cpp

Return to documentation for file (cmem_buffer.cpp)

#include <fstream>
#include <iostream>
#include <regex>
#include <cstdlib> // malloc/free
#include <cstdio>

#include "cmem_buffer.hpp"
#include "flxcard/FlxCard.h"
#include "log.hpp"

CmemBuffer::CmemBuffer(size_t size, const std::string& cmem_name, bool free_previous_cmem): DmaBuffer(size), free_previous_cmem(free_previous_cmem)  {
    int ret;

    ret = CMEM_OpenNopage();
    LOG_DBG("Allocating CMEM buffer %s", cmem_name.c_str());
    // free previous buffer if any and requested
    if (!ret && free_previous_cmem) {
        ret = CMEM_SegmentUnlockAndFree(const_cast<char*>(cmem_name.c_str()));
        if (!ret) {
            LOG_INFO("Freed previous CMEM buffer: %s", cmem_name.c_str());
        } else if (RCC_ERROR_MINOR(ret) == CMEM_RCC_ILLNAME) {
            ret = 0;
        } else {
            rcc_error_print(stdout, ret);
        }
    }

    // allocate new one
    if (!ret) {
        ret = CMEM_GFPBPASegmentAllocate(size, const_cast<char*>(cmem_name.c_str()), &handle);
    }

    if (!ret) {
        ret = CMEM_SegmentPhysicalAddress(handle, &paddr);
    }

    if (!ret) {
        ret = CMEM_SegmentVirtualAddress(handle, &vaddr);
    }

    if (!ret) {
        ret = CMEM_SegmentLock(handle);
    }

    if (ret) {
        rcc_error_print(stdout, ret);
        exit(1);
    }
}


CmemBuffer::~CmemBuffer() {
    LOG_DBG("Releasing CMEM buffer with handle %d", handle);
    int ret = CMEM_SegmentUnlock(handle);

    /* int ret = 0;

    if(!ret)
        ret = CMEM_GFPBPASegmentFree(handle);

    if(!ret) {
        ret = CMEM_Close();
    }
    */

    if (ret) {
        rcc_error_print(stdout, ret);
        exit(1);
    }
}


bool CmemBuffer::cmem_buffer_exists(const std::string& cmem_name) {
    //   2771 |      0 |    0x00000002ee800000 | 0x0000000010000000 |    yes |    4 | felix-file2host-0-0
    // \s?\d+\s+\|\s+\d+\s+\|\s+0x\w+\s+\|\s+0x\w+\s+\|\s+\w+\s+\|\s+\d+\s+\|\s
    std::string regex("^");       // start
    regex += "\\s?\\d+\\s+\\|";   // first number
    regex += "\\s+\\d+\\s+\\|";   // number
    regex += "\\s+0x\\w+\\s+\\|"; // hex-number
    regex += "\\s+0x\\w+\\s+\\|"; // hex-number
    regex += "\\s+\\w+\\s+\\|";   // string
    regex += "\\s+\\d+\\s+\\|";   // number
    regex += "\\s+";              // whitespace
    regex.append(cmem_name);      // cmem_name
    regex += "$";                 // end

    std::ifstream file("/proc/cmem_rcc");
    if (!file.is_open()) {
        fprintf(stderr, "Can't open /proc/cmem_rcc\n" );
        return false;
    }

    std::string line;
    while (std::getline(file, line)) {
        if (std::regex_match(line, std::regex(regex))) {
            return true;
        }
    }

    return false;
}


VmemBuffer::VmemBuffer(size_t size) : DmaBuffer(size) {
    ptr = malloc(size);
    if (!ptr) {
        LOG_ERR("Error vmem memory allocation of %zu failed", size);
        throw std::runtime_error("Cannot allocate vmem buffer");
    }
    paddr = 0;
    vaddr = (uint64_t)ptr;
}


VmemBuffer::~VmemBuffer() {
    if (vaddr) {
        free(ptr);
        vaddr = 0;
        ptr = 0;
    }
}