On Thu, 2003-04-03 at 21:14, rm wrote: > below is what i use (i think it works). the primary thing to notice > is that readers and writers are kept in line by the atomicity of > integer assignment (though in general, we should probably declare them > atomic_t or something).
Attached is the fifo I've had banging about. It uses atomic_t. -- Bob Ham <[EMAIL PROTECTED]>
/*
* Lock free FIFO
*
* Copyright (C) Robert Ham 2002, 2003 ([EMAIL PROTECTED])
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <stdlib.h>
#include <string.h>
#include "lff.h"
void
lff_init (lff_t * lff, unsigned int size, size_t object_size)
{
// this is +1 becase we need to have an empty element when the buffer is
// full otherwise there's no way to know if it's full or empty
lff->size = size + 1;
lff->object_size = object_size;
lff->data = malloc (object_size * lff->size);
atomic_set (&lff->read_index, 0);
atomic_set (&lff->write_index, 0);
}
void
lff_free (lff_t * lff)
{
free (lff->data);
}
lff_t *
lff_new (unsigned int size, size_t object_size)
{
lff_t * lff;
lff = malloc (sizeof (lff_t));
lff_init (lff, size, object_size);
return lff;
}
void
lff_destroy (lff_t * lff)
{
lff_free (lff);
free (lff);
}
/** read an element from the fifo into data.
returns 0 on success, non-zero if there were no elements to read */
int
lff_read (lff_t * lff, void * data)
{
if (atomic_read (&lff->read_index) == atomic_read (&lff->write_index))
return -1;
else
{
memcpy (data,
((char *)lff->data) + (atomic_read (&lff->read_index) * lff->object_size),
lff->object_size);
atomic_inc (&lff->read_index);
if (atomic_read (&lff->read_index) >= lff->size)
atomic_set (&lff->read_index, 0);
return 0;
}
}
/** write an element from data to the fifo.
returns 0 on success, non-zero if there was no space */
int
lff_write (lff_t * lff, const void * data)
{
int read_index;
/* got to read read_index only once for safety */
read_index = atomic_read (&lff->read_index);
/* lots of logic for when we're allowed to write to the fifo which basically
boils down to "don't write if we're one element behind the read index" */
if ((read_index > atomic_read (&lff->write_index) && read_index - atomic_read (&lff->write_index) > 1) ||
(atomic_read (&lff->write_index) >= read_index && atomic_read (&lff->write_index) != lff->size - 1) ||
(atomic_read (&lff->write_index) >= read_index && atomic_read (&lff->write_index) == lff->size - 1 && read_index != 0))
{
memcpy (((char *)lff->data) + (atomic_read (&lff->write_index) * lff->object_size),
data,
lff->object_size);
atomic_inc (&lff->write_index);
if (atomic_read (&lff->write_index) >= lff->size)
atomic_set (&lff->write_index, -1);
}
else
return -1;
return 0;
}
/* EOF */
/*
* Lock free FIFO
*
* Copyright (C) Robert Ham 2002, 2003 ([EMAIL PROTECTED])
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef __LOCK_FREE_FIFO_H__
#define __LOCK_FREE_FIFO_H__
#include <asm/atomic.h>
typedef struct _lff lff_t;
/** lock free fifo ring buffer structure */
struct _lff {
/** Size of the ringbuffer (in elements) */
unsigned int size;
/** the memory containing the ringbuffer */
void * data;
/** the size of an element */
size_t object_size;
/** the current position of the reader */
atomic_t read_index;
/** the current position of the writer */
atomic_t write_index;
};
void lff_init (lff_t * lff, unsigned int size, size_t object_size);
void lff_free (lff_t * lff);
lff_t * lff_new (unsigned int size, size_t object_size);
void lff_destroy (lff_t * lock_free_fifo);
int lff_read (lff_t * lock_free_fifo, void * data);
int lff_write (lff_t * lock_free_fifo, const void * data);
#endif /* __LOCK_FREE_FIFO_H__ */
signature.asc
Description: This is a digitally signed message part
