source: lib/fifo.c @ c5a22ec

4.0.1-hotfixescachetimestampsdevelopdpdk-ndagetsilivegetfragoffhelplibtrace4ndag_formatpfringrc-4.0.1rc-4.0.2rc-4.0.3rc-4.0.4ringdecrementfixringperformanceringtimestampfixes
Last change on this file since c5a22ec was 2c060e3, checked in by Daniel Lawson <dlawson@…>, 17 years ago

Initial revision

  • Property mode set to 100644
File size: 7.5 KB
Line 
1
2// $Id$
3
4#include <errno.h>
5#include <stdlib.h> /* free */
6#include <stdio.h> /* perror, sprintf, printf */
7#include <assert.h> /* assert */
8#include <string.h> /* bzero */
9#include "fifo.h"
10
11#include <netinet/in.h>
12
13
14enum which_t { IN, OUT, ACK };
15
16struct fifo_t {
17        size_t length;
18        size_t datamap[3];
19        void *base;
20};
21
22#define MIN(a,b) ({ int _a = a; int _b = b; (_a < _b) ? _a : _b; })
23
24
25static char *fifo_stat_buffer = 0;
26
27static void increment_pointer(struct fifo_t *fifo, enum which_t which, int amount);
28static void set_pointer(struct fifo_t *fifo, enum which_t which, int location);
29static size_t fifo_compare(struct fifo_t *fifo, enum which_t first, enum which_t second);
30static int fifo_read_generic(struct fifo_t *fifo, void *buffer, size_t len, enum which_t which, char update);
31
32struct fifo_t *create_fifo(size_t size) 
33{
34        /* Set up our fifo
35        */
36        struct fifo_t *fifo = malloc(sizeof(struct fifo_t));
37        assert(size > 0);
38
39        if (fifo_stat_buffer == 0) 
40                fifo_stat_buffer = (char *)malloc(513);
41        fifo->length = size;
42
43        if ((fifo->base = malloc(fifo->length)) == 0) {
44                perror("malloc");
45                return 0;
46        }
47
48        fifo->datamap[IN] = 0;
49        fifo->datamap[OUT] = 0;
50        fifo->datamap[ACK] = 0;
51        return fifo;
52}
53
54void destroy_fifo(struct fifo_t *fifo)
55{
56        assert(fifo);
57        //free(fifo_stat_buffer);
58        free(fifo->base);
59        free(fifo);
60}
61
62static void increment_pointer(struct fifo_t *fifo, enum which_t which, int amount) {
63        assert(fifo);
64        assert(which == IN || which == OUT || which == ACK);
65        assert(amount >= 0);
66
67        if ((fifo->datamap[which] + amount) >= fifo->length) {
68                fifo->datamap[which] = (fifo->datamap[which] + amount - fifo->length);
69        } else {
70                fifo->datamap[which] += amount;
71        }
72}
73
74void fifo_flush(struct fifo_t *fifo) {
75        // do nothing
76        return;
77}
78
79static void set_pointer(struct fifo_t *fifo, enum which_t which, int location) {
80        assert(fifo);
81        assert(which == IN || which == OUT || which == ACK);
82        assert(location >= 0);
83
84        assert(location <= fifo->length);
85
86        fifo->datamap[which] = location;
87}
88
89static size_t fifo_compare(struct fifo_t *fifo, enum which_t first, enum which_t second) {
90        assert(fifo);
91        assert(first == IN || first == OUT || first == ACK);
92        assert(second == IN || second == OUT || second == ACK);
93
94        if (fifo->datamap[first] == fifo->datamap[second]) {
95                return 0;
96        }
97        if (fifo->datamap[first] > fifo->datamap[second]) {
98                return fifo->datamap[first] - fifo->datamap[second];
99        } else {
100                return fifo->length - (fifo->datamap[second] - fifo->datamap[first]);
101        }
102}
103
104size_t fifo_free(struct fifo_t *fifo) {
105        assert(fifo);
106        return (fifo->length - fifo_compare(fifo,IN,ACK));
107} 
108
109size_t fifo_length(struct fifo_t *fifo) {
110        assert(fifo);
111        return fifo->length;
112}
113
114size_t fifo_out_available(struct fifo_t *fifo) {
115        assert(fifo);
116        return fifo_compare(fifo,IN,OUT);
117}
118
119size_t fifo_ack_available(struct fifo_t *fifo) {
120        assert(fifo);
121        return fifo_compare(fifo,OUT,ACK);
122}
123
124void fifo_stat_int(struct fifo_t *fifo, fifo_state_t *state)
125{
126        assert(fifo);
127        assert(state);
128
129        state->in = fifo->datamap[IN];
130        state->out = fifo->datamap[OUT];
131        state->ack = fifo->datamap[ACK];
132        state->length = fifo->length;
133        state->used = fifo_compare(fifo,IN,ACK);
134
135}
136char *fifo_stat_str(struct fifo_t *fifo, char *desc, int delta)
137{
138        char *scan = 0;
139        assert(fifo);
140
141        bzero(fifo_stat_buffer,513);
142        scan = fifo_stat_buffer;
143        if (desc)
144                scan += sprintf(scan,"%s\t",desc);
145        scan += sprintf(scan,"in:   %d \t",fifo->datamap[IN]);
146        scan += sprintf(scan,"sent: %d\t", fifo->datamap[OUT]);
147        scan += sprintf(scan,"ack:  %d\t", fifo->datamap[ACK]);
148        if (delta > 0)
149                scan += sprintf(scan,"delta: %d\t", delta);
150        scan += sprintf(scan,"Size: %d", fifo_compare(fifo,IN,ACK));
151        scan += sprintf(scan,"\n");
152        return fifo_stat_buffer;
153}
154void fifo_stat(struct fifo_t *fifo, char *desc, int delta)
155{
156        assert(fifo);
157
158        printf("%s",fifo_stat_str(fifo,desc,delta));
159}
160
161/* Read a portion from the given section of the fifo. Note that it is the responsibility
162 * of the caller to ensure that there is something to read! This will return len bytes
163 * starting at the pointer corresponding to which - if thats bogus data then its not
164 * the fault of this function */
165static int fifo_read_generic(struct fifo_t *fifo, void *buffer, size_t len, enum which_t which, char update) {
166        size_t oldptr;
167        int lenleft;
168        int size;
169        assert(fifo);
170        assert(buffer);
171        assert(len >= 0);
172
173        oldptr = fifo->datamap[which];
174        lenleft = len;
175        while (lenleft > 0) {
176                size = MIN( ( fifo->length - fifo->datamap[which]), lenleft);
177                memcpy(buffer, 
178                                (char *)((int)fifo->base + fifo->datamap[which]), 
179                                size);
180                increment_pointer(fifo,which,size);
181                buffer += size;
182                lenleft -= size;
183        }
184
185        if (update == 0) {
186                set_pointer(fifo,which,oldptr);
187        }
188        return len;
189}
190
191int fifo_write(struct fifo_t *fifo, void *buffer, size_t len) {
192        int lenleft;
193        int size;
194        assert(fifo);
195        assert(buffer);
196        assert(len >= 0);
197
198        if (fifo_free(fifo) < len) {
199                return 0;
200        }
201
202        lenleft = len;
203        while (lenleft > 0) {
204                size = MIN((fifo->length - fifo->datamap[IN]), lenleft );
205                memcpy((char *)((int)fifo->base + fifo->datamap[IN]), 
206                                buffer, 
207                                size);
208                increment_pointer(fifo,IN,size);
209                buffer += size;
210                lenleft -= size;
211        }
212        return len;
213}
214
215
216int fifo_out_read(struct fifo_t *fifo, void *buffer, size_t len) {
217        assert(fifo);
218        assert(buffer);
219        assert(len >= 0);
220        if (fifo_compare(fifo,IN,OUT) < len) {
221                return 0;
222        }
223        return fifo_read_generic(fifo,buffer,len,OUT,0);
224}
225
226int fifo_ack_read(struct fifo_t *fifo, void *buffer, size_t len) {
227        assert(fifo);
228        assert(buffer);
229        assert(len >= 0);
230        if (fifo_compare(fifo,OUT,ACK) < len) {
231                return 0;
232        }
233        return fifo_read_generic(fifo,buffer,len,ACK,0);
234}
235
236int fifo_out_update(struct fifo_t *fifo, size_t len){
237        assert(fifo);
238        assert(len >= 0);
239        if (fifo_compare(fifo,IN,OUT) < len) {
240                return 0;
241        }
242        increment_pointer(fifo,OUT,len);
243        return len;
244}
245
246int fifo_ack_update(struct fifo_t *fifo, size_t len){
247        assert(fifo);
248        assert(len >= 0);
249        if (fifo_compare(fifo,OUT,ACK) < len) {
250                return 0;
251        }
252        increment_pointer(fifo,ACK,len);
253        return len;
254}
255
256void fifo_out_reset(struct fifo_t *fifo) {
257        /*
258         * This will reset the sent pointer back to the ack pointer. This
259         * is called from the application when it realises that any data it
260         * has sent but not acked will probably have died for some reason
261         */
262        assert(fifo);
263        fifo->datamap[OUT] = fifo->datamap[ACK];
264}
265
Note: See TracBrowser for help on using the repository browser.