source: lib/fifo.c @ 5da3315

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

avoid warnings about format specifiers

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