source: lib/fifo.c @ 9ee7134

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

More portability fixes

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