summaryrefslogtreecommitdiff
path: root/mysys/my_once.c
blob: d83eba95b9d450708692f15ebdfa86a52e8fa8a1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
/* Copyright (C) 2000 MySQL AB

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; version 2 of the License.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */

/* Not MT-SAFE */

#ifdef SAFEMALLOC			/* We don't need SAFEMALLOC here */
#undef SAFEMALLOC
#endif

#include "mysys_priv.h"
#include "my_static.h"
#include "mysys_err.h"
#include <m_string.h>

/*
  Alloc for things we don't nead to free

  SYNOPSIS
    my_once_alloc()
      Size
      MyFlags

  NOTES
    No DBUG_ENTER... here to get smaller dbug-startup 
*/

gptr my_once_alloc(unsigned int Size, myf MyFlags)
{
  uint get_size,max_left;
  gptr point;
  reg1 USED_MEM *next;
  reg2 USED_MEM **prev;

  Size= ALIGN_SIZE(Size);
  prev= &my_once_root_block;
  max_left=0;
  for (next=my_once_root_block ; next && next->left < Size ; next= next->next)
  {
    if (next->left > max_left)
      max_left=next->left;
    prev= &next->next;
  }
  if (! next)
  {						/* Time to alloc new block */
    get_size= Size+ALIGN_SIZE(sizeof(USED_MEM));
    if (max_left*4 < my_once_extra && get_size < my_once_extra)
      get_size=my_once_extra;			/* Normal alloc */

    if ((next = (USED_MEM*) malloc(get_size)) == 0)
    {
      my_errno=errno;
      if (MyFlags & (MY_FAE+MY_WME))
	my_error(EE_OUTOFMEMORY, MYF(ME_BELL+ME_WAITTANG),get_size);
      return((gptr) 0);
    }
    DBUG_PRINT("test",("my_once_malloc %u byte malloced",get_size));
    next->next= 0;
    next->size= get_size;
    next->left= get_size-ALIGN_SIZE(sizeof(USED_MEM));
    *prev=next;
  }
  point= (gptr) ((char*) next+ (next->size-next->left));
  next->left-= Size;

  return(point);
} /* my_once_alloc */


char *my_once_strdup(const char *src,myf myflags)
{
  uint len= (uint) strlen(src)+1;
  char *dst=my_once_alloc(len, myflags);
  if (dst)
    memcpy(dst, src, len);
  return dst;
}


char *my_once_memdup(const char *src, uint len, myf myflags)
{
  char *dst=my_once_alloc(len, myflags);
  if (dst)
    memcpy(dst, src, len);
  return dst;
}


/*
  Deallocate everything used by my_once_alloc

  SYNOPSIS
    my_once_free()
*/

void my_once_free(void)
{
  reg1 USED_MEM *next,*old;
  DBUG_ENTER("my_once_free");

  for (next=my_once_root_block ; next ; )
  {
    old=next; next= next->next ;
    free((gptr) old);
  }
  my_once_root_block=0;

  DBUG_VOID_RETURN;
} /* my_once_free */