source: lib/fifo.c @ e5ee47e

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

test for stdint.h

  • Property mode set to 100644
File size: 8.7 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#ifdef HAVE_STDINT_H
41# include <stdint.h>
42#endif
43
44#ifdef HAVE_STDDEF_H
45# include <stddef.h>
46#else
47# error "Can't find stddef.h - do you define ptrdiff_t elsewhere"
48#endif
49
50#include <netinet/in.h>
51
52
53enum which_t { IN, OUT, ACK };
54
55struct fifo_t {
56        size_t length;
57        size_t datamap[3];
58        void *base;
59};
60
61#define MIN(a,b) ({ int _a = a; int _b = b; (_a < _b) ? _a : _b; })
62
63
64static char *fifo_stat_buffer = 0;
65
66static void increment_pointer(struct fifo_t *fifo, enum which_t which, int amount);
67static void set_pointer(struct fifo_t *fifo, enum which_t which, int location);
68static size_t fifo_compare(struct fifo_t *fifo, enum which_t first, enum which_t second);
69static int fifo_read_generic(struct fifo_t *fifo, void *buffer, size_t len, enum which_t which, char update);
70
71struct fifo_t *create_fifo(size_t size) 
72{
73        /* Set up our fifo
74        */
75        struct fifo_t *fifo = malloc(sizeof(struct fifo_t));
76        assert(size > 0);
77
78        if (fifo_stat_buffer == 0) 
79                fifo_stat_buffer = (char *)malloc(513);
80        fifo->length = size;
81
82        if ((fifo->base = malloc(fifo->length)) == 0) {
83                perror("malloc");
84                return 0;
85        }
86
87        fifo->datamap[IN] = 0;
88        fifo->datamap[OUT] = 0;
89        fifo->datamap[ACK] = 0;
90        return fifo;
91}
92
93void destroy_fifo(struct fifo_t *fifo)
94{
95        assert(fifo);
96        //free(fifo_stat_buffer);
97        free(fifo->base);
98        free(fifo);
99}
100
101static void increment_pointer(struct fifo_t *fifo, enum which_t which, int amount) {
102        assert(fifo);
103        assert(which == IN || which == OUT || which == ACK);
104        assert(amount >= 0);
105
106        if ((fifo->datamap[which] + amount) >= fifo->length) {
107                fifo->datamap[which] = (fifo->datamap[which] + amount - fifo->length);
108        } else {
109                fifo->datamap[which] += amount;
110        }
111}
112
113void fifo_flush(struct fifo_t *fifo) {
114        // do nothing
115        return;
116}
117
118static void set_pointer(struct fifo_t *fifo, enum which_t which, int location) {
119        assert(fifo);
120        assert(which == IN || which == OUT || which == ACK);
121        assert(location >= 0);
122
123        assert(location <= fifo->length);
124
125        fifo->datamap[which] = location;
126}
127
128static size_t fifo_compare(struct fifo_t *fifo, enum which_t first, enum which_t second) {
129        assert(fifo);
130        assert(first == IN || first == OUT || first == ACK);
131        assert(second == IN || second == OUT || second == ACK);
132
133        if (fifo->datamap[first] == fifo->datamap[second]) {
134                return 0;
135        }
136        if (fifo->datamap[first] > fifo->datamap[second]) {
137                return fifo->datamap[first] - fifo->datamap[second];
138        } else {
139                return fifo->length - (fifo->datamap[second] - fifo->datamap[first]);
140        }
141}
142
143size_t fifo_free(struct fifo_t *fifo) {
144        assert(fifo);
145        return (fifo->length - fifo_compare(fifo,IN,ACK));
146} 
147
148size_t fifo_length(struct fifo_t *fifo) {
149        assert(fifo);
150        return fifo->length;
151}
152
153size_t fifo_out_available(struct fifo_t *fifo) {
154        assert(fifo);
155        return fifo_compare(fifo,IN,OUT);
156}
157
158size_t fifo_ack_available(struct fifo_t *fifo) {
159        assert(fifo);
160        return fifo_compare(fifo,OUT,ACK);
161}
162
163void fifo_stat_int(struct fifo_t *fifo, fifo_state_t *state)
164{
165        assert(fifo);
166        assert(state);
167
168        state->in = fifo->datamap[IN];
169        state->out = fifo->datamap[OUT];
170        state->ack = fifo->datamap[ACK];
171        state->length = fifo->length;
172        state->used = fifo_compare(fifo,IN,ACK);
173
174}
175char *fifo_stat_str(struct fifo_t *fifo, char *desc, int delta)
176{
177        char *scan = 0;
178        assert(fifo);
179
180        bzero(fifo_stat_buffer,513);
181        scan = fifo_stat_buffer;
182        if (desc)
183                scan += sprintf(scan,"%s\t",desc);
184        scan += sprintf(scan,"in:   %d \t",fifo->datamap[IN]);
185        scan += sprintf(scan,"sent: %d\t", fifo->datamap[OUT]);
186        scan += sprintf(scan,"ack:  %d\t", fifo->datamap[ACK]);
187        if (delta > 0)
188                scan += sprintf(scan,"delta: %d\t", delta);
189        scan += sprintf(scan,"Size: %d", fifo_compare(fifo,IN,ACK));
190        scan += sprintf(scan,"\n");
191        return fifo_stat_buffer;
192}
193void fifo_stat(struct fifo_t *fifo, char *desc, int delta)
194{
195        assert(fifo);
196
197        printf("%s",fifo_stat_str(fifo,desc,delta));
198}
199
200/* Read a portion from the given section of the fifo. Note that it is the responsibility
201 * of the caller to ensure that there is something to read! This will return len bytes
202 * starting at the pointer corresponding to which - if thats bogus data then its not
203 * the fault of this function */
204static int fifo_read_generic(struct fifo_t *fifo, void *buffer, size_t len, enum which_t which, char update) {
205        size_t oldptr;
206        int lenleft;
207        int size;
208        assert(fifo);
209        assert(buffer);
210        assert(len >= 0);
211
212        oldptr = fifo->datamap[which];
213        lenleft = len;
214        while (lenleft > 0) {
215                size = MIN( ( fifo->length - fifo->datamap[which]), lenleft);
216                memcpy(buffer, 
217                                (char *)((ptrdiff_t)fifo->base + fifo->datamap[which]), 
218                                size);
219                increment_pointer(fifo,which,size);
220                buffer += size;
221                lenleft -= size;
222        }
223
224        if (update == 0) {
225                set_pointer(fifo,which,oldptr);
226        }
227        return len;
228}
229
230int fifo_write(struct fifo_t *fifo, void *buffer, size_t len) {
231        int lenleft;
232        int size;
233        assert(fifo);
234        assert(buffer);
235        assert(len >= 0);
236
237        if (fifo_free(fifo) < len) {
238                return 0;
239        }
240
241        lenleft = len;
242        while (lenleft > 0) {
243                size = MIN((fifo->length - fifo->datamap[IN]), lenleft );
244                memcpy((char *)((ptrdiff_t)fifo->base + fifo->datamap[IN]), 
245                                buffer, 
246                                size);
247                increment_pointer(fifo,IN,size);
248                buffer += size;
249                lenleft -= size;
250        }
251        return len;
252}
253
254
255int fifo_out_read(struct fifo_t *fifo, void *buffer, size_t len) {
256        assert(fifo);
257        assert(buffer);
258        assert(len >= 0);
259        if (fifo_compare(fifo,IN,OUT) < len) {
260                return 0;
261        }
262        return fifo_read_generic(fifo,buffer,len,OUT,0);
263}
264
265int fifo_ack_read(struct fifo_t *fifo, void *buffer, size_t len) {
266        assert(fifo);
267        assert(buffer);
268        assert(len >= 0);
269        if (fifo_compare(fifo,OUT,ACK) < len) {
270                return 0;
271        }
272        return fifo_read_generic(fifo,buffer,len,ACK,0);
273}
274
275int fifo_out_update(struct fifo_t *fifo, size_t len){
276        assert(fifo);
277        assert(len >= 0);
278        if (fifo_compare(fifo,IN,OUT) < len) {
279                return 0;
280        }
281        increment_pointer(fifo,OUT,len);
282        return len;
283}
284
285int fifo_ack_update(struct fifo_t *fifo, size_t len){
286        assert(fifo);
287        assert(len >= 0);
288        if (fifo_compare(fifo,OUT,ACK) < len) {
289                return 0;
290        }
291        increment_pointer(fifo,ACK,len);
292        return len;
293}
294
295void fifo_out_reset(struct fifo_t *fifo) {
296        /*
297         * This will reset the sent pointer back to the ack pointer. This
298         * is called from the application when it realises that any data it
299         * has sent but not acked will probably have died for some reason
300         */
301        assert(fifo);
302        fifo->datamap[OUT] = fifo->datamap[ACK];
303}
304
Note: See TracBrowser for help on using the repository browser.