source: lib/fifo.c @ 02b7297

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

OpenBSD compatibility fixes - adding in various #defines and #includes that are needed to compile under OpenBSD
Added a replacement pcap_next_ex function for systems that aren't running pcap-0.8 or better

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