Home | History | Annotate | Download | only in fio
      1 /*
      2  * A simple kernel FIFO implementation.
      3  *
      4  * Copyright (C) 2004 Stelian Pop <stelian (at) popies.net>
      5  *
      6  * This program is free software; you can redistribute it and/or modify
      7  * it under the terms of the GNU General Public License as published by
      8  * the Free Software Foundation; either version 2 of the License, or
      9  * (at your option) any later version.
     10  *
     11  * This program is distributed in the hope that it will be useful,
     12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     14  * GNU General Public License for more details.
     15  *
     16  * You should have received a copy of the GNU General Public License
     17  * along with this program; if not, write to the Free Software
     18  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
     19  *
     20  */
     21 
     22 #include <stdio.h>
     23 #include <stdlib.h>
     24 #include <string.h>
     25 
     26 #include "fifo.h"
     27 
     28 struct fifo *fifo_alloc(unsigned int size)
     29 {
     30 	struct fifo *fifo;
     31 
     32 	fifo = malloc(sizeof(struct fifo));
     33 	if (!fifo)
     34 		return NULL;
     35 
     36 	fifo->buffer = malloc(size);
     37 	fifo->size = size;
     38 	fifo->in = fifo->out = 0;
     39 
     40 	return fifo;
     41 }
     42 
     43 void fifo_free(struct fifo *fifo)
     44 {
     45 	free(fifo->buffer);
     46 	free(fifo);
     47 }
     48 
     49 unsigned int fifo_put(struct fifo *fifo, void *buffer, unsigned int len)
     50 {
     51 	unsigned int l;
     52 
     53 	len = min(len, fifo_room(fifo));
     54 
     55 	/* first put the data starting from fifo->in to buffer end */
     56 	l = min(len, fifo->size - (fifo->in & (fifo->size - 1)));
     57 	memcpy(fifo->buffer + (fifo->in & (fifo->size - 1)), buffer, l);
     58 
     59 	/* then put the rest (if any) at the beginning of the buffer */
     60 	memcpy(fifo->buffer, buffer + l, len - l);
     61 
     62 	/*
     63 	 * Ensure that we add the bytes to the fifo -before-
     64 	 * we update the fifo->in index.
     65 	 */
     66 
     67 	fifo->in += len;
     68 
     69 	return len;
     70 }
     71 
     72 unsigned int fifo_get(struct fifo *fifo, void *buf, unsigned int len)
     73 {
     74 	len = min(len, fifo->in - fifo->out);
     75 
     76 	if (buf) {
     77 		unsigned int l;
     78 
     79 		/*
     80 		 * first get the data from fifo->out until the end of the buffer
     81 		 */
     82 		l = min(len, fifo->size - (fifo->out & (fifo->size - 1)));
     83 		memcpy(buf, fifo->buffer + (fifo->out & (fifo->size - 1)), l);
     84 
     85 		/*
     86 		 * then get the rest (if any) from the beginning of the buffer
     87 		 */
     88 		memcpy(buf + l, fifo->buffer, len - l);
     89 	}
     90 
     91 	fifo->out += len;
     92 
     93 	if (fifo->in == fifo->out)
     94 		fifo->in = fifo->out = 0;
     95 
     96 	return len;
     97 }
     98