source: lib/fifo.c @ 063c879

4.0.1-hotfixescachetimestampsdevelopdpdk-ndagetsilivegetfragoffhelplibtrace4ndag_formatpfringrc-4.0.1rc-4.0.2rc-4.0.3rc-4.0.4ringdecrementfixringperformanceringtimestampfixes
Last change on this file since 063c879 was b1a0f24, checked in by Daniel Lawson <dlawson@…>, 17 years ago

fixes for types.h

  • Property mode set to 100644
File size: 8.8 KB
Line 
1/*
2 * This file is part of libtrace
3 *
4 * Copyright (c) 2004 The University of Waikato, Hamilton, New Zealand.
5 * Authors: Daniel Lawson
6 *          Perry Lorier
7 *         
8 * All rights reserved.
9 *
10 * This code has been developed by the University of Waikato WAND
11 * research group. For further information please see http://www.wand.net.nz/
12 *
13 * libtrace is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
17 *
18 * libtrace is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with libtrace; if not, write to the Free Software
25 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
26 *
27 * $Id$
28 *
29 */
30
31#include "common.h"
32#include "config.h"
33#include <errno.h>
34#include <stdlib.h> /* free */
35#include <stdio.h> /* perror, sprintf, printf */
36#include <assert.h> /* assert */
37#include <string.h> /* bzero */
38#include "fifo.h"
39
40#include <sys/types.h>
41
42#ifdef HAVE_STDINT_H
43# include <stdint.h>
44#endif
45
46#ifdef HAVE_STDDEF_H
47# include <stddef.h>
48#else
49# error "Can't find stddef.h - do you define ptrdiff_t elsewhere"
50#endif
51
52#include <netinet/in.h>
53
54
55enum which_t { IN, OUT, ACK };
56
57struct fifo_t {
58        size_t length;
59        size_t datamap[3];
60        void *base;
61};
62
63#define MIN(a,b) ({ int _a = a; int _b = b; (_a < _b) ? _a : _b; })
64
65
66static char *fifo_stat_buffer = 0;
67
68static void increment_pointer(struct fifo_t *fifo, enum which_t which, int amount);
69static void set_pointer(struct fifo_t *fifo, enum which_t which, int location);
70static size_t fifo_compare(struct fifo_t *fifo, enum which_t first, enum which_t second);
71static int fifo_read_generic(struct fifo_t *fifo, void *buffer, size_t len, enum which_t which, char update);
72
73struct fifo_t *create_fifo(size_t size) 
74{
75        /* Set up our fifo
76        */
77        struct fifo_t *fifo = malloc(sizeof(struct fifo_t));
78        assert(size > 0);
79
80        if (fifo_stat_buffer == 0) 
81                fifo_stat_buffer = (char *)malloc(513);
82        fifo->length = size;
83
84        if ((fifo->base = malloc(fifo->length)) == 0) {
85                perror("malloc");
86                return 0;
87        }
88
89        fifo->datamap[IN] = 0;
90        fifo->datamap[OUT] = 0;
91        fifo->datamap[ACK] = 0;
92        return fifo;
93}
94
95void destroy_fifo(struct fifo_t *fifo)
96{
97        assert(fifo);
98        //free(fifo_stat_buffer);
99        free(fifo->base);
100        free(fifo);
101}
102
103static void increment_pointer(struct fifo_t *fifo, enum which_t which, int amount) {
104        assert(fifo);
105        assert(which == IN || which == OUT || which == ACK);
106        assert(amount >= 0);
107
108        if ((fifo->datamap[which] + amount) >= fifo->length) {
109                fifo->datamap[which] = (fifo->datamap[which] + amount - fifo->length);
110        } else {
111                fifo->datamap[which] += amount;
112        }
113}
114
115void fifo_flush(struct fifo_t *fifo) {
116        // do nothing
117        return;
118}
119
120static void set_pointer(struct fifo_t *fifo, enum which_t which, int location) {
121        assert(fifo);
122        assert(which == IN || which == OUT || which == ACK);
123        assert(location >= 0);
124
125        assert(location <= fifo->length);
126
127        fifo->datamap[which] = location;
128}
129
130static size_t fifo_compare(struct fifo_t *fifo, enum which_t first, enum which_t second) {
131        assert(fifo);
132        assert(first == IN || first == OUT || first == ACK);
133        assert(second == IN || second == OUT || second == ACK);
134
135        if (fifo->datamap[first] == fifo->datamap[second]) {
136                return 0;
137        }
138        if (fifo->datamap[first] > fifo->datamap[second]) {
139                return fifo->datamap[first] - fifo->datamap[second];
140        } else {
141                return fifo->length - (fifo->datamap[second] - fifo->datamap[first]);
142        }
143}
144
145size_t fifo_free(struct fifo_t *fifo) {
146        assert(fifo);
147        return (fifo->length - fifo_compare(fifo,IN,ACK));
148} 
149
150size_t fifo_length(struct fifo_t *fifo) {
151        assert(fifo);
152        return fifo->length;
153}
154
155size_t fifo_out_available(struct fifo_t *fifo) {
156        assert(fifo);
157        return fifo_compare(fifo,IN,OUT);
158}
159
160size_t fifo_ack_available(struct fifo_t *fifo) {
161        assert(fifo);
162        return fifo_compare(fifo,OUT,ACK);
163}
164
165void fifo_stat_int(struct fifo_t *fifo, fifo_state_t *state)
166{
167        assert(fifo);
168        assert(state);
169
170        state->in = fifo->datamap[IN];
171        state->out = fifo->datamap[OUT];
172        state->ack = fifo->datamap[ACK];
173        state->length = fifo->length;
174        state->used = fifo_compare(fifo,IN,ACK);
175
176}
177char *fifo_stat_str(struct fifo_t *fifo, char *desc, int delta)
178{
179        char *scan = 0;
180        assert(fifo);
181
182        bzero(fifo_stat_buffer,513);
183        scan = fifo_stat_buffer;
184        if (desc)
185                scan += sprintf(scan,"%s\t",desc);
186        scan += sprintf(scan,"in:   %d \t",fifo->datamap[IN]);
187        scan += sprintf(scan,"sent: %d\t", fifo->datamap[OUT]);
188        scan += sprintf(scan,"ack:  %d\t", fifo->datamap[ACK]);
189        if (delta > 0)
190                scan += sprintf(scan,"delta: %d\t", delta);
191        scan += sprintf(scan,"Size: %d", fifo_compare(fifo,IN,ACK));
192        scan += sprintf(scan,"\n");
193        return fifo_stat_buffer;
194}
195void fifo_stat(struct fifo_t *fifo, char *desc, int delta)
196{
197        assert(fifo);
198
199        printf("%s",fifo_stat_str(fifo,desc,delta));
200}
201
202/* Read a portion from the given section of the fifo. Note that it is the responsibility
203 * of the caller to ensure that there is something to read! This will return len bytes
204 * starting at the pointer corresponding to which - if thats bogus data then its not
205 * the fault of this function */
206static int fifo_read_generic(struct fifo_t *fifo, void *buffer, size_t len, enum which_t which, char update) {
207        size_t oldptr;
208        int lenleft;
209        int size;
210        assert(fifo);
211        assert(buffer);
212        assert(len >= 0);
213
214        oldptr = fifo->datamap[which];
215        lenleft = len;
216        while (lenleft > 0) {
217                size = MIN( ( fifo->length - fifo->datamap[which]), lenleft);
218                memcpy(buffer, 
219                                (char *)((ptrdiff_t)fifo->base + fifo->datamap[which]), 
220                                size);
221                increment_pointer(fifo,which,size);
222                buffer += size;
223                lenleft -= size;
224        }
225
226        if (update == 0) {
227                set_pointer(fifo,which,oldptr);
228        }
229        return len;
230}
231
232int fifo_write(struct fifo_t *fifo, void *buffer, size_t len) {
233        int lenleft;
234        int size;
235        assert(fifo);
236        assert(buffer);
237        assert(len >= 0);
238
239        if (fifo_free(fifo) < len) {
240                return 0;
241        }
242
243        lenleft = len;
244        while (lenleft > 0) {
245                size = MIN((fifo->length - fifo->datamap[IN]), lenleft );
246                memcpy((char *)((ptrdiff_t)fifo->base + fifo->datamap[IN]), 
247                                buffer, 
248                                size);
249                increment_pointer(fifo,IN,size);
250                buffer += size;
251                lenleft -= size;
252        }
253        return len;
254}
255
256
257int fifo_out_read(struct fifo_t *fifo, void *buffer, size_t len) {
258        assert(fifo);
259        assert(buffer);
260        assert(len >= 0);
261        if (fifo_compare(fifo,IN,OUT) < len) {
262                return 0;
263        }
264        return fifo_read_generic(fifo,buffer,len,OUT,0);
265}
266
267int fifo_ack_read(struct fifo_t *fifo, void *buffer, size_t len) {
268        assert(fifo);
269        assert(buffer);
270        assert(len >= 0);
271        if (fifo_compare(fifo,OUT,ACK) < len) {
272                return 0;
273        }
274        return fifo_read_generic(fifo,buffer,len,ACK,0);
275}
276
277int fifo_out_update(struct fifo_t *fifo, size_t len){
278        assert(fifo);
279        assert(len >= 0);
280        if (fifo_compare(fifo,IN,OUT) < len) {
281                return 0;
282        }
283        increment_pointer(fifo,OUT,len);
284        return len;
285}
286
287int fifo_ack_update(struct fifo_t *fifo, size_t len){
288        assert(fifo);
289        assert(len >= 0);
290        if (fifo_compare(fifo,OUT,ACK) < len) {
291                return 0;
292        }
293        increment_pointer(fifo,ACK,len);
294        return len;
295}
296
297void fifo_out_reset(struct fifo_t *fifo) {
298        /*
299         * This will reset the sent pointer back to the ack pointer. This
300         * is called from the application when it realises that any data it
301         * has sent but not acked will probably have died for some reason
302         */
303        assert(fifo);
304        fifo->datamap[OUT] = fifo->datamap[ACK];
305}
306
Note: See TracBrowser for help on using the repository browser.