/* * Copyright (c) 2020 Elvees (support@elvees.com) * $Id: $ * $Name: Dmitry Evtushenko $ */ #include "fifo.h" #ifdef __linux__ #include #include #elif defined(__FREERTOS__) //#include "platform.h" #include "msg.h" #include "ddi/defines.h" #include #endif //__FREERTOS__ bool fifo_init( struct fifo_s *pf, u32 sz_fifo, u32 sz_item, pf_create_fitem_t pf_create, void *pcarg, pf_delete_fitem_t pf_delete, u32 opt) { struct fitem_s *pfi = NULL; struct fitem_s *pfi_end = NULL; u32 i; if( pf==NULL || (pf_create==NULL && sz_item==0) || sz_fifo==0 ) return false; memset( pf, 0, sizeof(*pf)); pf->pf_create = pf_create; pf->pf_delete = pf_delete; pf->p_crt_arg = pcarg; pf->opt = opt; for( i=0; ip_begin==NULL) pf->p_begin = pfi; if( pfi_end) pfi_end->p_next = pfi; if( pfi && (pf->opt & FIFO_OPT__DOUBLE_LINK)) ((struct dfitem_s *)pfi)->p_prev = (struct dfitem_s *)pfi_end; pfi_end = pfi; } pfi_end->p_next = pf->p_begin; if( pf->opt & FIFO_OPT__DOUBLE_LINK) ((struct dfitem_s *)pf->p_begin)->p_prev = (struct dfitem_s *)pfi_end; pf->sz_fifo = sz_fifo; fifo_reset( pf); return true; } void fifo_free( struct fifo_s *pf) { struct fitem_s *pfi; struct fitem_s *pfi_next; struct fitem_s *pfi_beg = pf->p_begin; for( pfi=pfi_beg; pfi; pfi=pfi_next ) { pfi_next = pfi->p_next; if( pf->pf_delete) pf->pf_delete( pfi); else kfree( pfi); if( pfi_next==pfi_beg) break; } pf->p_begin = NULL; pf->sz_fifo = 0; pf->pf_create = NULL; pf->pf_delete = NULL; fifo_reset( pf); } void fifo_reset( struct fifo_s *pf) { pf->p_first_free = pf->p_first_held = pf->p_begin; #ifdef USE_FIFO_DEBUG pf->cntFree = 0; pf->cntHeld = 0; #endif //USE_FIFO_DEBUG } struct fitem_s *fifo_hold_first_free( struct fifo_s *pf) { struct fitem_s *pfi_last_held = pf->p_first_free; if( pf->p_first_free->p_next==pf->p_first_held) return NULL; pf->p_first_free = pf->p_first_free->p_next; #ifdef USE_FIFO_DEBUG ++pf->cntHeld; #endif //-USE_FIFO_DEBUG return pfi_last_held; } int fifo_get_free_cnt( struct fifo_s *pf) { struct fitem_s *pfi = pf->p_first_free; u32 cnt = pf->sz_fifo, i; for( i=0; (ip_next) { if( pfi->p_next==pf->p_first_held) break; } return i; } bool fifo_is_next_free( struct fifo_s *pf, int cntFree) { struct fitem_s *pfi = pf->p_first_free; u32 cnt = pf->sz_fifo, i; for( i=0; (ip_next) { if( pfi->p_next==pf->p_first_held) break; if( ++i >= cntFree) return true; } return false; } struct fitem_s *fifo_free_first_held( struct fifo_s *pf) { struct fitem_s *pfi_last_free = pf->p_first_held; if( pf->p_first_held == pf->p_first_free) return NULL; pf->p_first_held = pf->p_first_held->p_next; #ifdef USE_FIFO_DEBUG ++pf->cntFree; #endif //-USE_FIFO_DEBUG return pfi_last_free; } int fifo_get_held_cnt( struct fifo_s *pf) { struct fitem_s *pfi = pf->p_first_held; u32 cnt = pf->sz_fifo, i; for( i=0; (i < cnt); ++i, pfi=pfi->p_next) { if( pfi==pf->p_first_free) break; } return i; } bool fifo_is_next_held( struct fifo_s *pf, int cntLaid) { struct fitem_s *pfi = pf->p_first_held; u32 cnt = pf->sz_fifo, i; for( i=0; (ip_next) { if( pfi==pf->p_first_free) break; if( ++i >= cntLaid) return true; } return false; } void fifo_print( struct fifo_s *pf) { pr_info( "Fifo info: pointer=0x%p\n", pf); pr_info( " Size FIFO: %i\n", pf->sz_fifo); pr_info( " Begin item: 0x%p\n", pf->p_begin); pr_info( " First free item: 0x%p\n", pf->p_first_free); pr_info( " First held item: 0x%p\n", pf->p_first_held); } #ifdef USE_FIFO_DEBUG /*void fifo_reset_counters( struct fifo_s *pf) { pf->cntFree = pf->cntHeld = 0; } // get current quantity of held item as difference between counters: // inaccurate estimate in multithreading !!! u32 fifo_get_held_qnt( struct fifo_s *pf) { return (pf->cntHeld - pf->cntFree); }*/ #endif //-USE_FIFO_DEBUG