source: lib/fifo.c @ b296c02

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

fixes for AMD64

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