void pb_flush (pb_t *pb) { pb_node_t *curr, *next, *stop; uint16_t i, n_iterators; pb_validate(pb); stop = pb->psentinel; curr = stop->next; /* next = head */ while(curr != stop) { next = curr->next; curr->next->prev = curr->prev; curr->prev->next = curr->next; pb->freeproc(&curr->data, curr->data_len); pb->n_nodes--; assert(curr->data == NULL); block_free(curr, sizeof(pb_node_t)); curr = next; } assert(stop->next == stop); assert(stop->prev == stop); assert(pb->n_nodes == 0); /* Reset all iterators */ n_iterators = pb->n_iterators; for(i = 0; i < n_iterators; i++) { pb->iterators[i].node = stop; } pb_validate(pb); }
void pb_shift_units_back_after(pb_t *pb, timestamp_t ref_ts, timestamp_t delta) { pb_node_t *stop, *curr; pb_validate(pb); stop = pb->psentinel; curr = pb->psentinel->prev; while(curr != stop && ts_gt(curr->playout, ref_ts)) { curr->playout = ts_add(curr->playout, delta); curr = curr->prev; } pb_validate(pb); }
void pb_shift_forward(pb_t *pb, timestamp_t delta) { pb_node_t *stop, *curr; pb_validate(pb); stop = pb->psentinel; curr = pb->psentinel->next; while(curr != stop) { curr->playout = ts_sub(curr->playout, delta); curr = curr->next; } pb_validate(pb); }
int pb_iterator_detach_at (pb_iterator_t *pi, u_char **data, uint32_t *data_len, timestamp_t *playout) { pb_iterator_t *iterators; pb_node_t *curr_node, *next_node; uint16_t i, n_iterators; pb_validate(pi->buffer); if (pb_iterator_get_at(pi, data, data_len, playout) == FALSE) { /* There is no data to get */ return FALSE; } /* Check we are not attempting to remove * data that another iterator is pointing to */ iterators = &pi->buffer->iterators[0]; n_iterators = pi->buffer->n_iterators; for(i = 0; i < n_iterators; i++) { if (iterators[i].node == pi->node && iterators + i != pi) { debug_msg("Eek removing node that another iterator is using...danger!\n"); iterators[i].node = iterators[i].node->prev; } } /* Relink list of nodes */ curr_node = pi->node; next_node = curr_node->next; curr_node->next->prev = curr_node->prev; curr_node->prev->next = curr_node->next; #ifdef DEBUG curr_node->next = NULL; curr_node->prev = NULL; curr_node->magic = 0; curr_node->data = NULL; curr_node->data_len = 0; #endif block_free(curr_node, sizeof(pb_node_t)); pi->node = next_node; pi->buffer->n_nodes--; pb_validate(pi->buffer); return TRUE; }
int pb_iterator_get_at(pb_iterator_t *pi, u_char **data, uint32_t *data_len, timestamp_t *playout) { pb_node_t *sentinel = pi->buffer->psentinel; /* This can be rewritten in fewer lines, but the obvious way is not as efficient. */ pb_validate(pi->buffer); if (pi->node != sentinel) { *data = pi->node->data; *data_len = pi->node->data_len; *playout = pi->node->playout; return TRUE; } else { /* We are at the start of the list so maybe we haven't tried reading before */ pi->node = sentinel->next; if (pi->node != sentinel) { *data = pi->node->data; *data_len = pi->node->data_len; *playout = pi->node->playout; return TRUE; } } /* There is data on the list */ *data = NULL; *data_len = 0; memset(playout, 0, sizeof(timestamp_t)); return FALSE; }
static enum pipe_error pb_cache_buffer_validate(struct pb_buffer *_buf, struct pb_validate *vl, unsigned flags) { struct pb_cache_buffer *buf = pb_cache_buffer(_buf); return pb_validate(buf->buffer, vl, flags); }
enum pipe_error pb_validate_validate(struct pb_validate *vl) { unsigned i; for(i = 0; i < vl->used; ++i) { enum pipe_error ret; ret = pb_validate(vl->entries[i].buf, vl, vl->entries[i].flags); if(ret != PIPE_OK) { while(i--) pb_validate(vl->entries[i].buf, NULL, 0); return ret; } } return PIPE_OK; }
static enum pipe_error mm_buffer_validate(struct pb_buffer *buf, struct pb_validate *vl, unsigned flags) { struct mm_buffer *mm_buf = mm_buffer(buf); struct mm_pb_manager *mm = mm_buf->mgr; return pb_validate(mm->buffer, vl, flags); }
static enum pipe_error pool_buffer_validate(struct pb_buffer *buf, struct pb_validate *vl, unsigned flags) { struct pool_buffer *pool_buf = pool_buffer(buf); struct pool_pb_manager *pool = pool_buf->mgr; return pb_validate(pool->buffer, vl, flags); }
int pb_iterators_equal(pb_iterator_t *pi1, pb_iterator_t *pi2) { assert(pi1 != NULL); assert(pi2 != NULL); pb_validate(pi1->buffer); pb_validate(pi2->buffer); /* Move nodes off of sentinel if necessary and possible */ if (pi1->node == pi1->buffer->psentinel) { pi1->node = pi1->buffer->psentinel->next; /* yuk */ } if (pi2->node == pi2->buffer->psentinel) { pi2->node = pi2->buffer->psentinel->next; /* yuk */ } return (pi1->node == pi2->node); }
int pb_iterator_dup(pb_iterator_t **pb_dst, pb_iterator_t *pb_src) { pb_validate(pb_src->buffer); if (pb_iterator_create(pb_src->buffer, pb_dst)) { (*pb_dst)->node = pb_src->node; return TRUE; } return FALSE; }
int pb_iterator_get_ts(pb_iterator_t *pbi, timestamp_t *ts) { pb_validate(pbi->buffer); assert(ts); if (pbi->node != pbi->buffer->psentinel) { *ts = pbi->node->playout; return TRUE; } return FALSE; }
int pb_iterator_rwd(pb_iterator_t *pi) { pb_node_t *sentinel = pi->buffer->psentinel; pb_validate(pi->buffer); if (sentinel->next != sentinel) { pi->node = sentinel->next; return TRUE; } return FALSE; }
int pb_get_end_ts(pb_t *pb, timestamp_t *ts) { pb_validate(pb); assert(ts); if (pb->sentinel.prev != pb->psentinel) { *ts = pb->sentinel.prev->playout; return TRUE; } return FALSE; }
int pb_iterator_retreat(pb_iterator_t *pi) { pb_node_t *sentinel = pi->buffer->psentinel; pb_validate(pi->buffer); if (pi->node->prev != sentinel) { pi->node = pi->node->prev; return TRUE; } return FALSE; }
int pb_add (pb_t *pb, u_char *data, uint32_t data_len, timestamp_t playout) { pb_node_t *curr, *stop, *made; assert(data != NULL); assert(data_len > 0); pb_validate(pb); /* Assuming that addition will be at the end of list (or near it) */ stop = pb->psentinel; curr = stop->prev; /* list tail */ while (curr != stop && ts_gt(curr->playout, playout)) { curr = curr->prev; } /* Check if unit already exists */ if (curr != stop && ts_eq(curr->playout, playout)) { debug_msg("Add failed - unit already exists\n"); return FALSE; } made = (pb_node_t*)block_alloc(sizeof(pb_node_t)); if (made) { made->playout = playout; made->data = data; made->data_len = data_len; made->prev = curr; made->next = curr->next; made->next->prev = made; made->prev->next = made; made->magic = PB_NODE_MAGIC; pb->n_nodes++; pb_validate(pb); return TRUE; } debug_msg("Insufficient memory\n"); return FALSE; }
int pb_iterator_ffwd(pb_iterator_t *pi) { pb_node_t *sentinel = pi->buffer->psentinel; pb_validate(pi->buffer); /* Sentinel prev is tail of buffer */ if (sentinel->prev != sentinel) { pi->node = sentinel->prev; return TRUE; } return FALSE; }
int pb_iterator_create(pb_t *pb, pb_iterator_t **ppi) { pb_iterator_t *pi; if (pb->n_iterators == PB_MAX_ITERATORS) { debug_msg("Too many iterators\n"); *ppi = NULL; return FALSE; } pb_validate(pb); /* Link the playout buffer to the iterator */ pi = &pb->iterators[pb->n_iterators]; pb->n_iterators++; /* Set up node and buffer references */ pi->node = &pb->sentinel; pi->buffer = pb; *ppi = pi; pb_validate(pi->buffer); return TRUE; }
static enum pipe_error fenced_buffer_validate(struct pb_buffer *buf, struct pb_validate *vl, unsigned flags) { struct fenced_buffer *fenced_buf = fenced_buffer(buf); struct fenced_manager *fenced_mgr = fenced_buf->mgr; enum pipe_error ret; pipe_mutex_lock(fenced_mgr->mutex); if(!vl) { /* invalidate */ fenced_buf->vl = NULL; fenced_buf->validation_flags = 0; ret = PIPE_OK; goto done; } assert(flags & PB_USAGE_GPU_READ_WRITE); assert(!(flags & ~PB_USAGE_GPU_READ_WRITE)); flags &= PB_USAGE_GPU_READ_WRITE; /* Buffer cannot be validated in two different lists */ if(fenced_buf->vl && fenced_buf->vl != vl) { ret = PIPE_ERROR_RETRY; goto done; } if(fenced_buf->vl == vl && (fenced_buf->validation_flags & flags) == flags) { /* Nothing to do -- buffer already validated */ ret = PIPE_OK; goto done; } ret = pb_validate(fenced_buf->buffer, vl, flags); if (ret != PIPE_OK) goto done; fenced_buf->vl = vl; fenced_buf->validation_flags |= flags; done: pipe_mutex_unlock(fenced_mgr->mutex); return ret; }
static enum pipe_error pb_ondemand_buffer_validate(struct pb_buffer *_buf, struct pb_validate *vl, unsigned flags) { struct pb_ondemand_buffer *buf = pb_ondemand_buffer(_buf); enum pipe_error ret; assert(!buf->mapcount); if(buf->mapcount) return PIPE_ERROR; ret = pb_ondemand_buffer_instantiate(buf); if(ret != PIPE_OK) return ret; return pb_validate(buf->buffer, vl, flags); }
int pb_iterator_audit(pb_iterator_t *pi, timestamp_t history_len) { timestamp_t cutoff; int removed; pb_node_t *stop, *curr, *next; pb_t *pb; #ifdef DEBUG /* If we are debugging we check we are not deleting * nodes pointed to by other iterators since this *BAD* */ uint16_t i, n_iterators; pb_iterator_t *iterators = pi->buffer->iterators; n_iterators = pi->buffer->n_iterators; #endif pb_validate(pi->buffer); pb = pi->buffer; stop = pi->node; removed = 0; if (pi->node != pb->psentinel) { curr = pb->psentinel->next; /* head */; cutoff = ts_sub(pi->node->playout, history_len); while(ts_gt(cutoff, curr->playout)) { /* About to erase a block an iterator is using! */ #ifdef DEBUG for(i = 0; i < n_iterators; i++) { assert(iterators[i].node != curr); } #endif next = curr->next; curr->next->prev = curr->prev; curr->prev->next = curr->next; pb->freeproc(&curr->data, curr->data_len); pb->n_nodes--; block_free(curr, sizeof(pb_node_t)); curr = next; removed ++; } } return removed; }
static enum pipe_error pb_debug_buffer_validate(struct pb_buffer *_buf, struct pb_validate *vl, unsigned flags) { struct pb_debug_buffer *buf = pb_debug_buffer(_buf); pipe_mutex_lock(buf->mutex); if(buf->map_count) { debug_printf("%s: attempting to validate a mapped buffer\n", __FUNCTION__); debug_printf("last map backtrace is\n"); debug_backtrace_dump(buf->map_backtrace, PB_DEBUG_MAP_BACKTRACE); } pipe_mutex_unlock(buf->mutex); pb_debug_buffer_check(buf); return pb_validate(buf->buffer, vl, flags); }
int pb_create(pb_t **ppb, void (*datafreeproc)(u_char **data, uint32_t data_len)) { pb_t *pb; assert(datafreeproc != NULL); pb = (pb_t*)xmalloc(sizeof(pb_t)); if (pb != NULL) { memset(pb, 0, sizeof(pb_t)); *ppb = pb; pb->sentinel.next = pb->sentinel.prev = &pb->sentinel; pb->psentinel = &pb->sentinel; pb->freeproc = datafreeproc; pb->magic = PB_MAGIC; pb_validate(pb); return TRUE; } return FALSE; }
int pb_destroy (pb_t **ppb) { pb_t *pb = *ppb; pb_validate(pb); pb_flush(pb); #ifdef DEBUG if (pb->n_iterators != 0) { debug_msg("Iterators dangling from buffer. Release first.\n"); abort(); } #endif assert(pb->n_iterators == 0); xfree(pb); *ppb = NULL; return TRUE; }
void pb_iterator_destroy(pb_t *pb, pb_iterator_t **ppi) { uint16_t i, j; pb_iterator_t *pi; pb_validate(pb); pi = *ppi; assert(pi->buffer == pb); /* Remove iterator from buffer's list of iterators and * compress list in one pass */ for(j = 0, i = 0; j < pb->n_iterators; i++,j++) { if (&pb->iterators[i] == pi) { j++; } pb->iterators[i] = pb->iterators[j]; } pb->n_iterators--; /* Empty pointer */ *ppi = NULL; }
int pb_is_empty(pb_t *pb) { pb_validate(pb); return (pb->psentinel->next == pb->psentinel); }
uint32_t pb_node_count(pb_t *pb) { pb_validate(pb); return pb->n_nodes; }
static enum pipe_error fenced_buffer_validate(struct pb_buffer *buf, struct pb_validate *vl, unsigned flags) { struct fenced_buffer *fenced_buf = fenced_buffer(buf); struct fenced_manager *fenced_mgr = fenced_buf->mgr; enum pipe_error ret; pipe_mutex_lock(fenced_mgr->mutex); if(!vl) { /* invalidate */ fenced_buf->vl = NULL; fenced_buf->validation_flags = 0; ret = PIPE_OK; goto done; } assert(flags & PIPE_BUFFER_USAGE_GPU_READ_WRITE); assert(!(flags & ~PIPE_BUFFER_USAGE_GPU_READ_WRITE)); flags &= PIPE_BUFFER_USAGE_GPU_READ_WRITE; /* Buffer cannot be validated in two different lists */ if(fenced_buf->vl && fenced_buf->vl != vl) { ret = PIPE_ERROR_RETRY; goto done; } if(fenced_buf->vl == vl && (fenced_buf->validation_flags & flags) == flags) { /* Nothing to do -- buffer already validated */ ret = PIPE_OK; goto done; } /* * Create and update GPU storage. */ if(!fenced_buf->buffer) { assert(!fenced_buf->mapcount); ret = fenced_buffer_create_gpu_storage_locked(fenced_mgr, fenced_buf, TRUE); if(ret != PIPE_OK) { goto done; } ret = fenced_buffer_copy_storage_to_gpu_locked(fenced_buf); if(ret != PIPE_OK) { fenced_buffer_destroy_gpu_storage_locked(fenced_buf); goto done; } if(fenced_buf->mapcount) { debug_printf("warning: validating a buffer while it is still mapped\n"); } else { fenced_buffer_destroy_cpu_storage_locked(fenced_buf); } } ret = pb_validate(fenced_buf->buffer, vl, flags); if (ret != PIPE_OK) goto done; fenced_buf->vl = vl; fenced_buf->validation_flags |= flags; done: pipe_mutex_unlock(fenced_mgr->mutex); return ret; }