~ubuntu-branches/ubuntu/karmic/python-scipy/karmic

« back to all changes in this revision

Viewing changes to Lib/xplt/src/play/all/mminit.c

  • Committer: Bazaar Package Importer
  • Author(s): Daniel T. Chen (new)
  • Date: 2005-03-16 02:15:29 UTC
  • Revision ID: james.westby@ubuntu.com-20050316021529-xrjlowsejs0cijig
Tags: upstream-0.3.2
ImportĀ upstreamĀ versionĀ 0.3.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * mminit.c -- $Id: mminit.c,v 1.1 2003/03/08 15:26:47 travo Exp $
 
3
 * basic memory management interface
 
4
 *
 
5
 * compile this file twice:
 
6
 * P_DEBUG not defined makes production version (p_mminit)
 
7
 * P_DEBUG defined makes debug version (p_mmdebug)
 
8
 *
 
9
 * Copyright (c) 1998.  See accompanying LEGAL file for details.
 
10
 */
 
11
 
 
12
#include "config.h"
 
13
#include "pstdlib.h"
 
14
 
 
15
typedef union mm_block mm_block;
 
16
typedef struct mm_arena mm_arena;
 
17
 
 
18
union mm_block {
 
19
  mm_block *next_free;  /* when not in use */
 
20
  mm_arena *arena;      /* when in use */
 
21
  /* remainder assure most restrictive alignment */
 
22
  long l;
 
23
  double d;   /* long double tickles bug for linux gcc 2.7.2 */
 
24
  void (*f)(void);
 
25
};
 
26
 
 
27
#ifndef P_DEBUG
 
28
# define MM_OFFSET 1
 
29
# define MM_EXTRA 1
 
30
# define MM_GUARD(block, n)
 
31
# define MM_CHECK(p, n)
 
32
# define MM_VCHECK(p)
 
33
#else
 
34
# define MM_OFFSET 3
 
35
# define MM_EXTRA 4
 
36
# define MM_GUARD(block, n) p_mmguard(block, n);
 
37
# define MM_CHECK(p, n) if (p_mmcheck(p)) return p_mmfail(n);
 
38
# define MM_VCHECK(p) if (p_mmcheck(p)) { p_mmfail(0); return; }
 
39
long p_mmoffset = MM_OFFSET*sizeof(mm_block);
 
40
long p_mmextra = MM_EXTRA*sizeof(mm_block);
 
41
#endif
 
42
 
 
43
static void *bmalloc(size_t);
 
44
static void  bfree(void *);
 
45
static void *brealloc(void *, size_t);
 
46
 
 
47
struct mm_arena {
 
48
  mm_block *next_free;
 
49
  mm_block *blocks;     /* current chunk */
 
50
  long n_blocks;        /* total number of mm_blocks per chunk */
 
51
  long size;            /* number of mm_blocks per unit */
 
52
};
 
53
 
 
54
/* the numbers are the number of allocation units per chunk
 
55
 * and the number of mm_blocks per unit (augmented by MM_EXTRA) */
 
56
static mm_arena arenas[6] = {
 
57
  { 0, 0, 512*( 1+MM_EXTRA),  1+MM_EXTRA },
 
58
  { 0, 0, 384*( 2+MM_EXTRA),  2+MM_EXTRA },
 
59
  { 0, 0, 256*( 4+MM_EXTRA),  4+MM_EXTRA },
 
60
  { 0, 0, 128*( 8+MM_EXTRA),  8+MM_EXTRA },
 
61
  { 0, 0, 64 *(16+MM_EXTRA), 16+MM_EXTRA },
 
62
  { 0, 0, 32 *(32+MM_EXTRA), 32+MM_EXTRA }};
 
63
 
 
64
static mm_arena *arena_list[32] = {
 
65
  arenas,  arenas+1,arenas+2,arenas+2,arenas+3,arenas+3,arenas+3,arenas+3,
 
66
  arenas+4,arenas+4,arenas+4,arenas+4,arenas+4,arenas+4,arenas+4,arenas+4,
 
67
  arenas+5,arenas+5,arenas+5,arenas+5,arenas+5,arenas+5,arenas+5,arenas+5,
 
68
  arenas+5,arenas+5,arenas+5,arenas+5,arenas+5,arenas+5,arenas+5,arenas+5 };
 
69
 
 
70
static mm_block *expand_arena(mm_arena *arena);
 
71
 
 
72
void
 
73
p_mminit(void)  /* actually p_mmdebug if P_DEBUG */
 
74
{
 
75
  p_malloc =  &bmalloc;
 
76
  p_free =    &bfree;
 
77
  p_realloc = &brealloc;
 
78
}
 
79
 
 
80
static void *
 
81
bmalloc(size_t n)
 
82
{
 
83
  mm_block *block;
 
84
  if (n<=0) n = 1;
 
85
  if (n <= 32*sizeof(mm_block)) {
 
86
    mm_arena *arena = arena_list[(n-1)/sizeof(mm_block)];
 
87
    block = arena->next_free;
 
88
    if (!block) {
 
89
      block = expand_arena(arena);
 
90
      if (!block) return p_mmfail(n);
 
91
    }
 
92
    arena->next_free = block->next_free;
 
93
    block->arena = arena;
 
94
    p_nsmall++;
 
95
  } else {
 
96
    block = (void *)malloc(MM_EXTRA*sizeof(mm_block)+n);
 
97
    if (!block) return p_mmfail(n);
 
98
    block->arena = 0;
 
99
  }
 
100
  MM_GUARD(block, n)
 
101
  p_nallocs++;
 
102
  return block+MM_OFFSET;
 
103
}
 
104
 
 
105
static void
 
106
bfree(void *p)
 
107
{
 
108
  if (p) {
 
109
    mm_block *block = ((mm_block *)p) - MM_OFFSET;
 
110
    mm_arena *arena = block->arena;
 
111
    MM_VCHECK(p)
 
112
    if (arena) {
 
113
      block->next_free = arena->next_free;
 
114
      arena->next_free = block;
 
115
      p_nsmall--;
 
116
    } else {
 
117
      free(block);
 
118
    }
 
119
    p_nfrees++;
 
120
  }
 
121
}
 
122
 
 
123
static mm_block *
 
124
expand_arena(mm_arena *arena)
 
125
{
 
126
  long n = arena->n_blocks;
 
127
  long size = sizeof(mm_block)*(n+1);
 
128
  mm_block *block = (void *)malloc(size);
 
129
  if (!block) return p_mmfail(size);
 
130
  block[0].next_free = arena->blocks;
 
131
  arena->blocks = block++;
 
132
  p_asmall += size;
 
133
  for (size=arena->size ; n-=size ; block+=size)
 
134
    block->next_free = block + size;
 
135
  block->next_free = 0;
 
136
  return (arena->next_free = arena->blocks+1);
 
137
}
 
138
 
 
139
static void *
 
140
brealloc(void *p, size_t n)
 
141
{
 
142
  if (p) {
 
143
    mm_block *block = ((mm_block *)p) - MM_OFFSET;
 
144
    mm_arena *arena = block->arena;
 
145
    MM_CHECK(p, n<=0? 1 : n)
 
146
    if (arena) {
 
147
      mm_block *new_block;
 
148
      long i, old_n = arena->size-MM_EXTRA;
 
149
      if (n <= sizeof(mm_block)*old_n) {
 
150
        MM_GUARD(block, n)
 
151
        return p;
 
152
      }
 
153
      new_block = bmalloc(n);
 
154
      if (!new_block) return p_mmfail(n<=0? 1 : n);
 
155
      for (i=0 ; i<old_n ; i++) new_block[i] = block[i+MM_OFFSET];
 
156
      block->next_free = arena->next_free;
 
157
      arena->next_free = block;
 
158
      p_nfrees++;
 
159
      return new_block;
 
160
    } else {
 
161
      /* don't bother trying to put shrinking blocks back into
 
162
       * the small block arenas */
 
163
      if (n<=0) n = 1;
 
164
      block = (void *)realloc(block, MM_EXTRA*sizeof(mm_block)+n);
 
165
      if (!block) return p_mmfail(n);
 
166
      MM_GUARD(block, n)
 
167
      return block+MM_OFFSET;
 
168
    }
 
169
  } else {
 
170
    return bmalloc(n);
 
171
  }
 
172
}
 
173
 
 
174
#ifdef P_DEBUG
 
175
/* provide primitive checking for memory overrun and underrun
 
176
 * checked on every free or realloc operation, or p_mmcheck can
 
177
 * be called anytime by debugger or debugging code */
 
178
 
 
179
static mm_block ur_pattern;
 
180
static char *pattern = 0;
 
181
 
 
182
void
 
183
p_mmguard(void *b, unsigned long n)
 
184
{
 
185
  mm_block *block = b;
 
186
  char *p = (char *)&block[2];
 
187
  int i;
 
188
  if (!pattern) {
 
189
    pattern = (char *)&ur_pattern;
 
190
    for (i=0 ; i<sizeof(mm_block) ; i++) pattern[i] = 255-i;
 
191
  }
 
192
  block[1].l = n;
 
193
  for (i=0 ; i<sizeof(mm_block) ; i++) p[i] = pattern[i];
 
194
  p += sizeof(mm_block)+n;
 
195
  for (i=0 ; i<sizeof(mm_block) ; i++) p[i] = pattern[i];
 
196
}
 
197
 
 
198
int
 
199
p_mmcheck(void *p)
 
200
{
 
201
  mm_block *block = p;
 
202
  char *chk = (char *)&block[-1];
 
203
  unsigned long n = block[-2].l;
 
204
  int i;
 
205
  for (i=0 ; i<sizeof(mm_block) ; i++) if (chk[i]!=pattern[i]) break;
 
206
  if (i<sizeof(mm_block)) return 1;  /* signal memory underrun */
 
207
  chk += sizeof(mm_block)+n;
 
208
  for (i=0 ; i<sizeof(mm_block) ; i++) if (chk[i]!=pattern[i]) break;
 
209
  if (i<sizeof(mm_block)) return 2;  /* signal memory overrun */
 
210
  return 0;
 
211
}
 
212
#endif