~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to mysys/my_alloc.cc

  • Committer: Jay Pipes
  • Date: 2009-09-21 14:33:44 UTC
  • mfrom: (1126.10.26 dtrace-probes)
  • mto: This revision was merged to the branch mainline in revision 1133.
  • Revision ID: jpipes@serialcoder-20090921143344-jnarp7gcn6zmg19c
Merge fixes from Trond and Padraig on dtrace probes.

Show diffs side-by-side

added added

removed removed

Lines of Context:
15
15
 
16
16
/* Routines to handle mallocing of results which will be freed the same time */
17
17
 
18
 
#include "config.h"
19
 
 
20
 
#include "drizzled/internal/my_sys.h"
21
 
#include "drizzled/internal/m_string.h"
 
18
#include "mysys/mysys_priv.h"
 
19
#include <mystrings/m_string.h>
22
20
 
23
21
#include <algorithm>
24
22
 
25
23
using namespace std;
26
24
 
27
 
namespace drizzled
28
 
{
29
 
 
30
 
static const unsigned int MAX_BLOCK_TO_DROP= 4096;
31
 
static const unsigned int MAX_BLOCK_USAGE_BEFORE_DROP= 10;
32
 
 
33
25
/*
34
26
  Initialize memory root
35
27
 
36
28
  SYNOPSIS
37
 
    memory::init_alloc_root()
 
29
    init_alloc_root()
38
30
      mem_root       - memory root to initialize
39
31
      block_size     - size of chunks (blocks) used for memory allocation
40
32
                       (It is external size of chunk i.e. it should include
41
33
                        memory required for internal structures, thus it
42
 
                        should be no less than memory::ROOT_MIN_BLOCK_SIZE)
 
34
                        should be no less than ALLOC_ROOT_MIN_BLOCK_SIZE)
 
35
      pre_alloc_size - if non-0, then size of block that should be
 
36
                       pre-allocated during memory root initialization.
43
37
 
44
38
  DESCRIPTION
45
39
    This function prepares memory root for further use, sets initial size of
49
43
    reported as error in first alloc_root() on this memory root.
50
44
*/
51
45
 
52
 
void memory::init_alloc_root(memory::Root *mem_root, size_t block_size)
 
46
void init_alloc_root(MEM_ROOT *mem_root, size_t block_size,
 
47
                     size_t )
53
48
{
54
49
  mem_root->free= mem_root->used= mem_root->pre_alloc= 0;
55
50
  mem_root->min_malloc= 32;
56
 
  mem_root->block_size= block_size - memory::ROOT_MIN_BLOCK_SIZE;
 
51
  mem_root->block_size= block_size - ALLOC_ROOT_MIN_BLOCK_SIZE;
57
52
  mem_root->error_handler= 0;
58
53
  mem_root->block_num= 4;                       /* We shift this with >>2 */
59
54
  mem_root->first_block_usage= 0;
79
74
    before allocation.
80
75
*/
81
76
 
82
 
void memory::reset_root_defaults(memory::Root *mem_root, size_t block_size,
83
 
                                 size_t pre_alloc_size)
 
77
void reset_root_defaults(MEM_ROOT *mem_root, size_t block_size,
 
78
                         size_t pre_alloc_size)
84
79
{
85
80
  assert(alloc_root_inited(mem_root));
86
81
 
87
 
  mem_root->block_size= block_size - memory::ROOT_MIN_BLOCK_SIZE;
 
82
  mem_root->block_size= block_size - ALLOC_ROOT_MIN_BLOCK_SIZE;
88
83
  if (pre_alloc_size)
89
84
  {
90
 
    size_t size= pre_alloc_size + ALIGN_SIZE(sizeof(memory::internal::UsedMemory));
 
85
    size_t size= pre_alloc_size + ALIGN_SIZE(sizeof(USED_MEM));
91
86
    if (!mem_root->pre_alloc || mem_root->pre_alloc->size != size)
92
87
    {
93
 
      memory::internal::UsedMemory *mem, **prev= &mem_root->free;
 
88
      USED_MEM *mem, **prev= &mem_root->free;
94
89
      /*
95
90
        Free unused blocks, so that consequent calls
96
91
        to reset_root_defaults won't eat away memory.
104
99
          mem_root->pre_alloc= mem;
105
100
          return;
106
101
        }
107
 
        if (mem->left + ALIGN_SIZE(sizeof(memory::internal::UsedMemory)) == mem->size)
 
102
        if (mem->left + ALIGN_SIZE(sizeof(USED_MEM)) == mem->size)
108
103
        {
109
104
          /* remove block from the list and free it */
110
105
          *prev= mem->next;
114
109
          prev= &mem->next;
115
110
      }
116
111
      /* Allocate new prealloc block and add it to the end of free list */
117
 
      if ((mem= static_cast<memory::internal::UsedMemory *>(malloc(size))))
 
112
      if ((mem= (USED_MEM *) malloc(size)))
118
113
      {
119
114
        mem->size= size;
120
115
        mem->left= pre_alloc_size;
134
129
}
135
130
 
136
131
 
137
 
void *memory::alloc_root(memory::Root *mem_root, size_t length)
 
132
void *alloc_root(MEM_ROOT *mem_root, size_t length)
138
133
{
139
134
  size_t get_size, block_size;
140
135
  unsigned char* point;
141
 
  memory::internal::UsedMemory *next= NULL;
142
 
  memory::internal::UsedMemory **prev;
 
136
  register USED_MEM *next= 0;
 
137
  register USED_MEM **prev;
143
138
  assert(alloc_root_inited(mem_root));
144
139
 
145
140
  length= ALIGN_SIZE(length);
146
141
  if ((*(prev= &mem_root->free)) != NULL)
147
142
  {
148
143
    if ((*prev)->left < length &&
149
 
        mem_root->first_block_usage++ >= MAX_BLOCK_USAGE_BEFORE_DROP &&
150
 
        (*prev)->left < MAX_BLOCK_TO_DROP)
 
144
        mem_root->first_block_usage++ >= ALLOC_MAX_BLOCK_USAGE_BEFORE_DROP &&
 
145
        (*prev)->left < ALLOC_MAX_BLOCK_TO_DROP)
151
146
    {
152
147
      next= *prev;
153
148
      *prev= next->next;                        /* Remove block from list */
161
156
  if (! next)
162
157
  {                                             /* Time to alloc new block */
163
158
    block_size= mem_root->block_size * (mem_root->block_num >> 2);
164
 
    get_size= length+ALIGN_SIZE(sizeof(memory::internal::UsedMemory));
 
159
    get_size= length+ALIGN_SIZE(sizeof(USED_MEM));
165
160
    get_size= max(get_size, block_size);
166
161
 
167
 
    if (!(next = static_cast<memory::internal::UsedMemory *>(malloc(get_size))))
 
162
    if (!(next = (USED_MEM*) malloc(get_size)))
168
163
    {
169
164
      if (mem_root->error_handler)
170
165
        (*mem_root->error_handler)();
171
 
      return NULL;
 
166
      return((void*) 0);                      /* purecov: inspected */
172
167
    }
173
168
    mem_root->block_num++;
174
169
    next->next= *prev;
175
170
    next->size= get_size;
176
 
    next->left= get_size-ALIGN_SIZE(sizeof(memory::internal::UsedMemory));
 
171
    next->left= get_size-ALIGN_SIZE(sizeof(USED_MEM));
177
172
    *prev=next;
178
173
  }
179
174
 
209
204
    in case of success or NULL if out of memory.
210
205
*/
211
206
 
212
 
void *memory::multi_alloc_root(memory::Root *root, ...)
 
207
void *multi_alloc_root(MEM_ROOT *root, ...)
213
208
{
214
209
  va_list args;
215
210
  char **ptr, *start, *res;
224
219
  }
225
220
  va_end(args);
226
221
 
227
 
  if (!(start= (char*) memory::alloc_root(root, tot_length)))
228
 
    return(0);
 
222
  if (!(start= (char*) alloc_root(root, tot_length)))
 
223
    return(0);                            /* purecov: inspected */
229
224
 
230
225
  va_start(args, root);
231
226
  res= start;
243
238
 
244
239
/* Mark all data in blocks free for reusage */
245
240
 
246
 
static inline void mark_blocks_free(memory::Root* root)
 
241
static inline void mark_blocks_free(MEM_ROOT* root)
247
242
{
248
 
  memory::internal::UsedMemory *next;
249
 
  memory::internal::UsedMemory **last;
 
243
  register USED_MEM *next;
 
244
  register USED_MEM **last;
250
245
 
251
246
  /* iterate through (partially) free blocks, mark them free */
252
247
  last= &root->free;
253
248
  for (next= root->free; next; next= *(last= &next->next))
254
249
  {
255
 
    next->left= next->size - ALIGN_SIZE(sizeof(memory::internal::UsedMemory));
 
250
    next->left= next->size - ALIGN_SIZE(sizeof(USED_MEM));
256
251
    TRASH_MEM(next);
257
252
  }
258
253
 
262
257
  /* now go through the used blocks and mark them free */
263
258
  for (; next; next= next->next)
264
259
  {
265
 
    next->left= next->size - ALIGN_SIZE(sizeof(memory::internal::UsedMemory));
 
260
    next->left= next->size - ALIGN_SIZE(sizeof(USED_MEM));
266
261
    TRASH_MEM(next);
267
262
  }
268
263
 
273
268
 
274
269
 
275
270
/*
276
 
  Deallocate everything used by memory::alloc_root or just move
 
271
  Deallocate everything used by alloc_root or just move
277
272
  used blocks to free list if called with MY_USED_TO_FREE
278
273
 
279
274
  SYNOPSIS
281
276
      root              Memory root
282
277
      MyFlags           Flags for what should be freed:
283
278
 
284
 
        MARK_BLOCKS_FREED       Don't free blocks, just mark them free
285
 
        KEEP_PREALLOC           If this is not set, then free also the
 
279
        MY_MARK_BLOCKS_FREED    Don't free blocks, just mark them free
 
280
        MY_KEEP_PREALLOC        If this is not set, then free also the
286
281
                                preallocated block
287
282
 
288
283
  NOTES
291
286
    It's also safe to call this multiple times with the same mem_root.
292
287
*/
293
288
 
294
 
void memory::free_root(memory::Root *root, myf MyFlags)
 
289
void free_root(MEM_ROOT *root, myf MyFlags)
295
290
{
296
 
  memory::internal::UsedMemory *next,*old;
 
291
  register USED_MEM *next,*old;
297
292
 
298
 
  if (MyFlags & memory::MARK_BLOCKS_FREE)
 
293
  if (MyFlags & MY_MARK_BLOCKS_FREE)
299
294
  {
300
295
    mark_blocks_free(root);
301
296
    return;
302
297
  }
303
 
  if (!(MyFlags & memory::KEEP_PREALLOC))
 
298
  if (!(MyFlags & MY_KEEP_PREALLOC))
304
299
    root->pre_alloc=0;
305
300
 
306
301
  for (next=root->used; next ;)
319
314
  if (root->pre_alloc)
320
315
  {
321
316
    root->free=root->pre_alloc;
322
 
    root->free->left=root->pre_alloc->size-ALIGN_SIZE(sizeof(memory::internal::UsedMemory));
 
317
    root->free->left=root->pre_alloc->size-ALIGN_SIZE(sizeof(USED_MEM));
323
318
    TRASH_MEM(root->pre_alloc);
324
319
    root->free->next=0;
325
320
  }
332
327
  Find block that contains an object and set the pre_alloc to it
333
328
*/
334
329
 
335
 
void memory::set_prealloc_root(memory::Root *root, char *ptr)
 
330
void set_prealloc_root(MEM_ROOT *root, char *ptr)
336
331
{
337
 
  memory::internal::UsedMemory *next;
 
332
  USED_MEM *next;
338
333
  for (next=root->used; next ; next=next->next)
339
334
  {
340
335
    if ((char*) next <= ptr && (char*) next + next->size > ptr)
354
349
}
355
350
 
356
351
 
357
 
char *memory::strdup_root(memory::Root *root, const char *str)
 
352
char *strdup_root(MEM_ROOT *root, const char *str)
358
353
{
359
354
  return strmake_root(root, str, strlen(str));
360
355
}
361
356
 
362
357
 
363
 
char *memory::strmake_root(memory::Root *root, const char *str, size_t len)
 
358
char *strmake_root(MEM_ROOT *root, const char *str, size_t len)
364
359
{
365
360
  char *pos;
366
 
  if ((pos=(char *)memory::alloc_root(root,len+1)))
 
361
  if ((pos=(char *)alloc_root(root,len+1)))
367
362
  {
368
363
    memcpy(pos,str,len);
369
364
    pos[len]=0;
372
367
}
373
368
 
374
369
 
375
 
void *memory::memdup_root(memory::Root *root, const void *str, size_t len)
 
370
void *memdup_root(MEM_ROOT *root, const void *str, size_t len)
376
371
{
377
372
  void *pos;
378
 
  if ((pos=memory::alloc_root(root,len)))
 
373
  if ((pos=alloc_root(root,len)))
379
374
    memcpy(pos,str,len);
380
375
  return pos;
381
376
}
382
 
 
383
 
} /* namespace drizzled */