/******************************************************************************* * @file rbuf_pool.c * @author MEMS Application Team * @version V1.0 * @date 2020-10-15 * @brief ring buffer pool for interaction RAM *******************************************************************************/ /******************************************************************************/ //includes /******************************************************************************/ #include #include #include /******************************************************************************/ //constants /******************************************************************************/ /******************************************************************************/ //typedef /******************************************************************************/ /******************************************************************************/ //variables /******************************************************************************/ /******************************************************************************/ //functions /******************************************************************************/ static rbuf_node_t *_pool_alloc_node(rbuf_pool_t *pool, unsigned int size) { rbuf_node_t *node = RBUF_NULL; if (pool->buf_size >= sizeof(rbuf_node_t)) { /* alloc from free buffer */ node = (rbuf_node_t*)RBUF_FR_OF(pool->buf_off); node->blk_list = 0; node->blk_size = size; node->next = 0; /* update free buffer */ pool->buf_off += sizeof(rbuf_node_t); pool->buf_size -= sizeof(rbuf_node_t); } return node; } static rbuf_node_t *_pool_get_node(rbuf_pool_t *pool, unsigned int size) { rbuf_node_t *node = &pool->root; rbuf_node_t *prev = NULL; /* node search */ while ((node != RBUF_NULL) && (node->blk_size < size)) { prev = node; node = (rbuf_node_t*)RBUF_FR_OF(node->next); } /* add node to list */ if ((node == RBUF_NULL) || (node->blk_size > size)) { node = _pool_alloc_node(pool, size); if (node != RBUF_NULL) { node->next = prev->next; prev->next = RBUF_TO_OF(node); } } return node; } rbuf_pool_t *rbuf_pool_init(char *buf, unsigned int size) { rbuf_pool_t *pool = (rbuf_pool_t*)buf; pool->buf_off = RBUF_TO_OF(buf) + sizeof(rbuf_pool_t); pool->buf_size = size - sizeof(rbuf_pool_t); pool->root.blk_size = 0; pool->root.blk_list = 0; pool->root.next = 0; return pool; } rbuf_t *rbuf_pool_alloc(rbuf_pool_t *pool, unsigned int size, unsigned int mode) { rbuf_node_t *node; rbuf_t *buf = NULL; unsigned int buf_size; /* get node */ size = ROUND_UP(size, 4); node = _pool_get_node(pool, size); if (node == RBUF_NULL) { return NULL; } /* alloc rbuf */ while (node != RBUF_NULL) { buf_size = sizeof(rbuf_t) + node->blk_size; if (node->blk_list > 0) { /* alloc from free blk list */ buf = RBUF_FR_OF(node->blk_list); node->blk_list = buf->next; break; } if (pool->buf_size >= buf_size) { /* alloc from free buffer */ buf = RBUF_FR_OF(pool->buf_off); pool->buf_off += buf_size; pool->buf_size -= buf_size; break; } node = (rbuf_node_t*)RBUF_FR_OF(node->next); } /* init rbuf */ if (buf != NULL) { rbuf_init_buf((char*)buf, buf_size, mode); buf->next = RBUF_TO_OF(node); } return buf; } int rbuf_pool_free(rbuf_t *buf) { rbuf_node_t *node; if (buf->next != 0) { node = (rbuf_node_t*)RBUF_FR_OF(buf->next); /* free to free blk list */ buf->next = node->blk_list; node->blk_list = RBUF_TO_OF(buf); } return 0; } #if RBUF_POOL_DBG void rbuf_pool_dump(rbuf_pool_t *pool) { rbuf_node_t *node = &pool->root; rbuf_t *buf; /* dump free */ printf("free: [0x%04x] [%d]\r\n", (unsigned int)pool->buf_off, pool->buf_size); printf("\r\n"); while (node != RBUF_NULL) { /* dump node */ printf("node: [0x%04x] [%d]\r\n", RBUF_TO_OF(node), node->blk_size); /* dump list */ buf = RBUF_FR_OF(node->blk_list); while (buf != RBUF_NULL) { printf(" -> rbuf: [0x%04x] [%d] [%d]\r\n", RBUF_TO_OF(buf), buf->size, buf->hlen); buf = RBUF_FR_OF(buf->next); } node = (rbuf_node_t*)RBUF_FR_OF(node->next); } printf("\r\n"); } #endif