[MPlayer-users] lockless cache2 looks buggy
Denis Vlasenko
vda.linux at googlemail.com
Sun Aug 20 18:35:46 CEST 2006
Hello mplayer coders,
I was looking into cache2.c. It says that it is a lockless
cache implementation.
I see s few issues with the code. First issue is the most serious,
since it looks like real bug.
(1) Non-atomic updated of metadata.
Main thread reds cached data using cache_read(), which uses
off_t variables s->min_filepos, s->max_filepos etc.
They are 64-bit variables on most systems:
newb=s->max_filepos-s->read_filepos; // new bytes in the buffer
pos=s->read_filepos - s->offset;
if(pos<0) pos+=s->buffer_size; else
if(pos>=s->buffer_size) pos-=s->buffer_size;
if(newb>s->buffer_size-pos) newb=s->buffer_size-pos; // handle wrap...
if(newb>size) newb=size;
memcpy(buf,&s->buffer[pos],newb);
However, caching thread reads new data into circular buffer
and updates those same variables in cache_fill():
back2=s->buffer_size-(space+newb); // max back size
if(s->min_filepos<(read-back2)) s->min_filepos=read-back2;
len=stream_read(s->stream,&s->buffer[pos],space);
if(!len) s->eof=1;
s->max_filepos+=len;
if(pos+len>=s->buffer_size){
// wrap...
s->offset+=s->buffer_size;
}
These updates are not atomic on 32-bit architectures (i386).
Therefore caching thread can update lower half of a value, then it
may get rescheduled with CPU given to main thread, which then
will use bogus value of half-updated variable.
(2) fork() failure is not checked
if((stream->cache_pid=fork())){
The above if() thinks that non-zero return means that we are the parent.
However, -1 is possible too (fork() may fail).
(3) Suboptimal underrun handling.
Cache underrun handling looks suboptimal to me:
while(size>0){
int pos,newb,len;
if(s->read_filepos>=s->max_filepos || s->read_filepos<s->min_filepos){
// eof?
if(s->eof) break;
// waiting for buffer fill...
usec_sleep(READ_USLEEP_TIME); // 10ms
continue; // try again...
}
...
}
If you have an underrun, it is not that good an idea to sleep.
Isn't it better to just schedule (man sched_yield), giving
cache thread a chance to do its work? In the above code,
you can easily add 10 ms more latency for the already bad case
of cache underrun.
(4) Jumbledtogethercoditionalexpressions
while(s->read_filepos<s->min_filepos || s->max_filepos-s->read_filepos<min){
This code has readability problems. Do you hate whitespace? ;)
I am willing to work on this code if it is acceptable to start
with reformatting cache2.c into more readable form first.
Would such patch be accepted?
Best regards,
--
vda
More information about the MPlayer-users
mailing list