OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [insight/] [libiberty/] [objalloc.c] - Blame information for rev 1774

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 578 markom
/* objalloc.c -- routines to allocate memory for objects
2
   Copyright 1997 Free Software Foundation, Inc.
3
   Written by Ian Lance Taylor, Cygnus Solutions.
4
 
5
This program is free software; you can redistribute it and/or modify it
6
under the terms of the GNU General Public License as published by the
7
Free Software Foundation; either version 2, or (at your option) any
8
later version.
9
 
10
This program is distributed in the hope that it will be useful,
11
but WITHOUT ANY WARRANTY; without even the implied warranty of
12
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
GNU General Public License for more details.
14
 
15
You should have received a copy of the GNU General Public License
16
along with this program; if not, write to the Free Software
17
Foundation, 59 Temple Place - Suite 330,
18
Boston, MA 02111-1307, USA.  */
19
 
20
#include "ansidecl.h"
21
#include "config.h"
22
 
23
#include "objalloc.h"
24
 
25
/* Get a definition for NULL.  */
26
#include <stdio.h>
27
 
28
#if VMS
29
#include <stdlib.h>
30
#include <unixlib.h>
31
#else
32
 
33
#ifdef ANSI_PROTOTYPES
34
/* Get a definition for size_t.  */
35
#include <stddef.h>
36
#endif
37
 
38
#ifdef HAVE_STDLIB_H
39
#include <stdlib.h>
40
#else
41
/* For systems with larger pointers than ints, this must be declared.  */
42
extern PTR malloc PARAMS ((size_t));
43
extern void free PARAMS ((PTR));
44
#endif
45
 
46
#endif
47
 
48
/* These routines allocate space for an object.  Freeing allocated
49
   space may or may not free all more recently allocated space.
50
 
51
   We handle large and small allocation requests differently.  If we
52
   don't have enough space in the current block, and the allocation
53
   request is for more than 512 bytes, we simply pass it through to
54
   malloc.  */
55
 
56
/* The objalloc structure is defined in objalloc.h.  */
57
 
58
/* This structure appears at the start of each chunk.  */
59
 
60
struct objalloc_chunk
61
{
62
  /* Next chunk.  */
63
  struct objalloc_chunk *next;
64
  /* If this chunk contains large objects, this is the value of
65
     current_ptr when this chunk was allocated.  If this chunk
66
     contains small objects, this is NULL.  */
67
  char *current_ptr;
68
};
69
 
70
/* The aligned size of objalloc_chunk.  */
71
 
72
#define CHUNK_HEADER_SIZE                                       \
73
  ((sizeof (struct objalloc_chunk) + OBJALLOC_ALIGN - 1)        \
74
   &~ (OBJALLOC_ALIGN - 1))
75
 
76
/* We ask for this much memory each time we create a chunk which is to
77
   hold small objects.  */
78
 
79
#define CHUNK_SIZE (4096 - 32)
80
 
81
/* A request for this amount or more is just passed through to malloc.  */
82
 
83
#define BIG_REQUEST (512)
84
 
85
/* Create an objalloc structure.  */
86
 
87
struct objalloc *
88
objalloc_create ()
89
{
90
  struct objalloc *ret;
91
  struct objalloc_chunk *chunk;
92
 
93
  ret = (struct objalloc *) malloc (sizeof *ret);
94
  if (ret == NULL)
95
    return NULL;
96
 
97
  ret->chunks = (PTR) malloc (CHUNK_SIZE);
98
  if (ret->chunks == NULL)
99
    {
100
      free (ret);
101
      return NULL;
102
    }
103
 
104
  chunk = (struct objalloc_chunk *) ret->chunks;
105
  chunk->next = NULL;
106
  chunk->current_ptr = NULL;
107
 
108
  ret->current_ptr = (char *) chunk + CHUNK_HEADER_SIZE;
109
  ret->current_space = CHUNK_SIZE - CHUNK_HEADER_SIZE;
110
 
111
  return ret;
112
}
113
 
114
/* Allocate space from an objalloc structure.  */
115
 
116
PTR
117
_objalloc_alloc (o, len)
118
     struct objalloc *o;
119
     unsigned long len;
120
{
121
  /* We avoid confusion from zero sized objects by always allocating
122
     at least 1 byte.  */
123
  if (len == 0)
124
    len = 1;
125
 
126
  len = (len + OBJALLOC_ALIGN - 1) &~ (OBJALLOC_ALIGN - 1);
127
 
128
  if (len <= o->current_space)
129
    {
130
      o->current_ptr += len;
131
      o->current_space -= len;
132
      return (PTR) (o->current_ptr - len);
133
    }
134
 
135
  if (len >= BIG_REQUEST)
136
    {
137
      char *ret;
138
      struct objalloc_chunk *chunk;
139
 
140
      ret = (char *) malloc (CHUNK_HEADER_SIZE + len);
141
      if (ret == NULL)
142
        return NULL;
143
 
144
      chunk = (struct objalloc_chunk *) ret;
145
      chunk->next = (struct objalloc_chunk *) o->chunks;
146
      chunk->current_ptr = o->current_ptr;
147
 
148
      o->chunks = (PTR) chunk;
149
 
150
      return (PTR) (ret + CHUNK_HEADER_SIZE);
151
    }
152
  else
153
    {
154
      struct objalloc_chunk *chunk;
155
 
156
      chunk = (struct objalloc_chunk *) malloc (CHUNK_SIZE);
157
      if (chunk == NULL)
158
        return NULL;
159
      chunk->next = (struct objalloc_chunk *) o->chunks;
160
      chunk->current_ptr = NULL;
161
 
162
      o->current_ptr = (char *) chunk + CHUNK_HEADER_SIZE;
163
      o->current_space = CHUNK_SIZE - CHUNK_HEADER_SIZE;
164
 
165
      o->chunks = (PTR) chunk;
166
 
167
      return objalloc_alloc (o, len);
168
    }
169
}
170
 
171
/* Free an entire objalloc structure.  */
172
 
173
void
174
objalloc_free (o)
175
     struct objalloc *o;
176
{
177
  struct objalloc_chunk *l;
178
 
179
  l = (struct objalloc_chunk *) o->chunks;
180
  while (l != NULL)
181
    {
182
      struct objalloc_chunk *next;
183
 
184
      next = l->next;
185
      free (l);
186
      l = next;
187
    }
188
 
189
  free (o);
190
}
191
 
192
/* Free a block from an objalloc structure.  This also frees all more
193
   recently allocated blocks.  */
194
 
195
void
196
objalloc_free_block (o, block)
197
     struct objalloc *o;
198
     PTR block;
199
{
200
  struct objalloc_chunk *p, *small;
201
  char *b = (char *) block;
202
 
203
  /* First set P to the chunk which contains the block we are freeing,
204
     and set Q to the last small object chunk we see before P.  */
205
  small = NULL;
206
  for (p = (struct objalloc_chunk *) o->chunks; p != NULL; p = p->next)
207
    {
208
      if (p->current_ptr == NULL)
209
        {
210
          if (b > (char *) p && b < (char *) p + CHUNK_SIZE)
211
            break;
212
          small = p;
213
        }
214
      else
215
        {
216
          if (b == (char *) p + CHUNK_HEADER_SIZE)
217
            break;
218
        }
219
    }
220
 
221
  /* If we can't find the chunk, the caller has made a mistake.  */
222
  if (p == NULL)
223
    abort ();
224
 
225
  if (p->current_ptr == NULL)
226
    {
227
      struct objalloc_chunk *q;
228
      struct objalloc_chunk *first;
229
 
230
      /* The block is in a chunk containing small objects.  We can
231
         free every chunk through SMALL, because they have certainly
232
         been allocated more recently.  After SMALL, we will not see
233
         any chunks containing small objects; we can free any big
234
         chunk if the current_ptr is greater than or equal to B.  We
235
         can then reset the new current_ptr to B.  */
236
 
237
      first = NULL;
238
      q = (struct objalloc_chunk *) o->chunks;
239
      while (q != p)
240
        {
241
          struct objalloc_chunk *next;
242
 
243
          next = q->next;
244
          if (small != NULL)
245
            {
246
              if (small == q)
247
                small = NULL;
248
              free (q);
249
            }
250
          else if (q->current_ptr > b)
251
            free (q);
252
          else if (first == NULL)
253
            first = q;
254
 
255
          q = next;
256
        }
257
 
258
      if (first == NULL)
259
        first = p;
260
      o->chunks = (PTR) first;
261
 
262
      /* Now start allocating from this small block again.  */
263
      o->current_ptr = b;
264
      o->current_space = ((char *) p + CHUNK_SIZE) - b;
265
    }
266
  else
267
    {
268
      struct objalloc_chunk *q;
269
      char *current_ptr;
270
 
271
      /* This block is in a large chunk by itself.  We can free
272
         everything on the list up to and including this block.  We
273
         then start allocating from the next chunk containing small
274
         objects, setting current_ptr from the value stored with the
275
         large chunk we are freeing.  */
276
 
277
      current_ptr = p->current_ptr;
278
      p = p->next;
279
 
280
      q = (struct objalloc_chunk *) o->chunks;
281
      while (q != p)
282
        {
283
          struct objalloc_chunk *next;
284
 
285
          next = q->next;
286
          free (q);
287
          q = next;
288
        }
289
 
290
      o->chunks = (PTR) p;
291
 
292
      while (p->current_ptr != NULL)
293
        p = p->next;
294
 
295
      o->current_ptr = current_ptr;
296
      o->current_space = ((char *) p + CHUNK_SIZE) - current_ptr;
297
    }
298
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.