~ubuntu-branches/ubuntu/karmic/gtk-gnutella/karmic

« back to all changes in this revision

Viewing changes to src/walloc.c

  • Committer: Bazaar Package Importer
  • Author(s): Anand Kumria
  • Date: 2005-08-04 11:32:05 UTC
  • mfrom: (1.2.1 upstream) (2.1.1 sarge)
  • Revision ID: james.westby@ubuntu.com-20050804113205-q746i4lgo3rtlegn
Tags: 0.95.4-1
New upstream release.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * $Id: walloc.c,v 1.12 2004/01/17 13:46:23 rmanfredi Exp $
3
 
 *
4
 
 * Copyright (c) 2002-2003, Raphael Manfredi
5
 
 *
6
 
 * Explicit-width block allocator, based on zalloc().
7
 
 *
8
 
 *----------------------------------------------------------------------
9
 
 * This file is part of gtk-gnutella.
10
 
 *
11
 
 *  gtk-gnutella is free software; you can redistribute it and/or modify
12
 
 *  it under the terms of the GNU General Public License as published by
13
 
 *  the Free Software Foundation; either version 2 of the License, or
14
 
 *  (at your option) any later version.
15
 
 *
16
 
 *  gtk-gnutella is distributed in the hope that it will be useful,
17
 
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
18
 
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19
 
 *  GNU General Public License for more details.
20
 
 *
21
 
 *  You should have received a copy of the GNU General Public License
22
 
 *  along with gtk-gnutella; if not, write to the Free Software
23
 
 *  Foundation, Inc.:
24
 
 *      59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
25
 
 *----------------------------------------------------------------------
26
 
 */
27
 
 
28
 
#include "common.h"
29
 
 
30
 
#include "walloc.h"
31
 
#include "zalloc.h"
32
 
#include "override.h"           /* Must be the last header included */
33
 
 
34
 
RCSID("$Id: walloc.c,v 1.12 2004/01/17 13:46:23 rmanfredi Exp $");
35
 
 
36
 
#if ZALLOC_ALIGNBYTES == 2
37
 
#define ZALLOC_ALIGNBITS 1
38
 
#elif ZALLOC_ALIGNBYTES == 4
39
 
#define ZALLOC_ALIGNBITS 2
40
 
#elif ZALLOC_ALIGNBYTES == 8
41
 
#define ZALLOC_ALIGNBITS 3
42
 
#else
43
 
#error "Unexpected ZALLOC_ALIGNBYTES value"
44
 
#endif
45
 
 
46
 
#ifdef TRACK_ZALLOC
47
 
#undef walloc                                   /* We want to define the real routines */
48
 
#undef walloc0
49
 
#undef wrealloc
50
 
#endif
51
 
 
52
 
#define WALLOC_MAX              4096    /* Passed this size, use malloc() */
53
 
#define WALLOC_CHUNK    4096    /* Target chunk size for small structs */
54
 
#define WALLOC_MINCOUNT 8               /* Minimum amount of structs in a chunk */
55
 
 
56
 
#define WZONE_SIZE      (WALLOC_MAX / ZALLOC_ALIGNBYTES)
57
 
 
58
 
static struct zone *wzone[WZONE_SIZE];
59
 
 
60
 
/*
61
 
 * Under REMAP_ZALLOC, do not define walloc(), wfree() and wrealloc().
62
 
 */
63
 
 
64
 
#ifndef REMAP_ZALLOC
65
 
/*
66
 
 * walloc
67
 
 *
68
 
 * Allocate memory from a zone suitable for the given size.
69
 
 *
70
 
 * The basics for this algorithm is to allocate from fixed-sized zones, which
71
 
 * are multiples of ZALLOC_ALIGNBYTES until WALLOC_MAX (e.g. 8, 16, 24, 40, ...)
72
 
 * and to malloc() if size is greater or equal to WALLOC_MAX.
73
 
 * Naturally, zones are allocated on demand only.
74
 
 *
75
 
 * Returns a pointer to the start of the allocated block.
76
 
 */
77
 
gpointer walloc(int size)
78
 
{
79
 
        zone_t *zone;
80
 
        gint rounded = zalloc_round(size);
81
 
        gint idx;
82
 
 
83
 
        g_assert(size > 0);
84
 
 
85
 
        if (rounded >= WALLOC_MAX)
86
 
                return g_malloc(size);          /* Too big for efficient zalloc() */
87
 
 
88
 
        idx = rounded >> ZALLOC_ALIGNBITS;
89
 
 
90
 
        g_assert(WALLOC_MAX >> ZALLOC_ALIGNBITS == WZONE_SIZE);
91
 
        g_assert(idx >= 0 && idx < WZONE_SIZE);
92
 
 
93
 
        if (!(zone = wzone[idx])) {
94
 
                gint count;
95
 
 
96
 
                /*
97
 
                 * We're paying this computation/allocation cost once per size!
98
 
                 *
99
 
                 * Try to create approximately WALLOC_CHUNK byte chunks, but
100
 
                 * capable of holding at least WALLOC_MINCOUNT structures.
101
 
                 */
102
 
 
103
 
                count = WALLOC_CHUNK / rounded;
104
 
                count = MAX(count, WALLOC_MINCOUNT);
105
 
 
106
 
                if (!(zone = wzone[idx] = zget(rounded, count)))
107
 
                        g_error("zget() failed?");
108
 
        }
109
 
 
110
 
        return zalloc(zone);
111
 
}
112
 
 
113
 
/*
114
 
 * walloc0
115
 
 *
116
 
 * Same as walloc(), but zeroes the allocated memory before returning.
117
 
 */
118
 
gpointer walloc0(int size)
119
 
{
120
 
        gpointer p = walloc(size);
121
 
 
122
 
        if (p != NULL)
123
 
                memset(p, 0, size);
124
 
 
125
 
        return p;
126
 
}
127
 
 
128
 
/*
129
 
 * wfree
130
 
 *
131
 
 * Free a block allocated via walloc().
132
 
 *
133
 
 * The size is used to find the zone from which the block was allocated, or
134
 
 * to determine that we actually malloc()'ed it so it gets free()'ed.
135
 
 */
136
 
void wfree(gpointer ptr, gint size)
137
 
{
138
 
        zone_t *zone;
139
 
        gint rounded = zalloc_round(size);
140
 
        gint idx;
141
 
 
142
 
        g_assert(ptr);
143
 
        g_assert(size > 0);
144
 
        
145
 
        if (rounded >= WALLOC_MAX) {
146
 
                g_free(ptr);
147
 
                return;
148
 
        }
149
 
 
150
 
        idx = rounded >> ZALLOC_ALIGNBITS;
151
 
 
152
 
        g_assert(idx >= 0 && idx < WZONE_SIZE);
153
 
 
154
 
        zone = wzone[idx];
155
 
        g_assert(zone);
156
 
 
157
 
        zfree(zone, ptr);
158
 
}
159
 
 
160
 
/*
161
 
 * wrealloc
162
 
 *
163
 
 * Reallocate a block allocated via walloc().
164
 
 * Returns new block address.
165
 
 */
166
 
gpointer wrealloc(gpointer old, gint old_size, gint new_size)
167
 
{
168
 
        gpointer new;
169
 
        gint rounded = zalloc_round(new_size);
170
 
 
171
 
        if (zalloc_round(old_size) == rounded)
172
 
                return old;
173
 
 
174
 
        new = walloc(new_size);
175
 
        memcpy(new, old, MIN(old_size, new_size));
176
 
        wfree(old, old_size);
177
 
 
178
 
        return new;
179
 
}
180
 
#endif  /* !REMAP_ZALLOC */
181
 
 
182
 
/***
183
 
 *** Tracking versions of the walloc routines.
184
 
 ***/
185
 
 
186
 
#ifdef TRACK_ZALLOC
187
 
/*
188
 
 * walloc_track
189
 
 *
190
 
 * Allocate memory from a zone suitable for the given size.
191
 
 * Returns a pointer to the start of the allocated block.
192
 
 */
193
 
gpointer walloc_track(int size, gchar *file, gint line)
194
 
{
195
 
        zone_t *zone;
196
 
        gint rounded = zalloc_round(size);
197
 
        gint idx;
198
 
 
199
 
        g_assert(size > 0);
200
 
 
201
 
        if (rounded >= WALLOC_MAX)
202
 
#ifdef TRACK_MALLOC
203
 
                return malloc_track(size, file, line);
204
 
#else
205
 
                return g_malloc(size);          /* Too big for efficient zalloc() */
206
 
#endif
207
 
 
208
 
        idx = rounded >> ZALLOC_ALIGNBITS;
209
 
 
210
 
        g_assert(WALLOC_MAX >> ZALLOC_ALIGNBITS == WZONE_SIZE);
211
 
        g_assert(idx >= 0 && idx < WZONE_SIZE);
212
 
 
213
 
        if (!(zone = wzone[idx])) {
214
 
                gint count;
215
 
 
216
 
                /*
217
 
                 * We're paying this computation/allocation cost once per size!
218
 
                 *
219
 
                 * Try to create approximately WALLOC_CHUNK byte chunks, but
220
 
                 * capable of holding at least WALLOC_MINCOUNT structures.
221
 
                 */
222
 
 
223
 
                count = WALLOC_CHUNK / rounded;
224
 
                count = MAX(count, WALLOC_MINCOUNT);
225
 
 
226
 
                if (!(zone = wzone[idx] = zget(rounded, count)))
227
 
                        g_error("zget() failed?");
228
 
        }
229
 
 
230
 
        return zalloc_track(zone, file, line);
231
 
}
232
 
 
233
 
/*
234
 
 * walloc0_track
235
 
 *
236
 
 * Same as walloc_track(), but zeroes the allocated memory before returning.
237
 
 */
238
 
gpointer walloc0_track(int size, gchar *file, gint line)
239
 
{
240
 
        gpointer p = walloc_track(size, file, line);
241
 
 
242
 
        if (p != NULL)
243
 
                memset(p, 0, size);
244
 
 
245
 
        return p;
246
 
}
247
 
 
248
 
/*
249
 
 * wrealloc_track
250
 
 *
251
 
 * Reallocate a block allocated via walloc().
252
 
 * Returns new block address.
253
 
 */
254
 
gpointer wrealloc_track(gpointer old, gint old_size, gint new_size,
255
 
        gchar *file, gint line)
256
 
{
257
 
        gpointer new;
258
 
        gint rounded = zalloc_round(new_size);
259
 
 
260
 
        if (zalloc_round(old_size) == rounded)
261
 
                return old;
262
 
 
263
 
        new = walloc_track(new_size, file, line);
264
 
        memcpy(new, old, MIN(old_size, new_size));
265
 
        wfree(old, old_size);
266
 
 
267
 
        return new;
268
 
}
269
 
#endif  /* TRACK_ZALLOC */
270
 
 
271
 
/*
272
 
 * wdestroy
273
 
 *
274
 
 * Destroy all the zones we allocated so far.
275
 
 */
276
 
void wdestroy(void)
277
 
{
278
 
        gint i;
279
 
 
280
 
        for (i = 0; i < WZONE_SIZE; i++) {
281
 
                if (wzone[i] != NULL) {
282
 
                        zdestroy(wzone[i]);
283
 
                        wzone[i] = NULL;
284
 
                }
285
 
        }
286
 
}
287