#include #include #include #include #include #include "bufhandle.h" #define BH_PAGEMAXCOUNT     32 //typedefs typedef unsigned char byte; //memory struct typedef struct tag_bh_struct {    size_t struct_size;    size_t buffer_size;    byte*  buffer_block; } bh_struct, *pbh_struct; //lock struct typedef struct tag_bh_page {    unsigned long addr;    size_t count; } bh_page, *pbh_page; static bh_page bh_pages[BH_PAGEMAXCOUNT]; static bool bh_init = false; /* find page index   returns index < BH_PAGEMAXCOUNT if is found   returns free index if index is not found   returns BH_PAGEMAXCOUNT if no index is available*/ int bh_findpage(unsigned long addr) {    int i;    int freeidx = BH_PAGEMAXCOUNT;    for(i = 0; i < BH_PAGEMAXCOUNT; i++)    {        if(bh_pages[i].addr == 0) freeidx = i;        else if(bh_pages[i].addr == addr) break;    }    if(i == BH_PAGEMAXCOUNT) i = freeidx;    return i; } size_t bh_pagelock(unsigned long page) {    int idx = 0;    if((idx = bh_findpage(page)) != BH_PAGEMAXCOUNT)        return (++bh_pages[idx].count); //increased page counter    else        return 0; //page not locked } size_t bh_pageunlock(unsigned long page) {    int idx = 0;    if((idx = bh_findpage(page)) != BH_PAGEMAXCOUNT)    {        if(bh_pages[idx].count == 0) //page not locked            return 0;        else if(bh_pages[idx].count == 1) //last lock; delete            bh_pages[idx].addr = 0;        return (--bh_pages[idx].count); //decreased page counter    }    else        return 0; //page not locked } // lock memory aligned bh_error_t bh_mlock(byte *addr, size_t len) {    unsigned long page_offset, page_size;    if(bh_init == false)    {        memset(bh_pages, 0, sizeof(bh_page)*BH_PAGEMAXCOUNT);        bh_init = true;    }    page_size = getpagesize();    page_offset = (unsigned long) addr % page_size;    addr -= page_offset; /* Adjust addr to page boundary */    len += page_offset; /* Adjust len with page_offset */    //no page available    if(bh_pagelock((unsigned long)addr) == 0)        return bh_maxhandlecount;    return (mlock(addr, len) == 0 ? bh_no_error : bh_errno); /* Lock the memory */ } // unlock memory aligned bh_error_t bh_unlock(byte *addr, size_t len) {    unsigned long page_offset, page_size;    page_size = getpagesize();    page_offset = (unsigned long) addr % page_size;    addr -= page_offset; /* Adjust addr to page boundary */    len  += page_offset; /* Adjust len with page_offset */    // no lock in that page    if(bh_pageunlock((unsigned long)addr) == 0)        return (munlock(addr, len) == 0 ? bh_no_error : bh_errno); /* Unlock the memory */    return bh_no_error; } // allocate memory and lock void* bh_alloc(size_t size) {    void* block = NULL;    if(bh_init == false)    {        memset(bh_pages, 0, BH_PAGEMAXCOUNT * sizeof(size_t));        bh_init = true;    }    block = malloc(size);    if(block == NULL) return NULL;    if(bh_mlock((byte*)block, size) != bh_no_error)    {        //lock not possible        free(block);        return NULL;    }    /*The write to each page forces Linux to      assign a unique, unshared memory page to      the process for that page. */    memset(block, 0, size);    return block; } // delocate memory and unlock void bh_free(void* block, size_t size) {    if(block == NULL) return;    memset(block, 0, size);    //pretend it works    bh_unlock((byte*)block, size);    free(block); } extern bh_error_t buffer_create(size_t size, buffer_handle_t *handle) {    pbh_struct bufstruct = NULL;    byte* buffer = NULL;    // handle is not valid    if(handle == NULL) return bh_invalid_handle;    // allocate handle structure    bufstruct = (pbh_struct)bh_alloc(sizeof(bh_struct));    if(bufstruct == NULL) return bh_errno;    // allocate buffer    buffer = (byte*)bh_alloc(size);    if(buffer == NULL) return bh_errno;    //fill buffer    bufstruct->struct_size = sizeof(bh_struct);    bufstruct->buffer_size = size;    bufstruct->buffer_block = buffer;    // set handle    *handle = (buffer_handle_t)bufstruct;    return bh_no_error; } extern bh_error_t buffer_release(buffer_handle_t handle) {    // handle check    if(handle == 0) return bh_invalid_handle;    pbh_struct bufstruct = (pbh_struct)handle;    if(bufstruct->struct_size != sizeof(bh_struct)) return bh_invalid_handle;    // free data    bh_free(bufstruct->buffer_block, bufstruct->buffer_size);    bh_free(bufstruct, sizeof(bh_struct));    return bh_no_error; } extern bh_error_t buffer_copy_in(buffer_handle_t handle, void* buffer,                 size_t size, size_t offset) {    if(handle == 0) return bh_invalid_handle;    pbh_struct bufstruct = (pbh_struct)handle;    if(bufstruct->struct_size != sizeof(bh_struct)) return bh_invalid_handle;    if(bufstruct->buffer_size < offset ||       bufstruct->buffer_size - offset < size) return bh_overflow;    memcpy(bufstruct->buffer_block + offset, buffer, size);    return bh_no_error; } extern bh_error_t buffer_copy_out(buffer_handle_t handle, void* buffer,                 size_t size, size_t offset) {    if(handle == 0) return bh_invalid_handle;    pbh_struct bufstruct = (pbh_struct)handle;    if(bufstruct->struct_size != sizeof(bh_struct)) return bh_invalid_handle;    if(bufstruct->buffer_size < offset ||       bufstruct->buffer_size - offset < size) return bh_overflow;    memcpy(buffer, bufstruct->buffer_block + offset, size);    return bh_no_error; }