ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/slirp/mbuf.c
Revision: 1.2
Committed: 2006-04-02T08:47:39Z (18 years, 8 months ago) by gbeauche
Content type: text/plain
Branch: MAIN
CVS Tags: nigel-build-19
Changes since 1.1: +4 -3 lines
Log Message:
fix memory leak (1.0.17)

File Contents

# User Rev Content
1 gbeauche 1.1 /*
2     * Copyright (c) 1995 Danny Gasparovski
3     *
4     * Please read the file COPYRIGHT for the
5     * terms and conditions of the copyright.
6     */
7    
8     /*
9     * mbuf's in SLiRP are much simpler than the real mbufs in
10     * FreeBSD. They are fixed size, determined by the MTU,
11     * so that one whole packet can fit. Mbuf's cannot be
12     * chained together. If there's more data than the mbuf
13     * could hold, an external malloced buffer is pointed to
14     * by m_ext (and the data pointers) and M_EXT is set in
15     * the flags
16     */
17    
18     #include <slirp.h>
19    
20     struct mbuf *mbutl;
21     char *mclrefcnt;
22     int mbuf_alloced = 0;
23     struct mbuf m_freelist, m_usedlist;
24     int mbuf_thresh = 30;
25     int mbuf_max = 0;
26     int msize;
27    
28     void
29     m_init()
30     {
31     m_freelist.m_next = m_freelist.m_prev = &m_freelist;
32     m_usedlist.m_next = m_usedlist.m_prev = &m_usedlist;
33     msize_init();
34     }
35    
36     void
37     msize_init()
38     {
39     /*
40     * Find a nice value for msize
41     * XXX if_maxlinkhdr already in mtu
42     */
43     msize = (if_mtu>if_mru?if_mtu:if_mru) +
44     if_maxlinkhdr + sizeof(struct m_hdr ) + 6;
45     }
46    
47     /*
48     * Get an mbuf from the free list, if there are none
49     * malloc one
50     *
51     * Because fragmentation can occur if we alloc new mbufs and
52     * free old mbufs, we mark all mbufs above mbuf_thresh as M_DOFREE,
53     * which tells m_free to actually free() it
54     */
55     struct mbuf *
56     m_get()
57     {
58     register struct mbuf *m;
59     int flags = 0;
60    
61     DEBUG_CALL("m_get");
62    
63     if (m_freelist.m_next == &m_freelist) {
64     m = (struct mbuf *)malloc(msize);
65     if (m == NULL) goto end_error;
66     mbuf_alloced++;
67     if (mbuf_alloced > mbuf_thresh)
68     flags = M_DOFREE;
69     if (mbuf_alloced > mbuf_max)
70     mbuf_max = mbuf_alloced;
71     } else {
72     m = m_freelist.m_next;
73     remque(m);
74     }
75    
76     /* Insert it in the used list */
77     insque(m,&m_usedlist);
78     m->m_flags = (flags | M_USEDLIST);
79    
80     /* Initialise it */
81     m->m_size = msize - sizeof(struct m_hdr);
82     m->m_data = m->m_dat;
83     m->m_len = 0;
84     m->m_nextpkt = 0;
85     m->m_prevpkt = 0;
86     end_error:
87     DEBUG_ARG("m = %lx", (long )m);
88     return m;
89     }
90    
91     void
92     m_free(m)
93     struct mbuf *m;
94     {
95    
96     DEBUG_CALL("m_free");
97     DEBUG_ARG("m = %lx", (long )m);
98    
99     if(m) {
100     /* Remove from m_usedlist */
101     if (m->m_flags & M_USEDLIST)
102     remque(m);
103    
104     /* If it's M_EXT, free() it */
105     if (m->m_flags & M_EXT)
106     free(m->m_ext);
107    
108     /*
109     * Either free() it or put it on the free list
110     */
111     if (m->m_flags & M_DOFREE) {
112     free(m);
113     mbuf_alloced--;
114     } else if ((m->m_flags & M_FREELIST) == 0) {
115     insque(m,&m_freelist);
116     m->m_flags = M_FREELIST; /* Clobber other flags */
117     }
118     } /* if(m) */
119     }
120    
121     /*
122     * Copy data from one mbuf to the end of
123     * the other.. if result is too big for one mbuf, malloc()
124     * an M_EXT data segment
125     */
126     void
127     m_cat(m, n)
128     register struct mbuf *m, *n;
129     {
130     /*
131     * If there's no room, realloc
132     */
133     if (M_FREEROOM(m) < n->m_len)
134     m_inc(m,m->m_size+MINCSIZE);
135    
136     memcpy(m->m_data+m->m_len, n->m_data, n->m_len);
137     m->m_len += n->m_len;
138    
139     m_free(n);
140     }
141    
142    
143     /* make m size bytes large */
144     void
145     m_inc(m, size)
146     struct mbuf *m;
147     int size;
148     {
149 gbeauche 1.2 int datasize;
150    
151 gbeauche 1.1 /* some compiles throw up on gotos. This one we can fake. */
152     if(m->m_size>size) return;
153    
154     if (m->m_flags & M_EXT) {
155 gbeauche 1.2 datasize = m->m_data - m->m_ext;
156 gbeauche 1.1 m->m_ext = (char *)realloc(m->m_ext,size);
157     /* if (m->m_ext == NULL)
158     * return (struct mbuf *)NULL;
159     */
160 gbeauche 1.2 m->m_data = m->m_ext + datasize;
161 gbeauche 1.1 } else {
162     char *dat;
163     datasize = m->m_data - m->m_dat;
164     dat = (char *)malloc(size);
165     /* if (dat == NULL)
166     * return (struct mbuf *)NULL;
167     */
168     memcpy(dat, m->m_dat, m->m_size);
169    
170     m->m_ext = dat;
171     m->m_data = m->m_ext + datasize;
172     m->m_flags |= M_EXT;
173     }
174    
175     m->m_size = size;
176    
177     }
178    
179    
180    
181     void
182     m_adj(m, len)
183     struct mbuf *m;
184     int len;
185     {
186     if (m == NULL)
187     return;
188     if (len >= 0) {
189     /* Trim from head */
190     m->m_data += len;
191     m->m_len -= len;
192     } else {
193     /* Trim from tail */
194     len = -len;
195     m->m_len -= len;
196     }
197     }
198    
199    
200     /*
201     * Copy len bytes from m, starting off bytes into n
202     */
203     int
204     m_copy(n, m, off, len)
205     struct mbuf *n, *m;
206     int off, len;
207     {
208     if (len > M_FREEROOM(n))
209     return -1;
210    
211     memcpy((n->m_data + n->m_len), (m->m_data + off), len);
212     n->m_len += len;
213     return 0;
214     }
215    
216    
217     /*
218     * Given a pointer into an mbuf, return the mbuf
219     * XXX This is a kludge, I should eliminate the need for it
220     * Fortunately, it's not used often
221     */
222     struct mbuf *
223     dtom(dat)
224     void *dat;
225     {
226     struct mbuf *m;
227    
228     DEBUG_CALL("dtom");
229     DEBUG_ARG("dat = %lx", (long )dat);
230    
231     /* bug corrected for M_EXT buffers */
232     for (m = m_usedlist.m_next; m != &m_usedlist; m = m->m_next) {
233     if (m->m_flags & M_EXT) {
234     if( (char *)dat>=m->m_ext && (char *)dat<(m->m_ext + m->m_size) )
235     return m;
236     } else {
237     if( (char *)dat >= m->m_dat && (char *)dat<(m->m_dat + m->m_size) )
238     return m;
239     }
240     }
241    
242     DEBUG_ERROR((dfd, "dtom failed"));
243    
244     return (struct mbuf *)0;
245     }
246