source: lib/fifo.c @ 90e4aa4

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

added license information

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