static void interval_tree_intersection_1(interval_tree tree, uint64_t start, uint64_t end, varray * dest) { interval_tree_node node; node = splay_tree_lookup(tree->splay, start); if (!node) { node = splay_tree_predecessor(tree->splay, start); if (!node || INTERVAL_END(node) <= start) node = splay_tree_successor(tree->splay, start); } if (!node) node = splay_tree_successor(tree->splay, start); for (; node && INTERVAL_START(node) < end; node = splay_tree_successor(tree->splay, INTERVAL_START(node))) { interval *x; VARRAY_EMPTY_PUSH(*dest); x = &VARRAY_TOP(*dest, interval); x->start = MAX(start, INTERVAL_START(node)); x->end = MIN(end, INTERVAL_END(node)); } }
static int interval_tree_add_1(splay_tree_node node, void *data) { interval_tree tree = (interval_tree) data; interval_tree_insert(tree, INTERVAL_START(node), INTERVAL_END(node)); return 0; }
static int mp3_write(struct file *file, const char *buf, size_t count, loff_t *ppos) { //static char tmp[E7B_MP3_MAX_INPUTSIZE]; static char tmp[3*1024]; int n = sizeof tmp; int ret; INTERVAL_START(timeWrite); if (n > count) n = count; // We should really redefine the lower level interface so that we // can avoid this copy. Rather than tmp we should go straight to // the epics. This is safe though for now. if (copy_from_user(tmp, buf, n)) ret = -EFAULT; else { TRACE(4, ">>MP3_WRITE n=%u\n", n); ret = mp3decInputData(tmp, n); TRACE(4, "<<MP3_WRITE ret=%u\n", ret); } INTERVAL_STOP(timeWrite); return ret; }
static void interval_tree_complement_1(interval_tree tree, uint64_t start, uint64_t end, varray * dest) { interval_tree_node node; uint64_t last; node = splay_tree_lookup(tree->splay, start); if (node) { last = INTERVAL_END(node); } else { node = splay_tree_predecessor(tree->splay, start); if (node && INTERVAL_END(node) > start) last = INTERVAL_END(node); else last = start; } node = splay_tree_successor(tree->splay, start); while (last < end) { interval *x; VARRAY_EMPTY_PUSH(*dest); x = &VARRAY_TOP(*dest, interval); x->start = last; if (node) { x->end = INTERVAL_START(node); last = INTERVAL_END(node); node = splay_tree_successor(tree->splay, INTERVAL_START(node)); } else { x->end = end; break; } } }
static int interval_tree_sub_1(splay_tree_node node, void *data) { interval_tree tree = (interval_tree) data; interval_tree_delete(tree, INTERVAL_START(node), INTERVAL_END(node)); /* Stop traversing when TREE is empty and thus no more intervals can be deleted. */ return tree->splay->root == NULL; }
/*! Print the interval in NODE to file DATA. */ static int print_interval_tree_node(splay_tree_node node, void *data) { FILE *f = (FILE *) data; fprintf(f, "["); fprintf(f, "%" PRIu64, INTERVAL_START(node)); fprintf(f, ","); fprintf(f, "%" PRIu64, INTERVAL_END(node)); fprintf(f, ")\n"); return 0; }
static bool interval_tree_write_1(interval_tree_node node, int fd, interval_tree_write_data * data) { bool r; /* Process left subtree. */ if (node->left) { r = interval_tree_write_1(node->left, fd, data); if (!r) return r; } /* Process current node. */ data->intervals[data->n].start = u64_to_le(INTERVAL_START(node)); data->intervals[data->n].end = u64_to_le(INTERVAL_END(node)); data->n++; if (data->n == INTERVAL_COUNT) { r = full_write(fd, data->intervals, INTERVAL_COUNT * sizeof(interval)); if (!r) return r; data->n = 0; } /* Process right subtree. */ if (node->right) { r = interval_tree_write_1(node->right, fd, data); if (!r) return r; } return true; }
interval_tree_node interval_tree_insert(interval_tree tree, uint64_t start, uint64_t end) { splay_tree_node node, prev, next; CHECK_MUTEX_LOCKED(tree->mutex); if ((node = splay_tree_lookup(tree->splay, start)) != NULL) { /* The START of interval is already in the tree. */ if (INTERVAL_END(node) >= end) { /* There already is a larger interval starting in START so we have nothing to do. */ return node; } INTERVAL_END(node) = end; } else { /* Lookup the predecessor and successor of key START. */ prev = splay_tree_predecessor(tree->splay, start); next = splay_tree_successor(tree->splay, start); if (prev && INTERVAL_END(prev) >= start) { /* We are extending PREV. */ node = prev; if (INTERVAL_END(node) < end) INTERVAL_END(node) = end; } else if (next && INTERVAL_START(next) <= end) { /* We are extending NEXT. */ node = next; if (INTERVAL_START(node) > start) INTERVAL_START(node) = start; if (INTERVAL_END(node) < end) INTERVAL_END(node) = end; } else { /* We are really inserting a new node. */ node = splay_tree_insert(tree->splay, start, end); tree->size++; } } /* Merge the successors if they are covered by [START, END). */ while ((next = splay_tree_successor(tree->splay, INTERVAL_START(node))) != NULL) { if (INTERVAL_START(next) <= INTERVAL_END(node)) { if (INTERVAL_END(node) < INTERVAL_END(next)) INTERVAL_END(node) = INTERVAL_END(next); splay_tree_delete(tree->splay, INTERVAL_START(next)); tree->size--; } else break; } return node; }
void interval_tree_delete(interval_tree tree, uint64_t start, uint64_t end) { splay_tree_node node, prev, next; CHECK_MUTEX_LOCKED(tree->mutex); if ((node = splay_tree_lookup(tree->splay, start)) != NULL) { tree->deleted = true; if (INTERVAL_END(node) > end) { /* We are shortening the interval NODE. */ INTERVAL_START(node) = end; return; } else { splay_tree_delete(tree->splay, start); tree->size--; } } else { prev = splay_tree_predecessor(tree->splay, start); if (prev && start < INTERVAL_END(prev)) { tree->deleted = true; if (INTERVAL_END(prev) > end) { /* We are cutting a subinterval from interval PREV. */ splay_tree_insert(tree->splay, end, INTERVAL_END(prev)); tree->size++; INTERVAL_END(prev) = start; return; } else { /* We are shortening the interval PREV. */ INTERVAL_END(prev) = start; } } } /* Delete rest intervals which intersect [START, END). */ while (1) { next = splay_tree_successor(tree->splay, start); if (!next || INTERVAL_START(next) >= end) break; tree->deleted = true; if (INTERVAL_END(next) <= end) { splay_tree_delete(tree->splay, INTERVAL_START(next)); tree->size--; } else { INTERVAL_START(next) = end; return; } } }
static int mp3_ioctl(struct inode *inode, struct file *fp, unsigned int command, unsigned long arg) { int retval = 0; TRACE(1, "%s\n", __FUNCTION__); switch (command) { case E7B_MP3_INIT: { int ret; TRACE(1, ">>E7B_MP3_INIT\n"); // Start of Stream /* fill references */ INTERVAL_START(timeInit); ret = mp3decInit(); INTERVAL_STOP(timeInit); if (ret < 0) return -EIO; } break; case E7B_MP3_DECODE: { int ret; e7b_mp3_decode dp; TRACE(1, ">>E7B_MP3_DECODE\n"); switch (mp3_driver_state) { case mp3_driver_idle: ret = mp3decDecode(); mp3_driver_state = mp3_driver_decoding; break; case mp3_driver_decoding: ret = mp3decContinue(); break; default: return -EIO; } dp.samplesReady = 0; dp.needInput = 0; dp.decReturn = 0; if (ret == 0) { mp3decDecodeFinish(&mp3_buff->out[0].hdr, &dp.samplesReady, mp3_buff->out[0].data, &dp.decReturn); if (dp.decReturn != 0) pnx0106_epics_printk("Decode returned 0x%x\n", dp.decReturn); mp3_driver_state = mp3_driver_idle; } else dp.needInput = 1; TRACE(3, "<<E7B_MP3_DECODE sReady=%u ret=%d\n", dp.samplesReady, ret); if (copy_to_user((void *)arg, &dp, sizeof(dp))) return -EFAULT; } break; case E7B_MP3_RESET: TRACE(1, ">>E7B_MP3_RESET\n"); INTERVAL_START(timeReset); wait_epics_idle(); mp3decReset(); INTERVAL_STOP(timeReset); break; case E7B_MP3_INPUT_EOF: mp3decInputEOF(); break; case E7B_MP3_STREAM: { int ret; u32 decReturn; TRACE(4, ">>E7B_MP3_STREAM\n"); switch (mp3_driver_state) { case mp3_driver_idle: ret = mp3decStreamStart(); mp3_driver_state = mp3_driver_streaming; break; case mp3_driver_streaming: ret = mp3decContinue(); break; default: return -EIO; } decReturn = 0; if (ret == 0) { mp3decStreamFinish(&decReturn); if (decReturn != 0) printk("Stream finish returned 0x%x\n", decReturn); mp3_driver_state = mp3_driver_idle; } if (copy_to_user((void *)arg, &decReturn, sizeof decReturn)) return -EFAULT; } break; case E7B_MP3_STREAM_RESUME: { int ret; TRACE(4, ">>E7B_MP3_STREAM_RESUME\n"); switch (mp3_driver_state) { case mp3_driver_idle: case mp3_driver_streaming: ret = mp3decStreamResume(); mp3_driver_state = mp3_driver_streaming; break; default: return -EIO; } } break; case E7B_MP3_STREAM_GETPCM: { e7b_mp3_decode sgp; INTERVAL_START(timeGetPCM); TRACE(4, ">>E7B_MP3_STREAM_GETPCM \n"); sgp.needInput = 0; sgp.decReturn = 0; mp3decStreamGetPCM( &mp3_buff->out[0].hdr, &sgp.samplesReady, mp3_buff->out[0].data, &sgp.decReturn); // ~ redundant with cSamplesRequested TRACE(4, "<<E7B_MP3_STREAM_GETPCM sRet=%u decReturn=%d\n", sgp.samplesReady, sgp.decReturn); if (copy_to_user((void *)arg, &sgp, sizeof(sgp))) retval = -EFAULT; INTERVAL_STOP(timeGetPCM); } break; } return retval; }