Commit ddce103b authored by Simon Evans's avatar Simon Evans Committed by Greg Kroah-Hartman

[PATCH] cleanup RingQueue_* functions in usbvideo.c

This patch against 2.5.31 cleans up the RingQueue_* functions

- make the buffer length be a power of 2 to speed up index manipulation
- make RingQueue_Dequeue use memcpy() rather than a byte by byte copy
- make RingQueue_Enqueue use memcpy() instead of memmove() as the memory
  regions do not overlap
- Add RingQueue_Flush() and RingQueue_GetFreeSpace()
- make RingQueue_GetLength() an inline
parent 5dfd412e
......@@ -135,9 +135,21 @@ static void RingQueue_Initialize(RingQueue_t *rq)
static void RingQueue_Allocate(RingQueue_t *rq, int rqLen)
{
/* Make sure the requested size is a power of 2 and
round up if necessary. This allows index wrapping
using masks rather than modulo */
int i = 1;
assert(rq != NULL);
assert(rqLen > 0);
while(rqLen >> i)
i++;
if(rqLen != 1 << (i-1))
rqLen = 1 << i;
rq->length = rqLen;
rq->ri = rq->wi = 0;
rq->queue = usbvideo_rvmalloc(rq->length);
assert(rq->queue != NULL);
}
......@@ -161,12 +173,32 @@ static void RingQueue_Free(RingQueue_t *rq)
int RingQueue_Dequeue(RingQueue_t *rq, unsigned char *dst, int len)
{
int i;
int rql, toread;
assert(rq != NULL);
assert(dst != NULL);
for (i=0; i < len; i++) {
dst[i] = rq->queue[rq->ri];
RING_QUEUE_DEQUEUE_BYTES(rq,1);
rql = RingQueue_GetLength(rq);
if(!rql)
return 0;
/* Clip requested length to available data */
if(len > rql)
len = rql;
toread = len;
if(rq->ri > rq->wi) {
/* Read data from tail */
int read = (toread < (rq->length - rq->ri)) ? toread : rq->length - rq->ri;
memcpy(dst, rq->queue + rq->ri, read);
toread -= read;
dst += read;
rq->ri = (rq->ri + read) & (rq->length-1);
}
if(toread) {
/* Read data from head */
memcpy(dst, rq->queue + rq->ri, toread);
rq->ri = (rq->ri + toread) & (rq->length-1);
}
return len;
}
......@@ -194,7 +226,7 @@ int RingQueue_Enqueue(RingQueue_t *rq, const unsigned char *cdata, int n)
if (m > q_avail)
m = q_avail;
memmove(rq->queue + rq->wi, cdata, m);
memcpy(rq->queue + rq->wi, cdata, m);
RING_QUEUE_ADVANCE_INDEX(rq, wi, m);
cdata += m;
enqueued += m;
......@@ -205,24 +237,6 @@ int RingQueue_Enqueue(RingQueue_t *rq, const unsigned char *cdata, int n)
EXPORT_SYMBOL(RingQueue_Enqueue);
int RingQueue_GetLength(const RingQueue_t *rq)
{
int ri, wi;
assert(rq != NULL);
ri = rq->ri;
wi = rq->wi;
if (ri == wi)
return 0;
else if (ri < wi)
return wi - ri;
else
return wi + (rq->length - ri);
}
EXPORT_SYMBOL(RingQueue_GetLength);
static void RingQueue_InterruptibleSleepOn(RingQueue_t *rq)
{
assert(rq != NULL);
......@@ -238,6 +252,16 @@ void RingQueue_WakeUpInterruptible(RingQueue_t *rq)
EXPORT_SYMBOL(RingQueue_WakeUpInterruptible);
void RingQueue_Flush(RingQueue_t *rq)
{
assert(rq != NULL);
rq->ri = 0;
rq->wi = 0;
}
EXPORT_SYMBOL(RingQueue_Flush);
/*
* usbvideo_VideosizeToString()
*
......@@ -374,7 +398,7 @@ static void usbvideo_OverlayStats(uvd_t *uvd, usbvideo_frame_t *frame)
q_used = RingQueue_GetLength(&uvd->dp);
if ((uvd->dp.ri + q_used) >= uvd->dp.length) {
u_hi = uvd->dp.length;
u_lo = (q_used + uvd->dp.ri) % uvd->dp.length;
u_lo = (q_used + uvd->dp.ri) & (uvd->dp.length-1);
} else {
u_hi = (q_used + uvd->dp.ri);
u_lo = -1;
......@@ -1256,7 +1280,7 @@ static int usbvideo_v4l_open(struct inode *inode, struct file *file)
/* Allocate memory for the frame buffers */
uvd->fbuf_size = USBVIDEO_NUMFRAMES * uvd->max_frame_size;
uvd->fbuf = usbvideo_rvmalloc(uvd->fbuf_size);
RingQueue_Allocate(&uvd->dp, 128*1024); /* FIXME #define */
RingQueue_Allocate(&uvd->dp, RING_QUEUE_SIZE);
if ((uvd->fbuf == NULL) ||
(!RingQueue_IsAllocated(&uvd->dp))) {
err("%s: Failed to allocate fbuf or dp", proc);
......
......@@ -113,9 +113,10 @@ typedef unsigned long videosize_t;
mr = LIMIT_RGB(mm_r); \
}
#define RING_QUEUE_ADVANCE_INDEX(rq,ind,n) (rq)->ind = ((rq)->ind + (n)) % (rq)->length
#define RING_QUEUE_SIZE (128*1024) /* Must be a power of 2 */
#define RING_QUEUE_ADVANCE_INDEX(rq,ind,n) (rq)->ind = ((rq)->ind + (n)) & ((rq)->length-1)
#define RING_QUEUE_DEQUEUE_BYTES(rq,n) RING_QUEUE_ADVANCE_INDEX(rq,ri,n)
#define RING_QUEUE_PEEK(rq,ofs) ((rq)->queue[((ofs) + (rq)->ri) % (rq)->length])
#define RING_QUEUE_PEEK(rq,ofs) ((rq)->queue[((ofs) + (rq)->ri) & ((rq)->length-1)])
typedef struct {
unsigned char *queue; /* Data from the Isoc data pump */
......@@ -306,8 +307,18 @@ typedef struct s_usbvideo_t usbvideo_t;
int RingQueue_Dequeue(RingQueue_t *rq, unsigned char *dst, int len);
int RingQueue_Enqueue(RingQueue_t *rq, const unsigned char *cdata, int n);
int RingQueue_GetLength(const RingQueue_t *rq);
void RingQueue_WakeUpInterruptible(RingQueue_t *rq);
void RingQueue_Flush(RingQueue_t *rq);
static inline int RingQueue_GetLength(const RingQueue_t *rq)
{
return (rq->wi - rq->ri + rq->length) & (rq->length-1);
}
static inline int RingQueue_GetFreeSpace(const RingQueue_t *rq)
{
return rq->length - RingQueue_GetLength(rq);
}
void usbvideo_DrawLine(
usbvideo_frame_t *frame,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment