source: lib/fifo.c @ 114b8d6

4.0.1-hotfixescachetimestampsdevelopdpdk-ndagetsilivegetfragoffhelplibtrace4ndag_formatpfringrc-4.0.1rc-4.0.2rc-4.0.3rc-4.0.4ringdecrementfixringperformanceringtimestampfixes
Last change on this file since 114b8d6 was 9e830d4, checked in by Perry Lorier <perry@…>, 15 years ago

More portability/warnings fixed

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