Line data Source code
1 : /* src/interfaces/ecpg/ecpglib/memory.c */ 2 : 3 : #define POSTGRES_ECPG_INTERNAL 4 : #include "postgres_fe.h" 5 : 6 : #include "ecpg-pthread-win32.h" 7 : #include "ecpgerrno.h" 8 : #include "ecpglib.h" 9 : #include "ecpglib_extern.h" 10 : #include "ecpgtype.h" 11 : 12 : void 13 6524754 : ecpg_free(void *ptr) 14 : { 15 6524754 : free(ptr); 16 6524754 : } 17 : 18 : char * 19 6466640 : ecpg_alloc(long size, int lineno) 20 : { 21 6466640 : char *new = (char *) calloc(1L, size); 22 : 23 6466640 : if (!new) 24 : { 25 0 : ecpg_raise(lineno, ECPG_OUT_OF_MEMORY, ECPG_SQLSTATE_ECPG_OUT_OF_MEMORY, NULL); 26 0 : return NULL; 27 : } 28 : 29 6466640 : return new; 30 : } 31 : 32 : char * 33 21300 : ecpg_realloc(void *ptr, long size, int lineno) 34 : { 35 21300 : char *new = (char *) realloc(ptr, size); 36 : 37 21300 : if (!new) 38 : { 39 0 : ecpg_raise(lineno, ECPG_OUT_OF_MEMORY, ECPG_SQLSTATE_ECPG_OUT_OF_MEMORY, NULL); 40 0 : return NULL; 41 : } 42 : 43 21300 : return new; 44 : } 45 : 46 : /* 47 : * Wrapper for strdup(), with NULL in input treated as a correct case. 48 : * 49 : * "alloc_failed" can be optionally specified by the caller to check for 50 : * allocation failures. The caller is responsible for its initialization, 51 : * as ecpg_strdup() may be called repeatedly across multiple allocations. 52 : */ 53 : char * 54 22576 : ecpg_strdup(const char *string, int lineno, bool *alloc_failed) 55 : { 56 : char *new; 57 : 58 22576 : if (string == NULL) 59 0 : return NULL; 60 : 61 22576 : new = strdup(string); 62 22576 : if (!new) 63 : { 64 0 : if (alloc_failed) 65 0 : *alloc_failed = true; 66 0 : ecpg_raise(lineno, ECPG_OUT_OF_MEMORY, ECPG_SQLSTATE_ECPG_OUT_OF_MEMORY, NULL); 67 0 : return NULL; 68 : } 69 : 70 22576 : return new; 71 : } 72 : 73 : /* keep a list of memory we allocated for the user */ 74 : struct auto_mem 75 : { 76 : void *pointer; 77 : struct auto_mem *next; 78 : }; 79 : 80 : static pthread_key_t auto_mem_key; 81 : static pthread_once_t auto_mem_once = PTHREAD_ONCE_INIT; 82 : 83 : static void 84 64 : auto_mem_destructor(void *arg) 85 : { 86 : (void) arg; /* keep the compiler quiet */ 87 64 : ECPGfree_auto_mem(); 88 64 : } 89 : 90 : static void 91 230 : auto_mem_key_init(void) 92 : { 93 230 : pthread_key_create(&auto_mem_key, auto_mem_destructor); 94 230 : } 95 : 96 : static struct auto_mem * 97 14834 : get_auto_allocs(void) 98 : { 99 14834 : pthread_once(&auto_mem_once, auto_mem_key_init); 100 14834 : return (struct auto_mem *) pthread_getspecific(auto_mem_key); 101 : } 102 : 103 : static void 104 6520 : set_auto_allocs(struct auto_mem *am) 105 : { 106 6520 : pthread_setspecific(auto_mem_key, am); 107 6520 : } 108 : 109 : char * 110 3344 : ecpg_auto_alloc(long size, int lineno) 111 : { 112 3344 : void *ptr = ecpg_alloc(size, lineno); 113 : 114 3344 : if (!ptr) 115 0 : return NULL; 116 : 117 3344 : if (!ecpg_add_mem(ptr, lineno)) 118 : { 119 0 : ecpg_free(ptr); 120 0 : return NULL; 121 : } 122 3344 : return ptr; 123 : } 124 : 125 : bool 126 3344 : ecpg_add_mem(void *ptr, int lineno) 127 : { 128 3344 : struct auto_mem *am = (struct auto_mem *) ecpg_alloc(sizeof(struct auto_mem), lineno); 129 : 130 3344 : if (!am) 131 0 : return false; 132 : 133 3344 : am->pointer = ptr; 134 3344 : am->next = get_auto_allocs(); 135 3344 : set_auto_allocs(am); 136 3344 : return true; 137 : } 138 : 139 : void 140 326 : ECPGfree_auto_mem(void) 141 : { 142 326 : struct auto_mem *am = get_auto_allocs(); 143 : 144 : /* free all memory we have allocated for the user */ 145 326 : if (am) 146 : { 147 : do 148 : { 149 80 : struct auto_mem *act = am; 150 : 151 80 : am = am->next; 152 80 : ecpg_free(act->pointer); 153 80 : ecpg_free(act); 154 80 : } while (am); 155 8 : set_auto_allocs(NULL); 156 : } 157 326 : } 158 : 159 : void 160 11164 : ecpg_clear_auto_mem(void) 161 : { 162 11164 : struct auto_mem *am = get_auto_allocs(); 163 : 164 : /* only free our own structure */ 165 11164 : if (am) 166 : { 167 : do 168 : { 169 3188 : struct auto_mem *act = am; 170 : 171 3188 : am = am->next; 172 3188 : ecpg_free(act); 173 3188 : } while (am); 174 3168 : set_auto_allocs(NULL); 175 : } 176 11164 : }