| 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 | |
| 36 | void* 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 | |
| 80 | char *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 | |
| 90 | void *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 | |
| 106 | void 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 | |