//todo ? skip is used to jump over given bytes? int ringbuffer_data(struct ringbuffer * rb, struct ringbuffer_block * blk, int size, int skip, void **ptr) { int length = blk->length - sizeof(struct ringbuffer_block) - blk->offset; for (;;) { if (length > skip) { //length > skip if (length - skip >= size) { char * start = (char *)(blk + 1); *ptr = (start + blk->offset + skip); return size; } //set address to read to NULL *ptr = NULL; int ret = length - skip; //if ret < size ,and blk has next , shift to next while (blk->next >= 0) { blk = block_ptr(rb, blk->next); ret += blk->length - sizeof(struct ringbuffer_block); if (ret >= size) return size; } return ret; } if (blk->next < 0) { assert(length == skip); //length == skip *ptr = NULL; return 0; } //length < skip blk = block_ptr(rb, blk->next); assert(blk->offset == 0); skip -= length; length = blk->length - sizeof(struct ringbuffer_block); } }
int ringbuffer_data(struct ringbuffer * rb, struct ringbuffer_block * blk, int size, int skip, void **ptr) { int length = blk->length - sizeof(struct ringbuffer_block) - blk->offset; for (;;) { if (length > skip) { if (length - skip >= size) { char * start = (char *)(blk + 1); *ptr = (start + blk->offset + skip); return size; } *ptr = NULL; int ret = length - skip; while (blk->next >= 0) { blk = block_ptr(rb, blk->next); ret += blk->length - sizeof(struct ringbuffer_block); if (ret >= size) return size; } return ret; } if (blk->next < 0) { assert(length == skip); *ptr = NULL; return 0; } blk = block_ptr(rb, blk->next); assert(blk->offset == 0); skip -= length; length = blk->length - sizeof(struct ringbuffer_block); } }
void * ringbuffer_copy(struct ringbuffer * rb, struct ringbuffer_block * from, int skip, struct ringbuffer_block * to) { int size = to->length - sizeof(struct ringbuffer_block); int length = from->length - sizeof(struct ringbuffer_block) - from->offset; char * ptr = (char *)(to+1); for (;;) { if (length > skip) { //data length bigger than skip ,need to copy char * src = (char *)(from + 1); src += from->offset + skip; length -= skip; //length of data to copy while (length < size) { //if small than size, pull from its next blk memcpy(ptr, src, length); assert(from->next >= 0); //has a next blk from = block_ptr(rb , from->next); assert(from->offset == 0); //if offset not 0 ,means this blk has data to be handle ptr += length; //shift dest address size -= length; //re calculate size to copy length = from->length - sizeof(struct ringbuffer_block); //data length of blk src = (char *)(from + 1); } memcpy(ptr, src , size); //if data length is enough ,do copy to->id = from->id; //copy id return (char *)(to + 1); //return dest } assert(from->next >= 0); //if length is not enough to skip ,shift to next blk ,skip the left num from = block_ptr(rb, from->next); assert(from->offset == 0); skip -= length; //remaind skip length = from->length - sizeof(struct ringbuffer_block); //get a new length of a new blk ,restart } }
void * ringbuffer_copy(struct ringbuffer * rb, struct ringbuffer_block * from, int skip, struct ringbuffer_block * to) { int size = to->length - sizeof(struct ringbuffer_block); int length = from->length - sizeof(struct ringbuffer_block) - from->offset; char * ptr = (char *)(to+1); for (;;) { if (length > skip) { char * src = (char *)(from + 1); src += from->offset + skip; length -= skip; while (length < size) { memcpy(ptr, src, length); assert(from->next >= 0); from = block_ptr(rb , from->next); assert(from->offset == 0); ptr += length; size -= length; length = from->length - sizeof(struct ringbuffer_block); src = (char *)(from + 1); } memcpy(ptr, src , size); to->id = from->id; return (char *)(to + 1); } assert(from->next >= 0); from = block_ptr(rb, from->next); assert(from->offset == 0); skip -= length; length = from->length - sizeof(struct ringbuffer_block); } }
static void free_block(struct k_mem_pool *p, int level, size_t *lsizes, int bn) { int i, key, lsz = lsizes[level]; void *block = block_ptr(p, lsz, bn); key = irq_lock(); set_free_bit(p, level, bn); if (level && partner_bits(p, level, bn) == 0xf) { for (i = 0; i < 4; i++) { int b = (bn & ~3) + i; clear_free_bit(p, level, b); if (b != bn && block_fits(p, block_ptr(p, lsz, b), lsz)) { sys_dlist_remove(block_ptr(p, lsz, b)); } } irq_unlock(key); free_block(p, level-1, lsizes, bn / 4); /* tail recursion! */ return; } if (block_fits(p, block, lsz)) { sys_dlist_append(&p->levels[level].free_list, block); } irq_unlock(key); }
/** @fn RBUF_BLOCK *ringbuffer_alloc(RINGBUFFER * rb, int size) * @brief 在ringbuffer中开辟size大小的数据块 * @param rb 环形缓冲区指针. * @param size 需要开辟的数据块的大小 * @return 指向该数据块的指针 */ RBUF_BLOCK *ringbuffer_alloc(RINGBUFFER * rb, int size) { /*调整数据块大小4字节对齐*/ int align_length = ALIGN(sizeof(RBUF_BLOCK) + size); int i; /*循环2次实现一个环形的功能*/ for (i = 0;i < 2;i++) { int free_size = 0; RBUF_BLOCK * blk = block_ptr(rb, rb->head); do { // printf("blk->length:%d\n",blk->length); // printf("blk->offset:%d\n",blk->offset); /*如果当前blk还在使用则返回NULL表示没有剩余的空间可以分配*/ if ((blk->length >= sizeof(RBUF_BLOCK)) && (blk->id >= 0)) { return NULL; } /*回收碎片*/ free_size += ALIGN(blk->length); if (free_size >= align_length) { return _alloc(rb, free_size , size); } blk = block_next(rb, blk); } while(blk); /*如果后面没有足够的空间分配则从头分配*/ rb->head = 0; } return NULL; }
//ring buffer alloc struct ringbuffer_block * ringbuffer_alloc(struct ringbuffer * rb, int size) { //get align size needed int align_length = ALIGN(sizeof(struct ringbuffer_block) + size); int i; for (i=0;i<2;i++) { int free_size = 0; //find start pointer, from rb->head on struct ringbuffer_block * blk = block_ptr(rb, rb->head); //blk is next point of last blk //so blk is next space to use do { //轮转之前不会执行,只有轮转后后可能执行,轮转后遇到不可分配的,应该强行回收 if (blk->length >= sizeof(struct ringbuffer_block) && blk->id >= 0) //id >= 0 means mem in use return NULL; free_size += ALIGN(blk->length); if (free_size >= align_length) { return _alloc(rb, free_size , size); } blk = block_next(rb, blk); //find space available } while(blk); rb->head = 0; //roll back ,do again } return NULL; }
static struct ringbuffer_block * _alloc(struct ringbuffer * rb, int total_size , int size) { //get start point ,from rb->head on struct ringbuffer_block * blk = block_ptr(rb, rb->head); //get align length int align_length = ALIGN(sizeof(struct ringbuffer_block) + size); //set real length blk->length = sizeof(struct ringbuffer_block) + size; //blk real size ,no align blk->offset = 0; //set length with no align ,cause padding space no need to read blk->next = -1; blk->id = -1; //get next blk struct ringbuffer_block * next = block_next(rb, blk); if (next) { rb->head = block_offset(rb, next); //set head to offset(start) of next blk if (align_length < total_size) { next->length = total_size - align_length; //next blk is the remain space, set length of rest space if (next->length >= sizeof(struct ringbuffer_block)) { next->id = -1; //-1 means blk available } } } else { rb->head = 0; //if no next , means roll back ,head set to 0 } return blk; }
static void init_mem_pool(struct k_mem_pool *p) { int i; size_t buflen = p->n_max * p->max_sz, sz = p->max_sz; u32_t *bits = p->buf + buflen; sys_dlist_init(&p->wait_q); for (i = 0; i < p->n_levels; i++) { int nblocks = buflen / sz; sys_dlist_init(&p->levels[i].free_list); if (nblocks < 32) { p->max_inline_level = i; } else { p->levels[i].bits_p = bits; bits += (nblocks + 31)/32; } sz = _ALIGN4(sz / 4); } for (i = 0; i < p->n_max; i++) { void *block = block_ptr(p, p->max_sz, i); sys_dlist_append(&p->levels[0].free_list, block); set_free_bit(p, 0, i); } }
void ringbuffer_link(struct ringbuffer *rb , struct ringbuffer_block * head, struct ringbuffer_block * next) { while (head->next >=0) { head = block_ptr(rb, head->next); } next->id = head->id; head->next = block_offset(rb, next); }
struct ringbuffer * ringbuffer_new(int size) { struct ringbuffer * rb = malloc(sizeof(*rb) + size); rb->size = size; rb->head = 0; struct ringbuffer_block * blk = block_ptr(rb, 0); blk->length = size; blk->id = -1; return rb; }
/** @fn void ringbuffer_link(RINGBUFFER *rb , RBUF_BLOCK * head, RBUF_BLOCK * next) * @brief 将同一连接的数据块连接起来 * @param rb 环形缓冲区指针. * @param head 指向同一连接的一块数据块 * @param next 指向要连接的数据块 * @return N/A */ void ringbuffer_link(RINGBUFFER *rb , RBUF_BLOCK * head, RBUF_BLOCK * next) { /*指到同一连接的数据块的最尾*/ while (head->next >=0) { head = block_ptr(rb, head->next); } next->id = head->id; head->next = block_offset(rb, next); }
static inline struct ringbuffer_block * block_next(struct ringbuffer * rb, struct ringbuffer_block * blk) { int align_length = ALIGN(blk->length); int head = block_offset(rb, blk); if (align_length + head == rb->size) { return NULL; } assert(align_length + head < rb->size); return block_ptr(rb, head + align_length); }
void ringbuffer_link(struct ringbuffer *rb , struct ringbuffer_block * head, struct ringbuffer_block * next) { //head blk already have a next blk, shift to this "next blk" while (head->next >=0) { head = block_ptr(rb, head->next); } //set 2 block of same id next->id = head->id; //set blk1 -> next offset of blk2 head->next = block_offset(rb, next); }
static inline struct ringbuffer_block * block_next(struct ringbuffer * rb, struct ringbuffer_block * blk) { int align_length = ALIGN(blk->length); int head = block_offset(rb, blk); //head is result of last blk - (start+1),head is relative address of blk if (align_length + head == rb->size) { return NULL; } assert(align_length + head < rb->size); //have space to alloc return block_ptr(rb, head + align_length); //offset of last bulk + length of last bulk }
void ringbuffer_free(struct ringbuffer * rb, struct ringbuffer_block * blk) { if (blk == NULL) return; int id = _block_id(blk); blk->id = -1; while (blk->next >= 0) { blk = block_ptr(rb, blk->next); assert(_block_id(blk) == id); blk->id = -1; } }
int ringbuffer_collect(struct ringbuffer * rb) { int id = _last_id(rb); struct ringbuffer_block *blk = block_ptr(rb, 0); do { if (blk->length >= sizeof(struct ringbuffer_block) && blk->id == id) { blk->id = -1; } blk = block_next(rb, blk); } while(blk); return id; }
struct ringbuffer * ringbuffer_new(int size) { struct ringbuffer * rb = malloc(sizeof(*rb) + size); printf("size of init rb is %d \n", sizeof(*rb)); rb->size = size; rb->head = 0; struct ringbuffer_block * blk = block_ptr(rb, 0); //get address of memory blk->length = size; blk->id = -1; return rb; }
/** @fn int ringbuffer_collect(RINGBUFFER * rb) * @brief 收集最早分配的还在使用的同一id的数据块以便覆盖 * @param rb 环形缓冲区指针 * @return 返回该数据块id */ int ringbuffer_collect(RINGBUFFER * rb) { int id = _last_id(rb); RBUF_BLOCK *blk = block_ptr(rb, 0); do { if (blk->length >= sizeof(RBUF_BLOCK) && blk->id == id) { blk->id = -1; } blk = block_next(rb, blk); } while(blk); return id; }
/** @fn static inline RBUF_BLOCK *block_next(RINGBUFFER * rb, RBUF_BLOCK * blk) * @brief 指针指向下一个数据块 * @param rb 环形缓冲区指针. * @param blk 当前数据块指针. * @return 指向下一块数据块的指针 */ static inline RBUF_BLOCK *block_next(RINGBUFFER * rb, RBUF_BLOCK * blk) { /*分配的时候是按4字节对齐的。中间会有碎片*/ int align_length = ALIGN(blk->length); int head = block_offset(rb, blk); /*如果当前的blk已经在buffer的最尾,则表示没有下一块*/ if (align_length + head == rb->size) { return NULL; } /*如果当前分配的空间加上当前的位置大于ringbuffersize则段错误*/ assert(align_length + head < rb->size); return block_ptr(rb, head + align_length); }
static int _last_id(struct ringbuffer * rb) { int i; for (i=0;i<2;i++) { struct ringbuffer_block * blk = block_ptr(rb, rb->head); do { if (blk->length >= sizeof(struct ringbuffer_block) && blk->id >= 0) return blk->id; blk = block_next(rb, blk); } while(blk); rb->head = 0; } return -1; }
/** @fn RINGBUFFER *ringbuffer_new(int size) * @brief 创建一个ringbuffer * @param size ringbuffer的大小 * @return 指向ringbuffer的指针rb */ RINGBUFFER *ringbuffer_new(int size) { RINGBUFFER * rb = NULL; if(NULL == (rb = (RINGBUFFER *)malloc(sizeof(*rb) + size))) { perror("malloc"); } rb->size = size; rb->head = 0; RBUF_BLOCK * blk = block_ptr(rb, 0); blk->length = size; blk->id = -1; return rb; }
/** @fn void ringbuffer_free(RINGBUFFER * rb, RBUF_BLOCK * blk) * @brief 将已经断开连接的数据块id置-1 * @param rb 指向ringbuffer的指针 * @param blk 指向已断开连接的第一块数据块 * @return N/A */ void ringbuffer_free(RINGBUFFER * rb, RBUF_BLOCK * blk) { if (blk == NULL) { return; } int id = _block_id(blk); blk->id = -1; while (blk->next >= 0) { blk = block_ptr(rb, blk->next); assert(_block_id(blk) == id); blk->id = -1; } }
static struct ringbuffer_block * _alloc(struct ringbuffer * rb, int total_size , int size) { struct ringbuffer_block * blk = block_ptr(rb, rb->head); int align_length = ALIGN(sizeof(struct ringbuffer_block) + size); blk->length = sizeof(struct ringbuffer_block) + size; blk->offset = 0; blk->next = -1; blk->id = -1; struct ringbuffer_block * next = block_next(rb, blk); rb->head = block_offset(rb, next); if (align_length < total_size) { next->length = total_size - align_length; if (next->length >= sizeof(struct ringbuffer_block)) { next->id = -1; } } return blk; }
//get a blk needed ,with skip param struct ringbuffer_block * ringbuffer_yield(struct ringbuffer * rb, struct ringbuffer_block *blk, int skip) { int length = blk->length - sizeof(struct ringbuffer_block) - blk->offset; //-offset 意思是处理未处理的数据,offset是未处理的数据起始点 for (;;) { if (length > skip) { blk->offset += skip; //shift offset by skip ,skip means no need to process return blk; } blk->id = -1; if (blk->next < 0) { return NULL; } blk = block_ptr(rb, blk->next); assert(blk->offset == 0); skip -= length; //re calculate skip, skip is consumed partly by last blk length = blk->length - sizeof(struct ringbuffer_block); } }
struct ringbuffer_block * ringbuffer_yield(struct ringbuffer * rb, struct ringbuffer_block *blk, int skip) { int length = blk->length - sizeof(struct ringbuffer_block) - blk->offset; for (;;) { if (length > skip) { blk->offset += skip; return blk; } blk->id = -1; if (blk->next < 0) { return NULL; } blk = block_ptr(rb, blk->next); assert(blk->offset == 0); skip -= length; length = blk->length - sizeof(struct ringbuffer_block); } }
/** @fn static int _last_id(RINGBUFFER * rb) * @brief 寻找最早分配的还在使用的数据块id,以便收集覆盖 * @param rb 环形缓冲区指针. * @return 返回该数据块id */ static int _last_id(RINGBUFFER * rb) { int i; /*循环2次实现一个环形的功能*/ for (i = 0;i < 2;i++) { RBUF_BLOCK * blk = block_ptr(rb, rb->head); do { if ((blk->length >= sizeof(RBUF_BLOCK)) && (blk->id >= 0)) { return blk->id; } blk = block_next(rb, blk); } while(blk); rb->head = 0; } return -1; }
struct ringbuffer_block * ringbuffer_alloc(struct ringbuffer * rb, int size) { int align_length = ALIGN(sizeof(struct ringbuffer_block) + size); int i; for (i=0;i<2;i++) { int free_size = 0; struct ringbuffer_block * blk = block_ptr(rb, rb->head); do { if (blk->length >= sizeof(struct ringbuffer_block) && blk->id >= 0) return NULL; free_size += ALIGN(blk->length); if (free_size >= align_length) { return _alloc(rb, free_size , size); } blk = block_next(rb, blk); } while(blk); rb->head = 0; } return NULL; }
decompressor::block_ptr_t decompressor::read_block(size_t block_id) const { block_ptr_t cached_block_ptr = m_cache->get(block_id); if (cached_block_ptr) { return cached_block_ptr; } boost::shared_ptr<block_t> block_ptr(new block_t(block_id * block_size(), std::vector<char>())); // non-const ptr std::vector<char>& block = block_ptr->second; block.resize(m_block_size); z_stream strm; int ret; strm.zalloc = Z_NULL; strm.zfree = Z_NULL; strm.opaque = Z_NULL; ret = inflateInit2(&strm, window_size); assert(ret == Z_OK); size_t offset = m_offsets[block_id]; strm.avail_in = m_compressed_size - offset; strm.next_in = (unsigned char*)(m_compressed_data + offset); strm.avail_out = m_block_size; strm.next_out = (unsigned char*)&block[0]; ret = inflate(&strm, Z_BLOCK); assert(ret == Z_OK); block.resize(m_block_size - strm.avail_out); inflateEnd(&strm); #ifdef ZRANDOM_PROFILE ++m_reads; m_unique_reads.insert(block_id); #endif m_cache->put(block_id, block_ptr); return block_ptr; }
void ringbuffer_dump(struct ringbuffer * rb) { struct ringbuffer_block *blk = block_ptr(rb,0); int i=0; printf("total size= %d\n",rb->size); while (blk) { ++i; if (i>10) break; if (blk->length >= sizeof(*blk)) { printf("[%u : %d]", (unsigned)(blk->length - sizeof(*blk)), block_offset(rb,blk)); printf(" id=%d",blk->id); if (blk->id >=0) { printf(" offset=%d next=%d",blk->offset, blk->next); } } else { printf("<%u : %d>", blk->length, block_offset(rb,blk)); } printf("\n"); blk = block_next(rb, blk); } }