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) ...@@ -135,9 +135,21 @@ static void RingQueue_Initialize(RingQueue_t *rq)
static void RingQueue_Allocate(RingQueue_t *rq, int rqLen) 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(rq != NULL);
assert(rqLen > 0); assert(rqLen > 0);
while(rqLen >> i)
i++;
if(rqLen != 1 << (i-1))
rqLen = 1 << i;
rq->length = rqLen; rq->length = rqLen;
rq->ri = rq->wi = 0;
rq->queue = usbvideo_rvmalloc(rq->length); rq->queue = usbvideo_rvmalloc(rq->length);
assert(rq->queue != NULL); assert(rq->queue != NULL);
} }
...@@ -161,12 +173,32 @@ static void RingQueue_Free(RingQueue_t *rq) ...@@ -161,12 +173,32 @@ static void RingQueue_Free(RingQueue_t *rq)
int RingQueue_Dequeue(RingQueue_t *rq, unsigned char *dst, int len) int RingQueue_Dequeue(RingQueue_t *rq, unsigned char *dst, int len)
{ {
int i; int rql, toread;
assert(rq != NULL); assert(rq != NULL);
assert(dst != NULL); assert(dst != NULL);
for (i=0; i < len; i++) {
dst[i] = rq->queue[rq->ri]; rql = RingQueue_GetLength(rq);
RING_QUEUE_DEQUEUE_BYTES(rq,1); 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; return len;
} }
...@@ -194,7 +226,7 @@ int RingQueue_Enqueue(RingQueue_t *rq, const unsigned char *cdata, int n) ...@@ -194,7 +226,7 @@ int RingQueue_Enqueue(RingQueue_t *rq, const unsigned char *cdata, int n)
if (m > q_avail) if (m > q_avail)
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); RING_QUEUE_ADVANCE_INDEX(rq, wi, m);
cdata += m; cdata += m;
enqueued += m; enqueued += m;
...@@ -205,24 +237,6 @@ int RingQueue_Enqueue(RingQueue_t *rq, const unsigned char *cdata, int n) ...@@ -205,24 +237,6 @@ int RingQueue_Enqueue(RingQueue_t *rq, const unsigned char *cdata, int n)
EXPORT_SYMBOL(RingQueue_Enqueue); 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) static void RingQueue_InterruptibleSleepOn(RingQueue_t *rq)
{ {
assert(rq != NULL); assert(rq != NULL);
...@@ -238,6 +252,16 @@ void RingQueue_WakeUpInterruptible(RingQueue_t *rq) ...@@ -238,6 +252,16 @@ void RingQueue_WakeUpInterruptible(RingQueue_t *rq)
EXPORT_SYMBOL(RingQueue_WakeUpInterruptible); 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() * usbvideo_VideosizeToString()
* *
...@@ -374,7 +398,7 @@ static void usbvideo_OverlayStats(uvd_t *uvd, usbvideo_frame_t *frame) ...@@ -374,7 +398,7 @@ static void usbvideo_OverlayStats(uvd_t *uvd, usbvideo_frame_t *frame)
q_used = RingQueue_GetLength(&uvd->dp); q_used = RingQueue_GetLength(&uvd->dp);
if ((uvd->dp.ri + q_used) >= uvd->dp.length) { if ((uvd->dp.ri + q_used) >= uvd->dp.length) {
u_hi = 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 { } else {
u_hi = (q_used + uvd->dp.ri); u_hi = (q_used + uvd->dp.ri);
u_lo = -1; u_lo = -1;
...@@ -1256,7 +1280,7 @@ static int usbvideo_v4l_open(struct inode *inode, struct file *file) ...@@ -1256,7 +1280,7 @@ static int usbvideo_v4l_open(struct inode *inode, struct file *file)
/* Allocate memory for the frame buffers */ /* Allocate memory for the frame buffers */
uvd->fbuf_size = USBVIDEO_NUMFRAMES * uvd->max_frame_size; uvd->fbuf_size = USBVIDEO_NUMFRAMES * uvd->max_frame_size;
uvd->fbuf = usbvideo_rvmalloc(uvd->fbuf_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) || if ((uvd->fbuf == NULL) ||
(!RingQueue_IsAllocated(&uvd->dp))) { (!RingQueue_IsAllocated(&uvd->dp))) {
err("%s: Failed to allocate fbuf or dp", proc); err("%s: Failed to allocate fbuf or dp", proc);
......
...@@ -113,9 +113,10 @@ typedef unsigned long videosize_t; ...@@ -113,9 +113,10 @@ typedef unsigned long videosize_t;
mr = LIMIT_RGB(mm_r); \ 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_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 { typedef struct {
unsigned char *queue; /* Data from the Isoc data pump */ unsigned char *queue; /* Data from the Isoc data pump */
...@@ -306,8 +307,18 @@ typedef struct s_usbvideo_t usbvideo_t; ...@@ -306,8 +307,18 @@ typedef struct s_usbvideo_t usbvideo_t;
int RingQueue_Dequeue(RingQueue_t *rq, unsigned char *dst, int len); 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_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_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( void usbvideo_DrawLine(
usbvideo_frame_t *frame, 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