John
8/7/2004 12:26:00 AM
Hi. I've been fighting with the following bit of code for quite a while
now. It is part of a multithreaded ringbuffer module, and I'm getting
unpredictable values when the test driver runs against this module, so there
must be an error here in my logic. Hopefully it's something glaringly
obvious, but that i'm not seeing cuz i'm burned out =)
All the error checking for malloc and semaphore operations are taking place,
though it is not shown below. Some code (which I believe is unrelated to
the problem) is left out for brevity's sake. If needed, I can post the
whole source somewhere. Also forgive the lousy formatting... Outlook
Express isn't a friend of mine.
Thanks in advance for any and all help in this matter!
----------------------------------
int readyToPut( ringbuf_t* );
int readyToGet( ringbuf_t* );
ringbuf_t*
ringbuf_alloc( int num_elements ){
DEBUG("In ringbuf_alloc\n");
/* make a new ringbuf_t and malloc room for it */
ringbuf_t *ringbuf;
ringbuf = Malloc( sizeof(ringbuf_t) );
/* malloc enough to hold num_elements of value_type */
value_type *bufspace;
bufspace = Malloc( num_elements * sizeof( value_type ) );
/* init a mutex that will protect access to the buffah
and notEmpty / notFull condition variables */
Sem_init( &ringbuf->notEmpty, 0, 0 );
Sem_init( &ringbuf->notFull, 0, 1 );
Sem_init( &ringbuf->mutex, 0, 1 );
return( ringbuf );
}
void
ringbuf_put( ringbuf_t *ringbuf,value_type val ){
while( !readyToPut( ringbuf ) )
Sem_wait( &ringbuf->notFull );
Sem_wait( &ringbuf->mutex );
DEBUG("\n:::: putting %d in %d\n",val,ringbuf->putspot);
ringbuf->buffer[ ringbuf->putspot ] = val;
ringbuf->putspot = ( ringbuf->putspot +1 ) % ringbuf->maxSize;
DEBUG(":::: next putspot %d\n\n",ringbuf->putspot );
ringbuf->itemCount++;
Sem_post( &ringbuf->mutex );
Sem_post( &ringbuf->notEmpty );
}
value_type
ringbuf_get( ringbuf_t *ringbuf ){
while( !readyToGet( ringbuf ) )
Sem_wait( &ringbuf->notEmpty );
Sem_wait( &ringbuf->mutex );
DEBUG("IN ringbuf_get\n");
value_type val = ringbuf->buffer[ ringbuf->nextGet ];
ringbuf->nextGet = (ringbuf->nextGet +1) % ringbuf->maxSize;
ringbuf->itemCount--;
Sem_post( &ringbuf->mutex );
Sem_post( &ringbuf->notFull );
return( val );
}
void
ringbuf_dealloc( ringbuf_t *ringbuf ){
/* free the buffer space and the mutex */
Sem_destroy( &ringbuf->notEmpty );
Sem_destroy( &ringbuf->notFull );
Sem_destroy( &ringbuf->mutex );
free( ringbuf->buffer );
free( ringbuf );
}
int
readyToPut( ringbuf_t *ringbuf ){
/* Is the buffer _not_ full? Then we can put */
return( ringbuf->itemCount != ringbuf->maxSize );
}
int
readyToGet( ringbuf_t *ringbuf ){
/* Is the buffer _not_empty? Then we can get */
return( ringbuf->itemCount != 0 );
}