1/* Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
2
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; version 2 of the License.
6
7 This program is distributed in the hope that it will be useful,
8 but WITHOUT ANY WARRANTY; without even the implied warranty of
9 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 GNU General Public License for more details.
11
12 You should have received a copy of the GNU General Public License
13 along with this program; if not, write to the Free Software
14 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
15
16/* Not MT-SAFE */
17
18#include "mysys_priv.h"
19#include "my_static.h"
20#include "mysys_err.h"
21#include <m_string.h>
22
23/*
24 Alloc for things we don't nend to free run-time (that only
25 should be free'd on exit)
26
27 SYNOPSIS
28 my_once_alloc()
29 Size
30 MyFlags
31
32 NOTES
33 No DBUG_ENTER... here to get smaller dbug-startup
34*/
35
36void* my_once_alloc(size_t Size, myf MyFlags)
37{
38 size_t get_size, max_left;
39 uchar* point;
40 reg1 USED_MEM *next;
41 reg2 USED_MEM **prev;
42
43 Size= ALIGN_SIZE(Size);
44 prev= &my_once_root_block;
45 max_left=0;
46 for (next=my_once_root_block ; next && next->left < Size ; next= next->next)
47 {
48 if (next->left > max_left)
49 max_left=next->left;
50 prev= &next->next;
51 }
52 if (! next)
53 { /* Time to alloc new block */
54 get_size= Size+ALIGN_SIZE(sizeof(USED_MEM));
55 if (max_left*4 < my_once_extra && get_size < my_once_extra)
56 get_size=my_once_extra; /* Normal alloc */
57
58 if ((next = (USED_MEM*) malloc(get_size)) == 0)
59 {
60 my_errno=errno;
61 if (MyFlags & (MY_FAE+MY_WME))
62 my_error(EE_OUTOFMEMORY, MYF(ME_BELL+ME_WAITTANG+ME_FATALERROR), get_size);
63 return((uchar*) 0);
64 }
65 DBUG_PRINT("test",("my_once_malloc %lu byte malloced", (ulong) get_size));
66 next->next= 0;
67 next->size= get_size;
68 next->left= get_size-ALIGN_SIZE(sizeof(USED_MEM));
69 *prev=next;
70 }
71 point= (uchar*) ((char*) next+ (next->size-next->left));
72 next->left-= Size;
73
74 if (MyFlags & MY_ZEROFILL)
75 bzero(point, Size);
76 return((void*) point);
77} /* my_once_alloc */
78
79
80char *my_once_strdup(const char *src,myf myflags)
81{
82 size_t len= strlen(src)+1;
83 uchar *dst= my_once_alloc(len, myflags);
84 if (dst)
85 memcpy(dst, src, len);
86 return (char*) dst;
87}
88
89
90void *my_once_memdup(const void *src, size_t len, myf myflags)
91{
92 uchar *dst= my_once_alloc(len, myflags);
93 if (dst)
94 memcpy(dst, src, len);
95 return dst;
96}
97
98
99/*
100 Deallocate everything that was allocated with my_once_alloc
101
102 SYNOPSIS
103 my_once_free()
104*/
105
106void my_once_free(void)
107{
108 reg1 USED_MEM *next,*old;
109 DBUG_ENTER("my_once_free");
110
111 for (next=my_once_root_block ; next ; )
112 {
113 old=next; next= next->next ;
114 free((uchar*) old);
115 }
116 my_once_root_block=0;
117
118 DBUG_VOID_RETURN;
119} /* my_once_free */
120