source: lib/fifo.c @ 60fc8aa

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

poink

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