source: lib/fifo.c @ b5cd711

4.0.1-hotfixescachetimestampsdevelopdpdk-ndagetsilivegetfragoffhelplibtrace4ndag_formatpfringrc-4.0.1rc-4.0.2rc-4.0.3rc-4.0.4ringdecrementfixringperformanceringtimestampfixes
Last change on this file since b5cd711 was b5cd711, checked in by Shane Alcock <salcock@…>, 15 years ago

Changed all references to "fifo" to "tracefifo" with regards to function names and structures.
Fixes namespace conflicts with libfifo.

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