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 "ecpgtype.h"
8 #include "ecpglib.h"
9 #include "ecpgerrno.h"
10 #include "extern.h"
11
12 void
ecpg_free(void * ptr)13 ecpg_free(void *ptr)
14 {
15 free(ptr);
16 }
17
18 char *
ecpg_alloc(long size,int lineno)19 ecpg_alloc(long size, int lineno)
20 {
21 char *new = (char *) calloc(1L, size);
22
23 if (!new)
24 {
25 ecpg_raise(lineno, ECPG_OUT_OF_MEMORY, ECPG_SQLSTATE_ECPG_OUT_OF_MEMORY, NULL);
26 return NULL;
27 }
28
29 return new;
30 }
31
32 char *
ecpg_realloc(void * ptr,long size,int lineno)33 ecpg_realloc(void *ptr, long size, int lineno)
34 {
35 char *new = (char *) realloc(ptr, size);
36
37 if (!new)
38 {
39 ecpg_raise(lineno, ECPG_OUT_OF_MEMORY, ECPG_SQLSTATE_ECPG_OUT_OF_MEMORY, NULL);
40 return NULL;
41 }
42
43 return new;
44 }
45
46 char *
ecpg_strdup(const char * string,int lineno)47 ecpg_strdup(const char *string, int lineno)
48 {
49 char *new;
50
51 if (string == NULL)
52 return NULL;
53
54 new = strdup(string);
55 if (!new)
56 {
57 ecpg_raise(lineno, ECPG_OUT_OF_MEMORY, ECPG_SQLSTATE_ECPG_OUT_OF_MEMORY, NULL);
58 return NULL;
59 }
60
61 return new;
62 }
63
64 /* keep a list of memory we allocated for the user */
65 struct auto_mem
66 {
67 void *pointer;
68 struct auto_mem *next;
69 };
70
71 #ifdef ENABLE_THREAD_SAFETY
72 static pthread_key_t auto_mem_key;
73 static pthread_once_t auto_mem_once = PTHREAD_ONCE_INIT;
74
75 static void
auto_mem_destructor(void * arg)76 auto_mem_destructor(void *arg)
77 {
78 (void) arg; /* keep the compiler quiet */
79 ECPGfree_auto_mem();
80 }
81
82 static void
auto_mem_key_init(void)83 auto_mem_key_init(void)
84 {
85 pthread_key_create(&auto_mem_key, auto_mem_destructor);
86 }
87
88 static struct auto_mem *
get_auto_allocs(void)89 get_auto_allocs(void)
90 {
91 pthread_once(&auto_mem_once, auto_mem_key_init);
92 return (struct auto_mem *) pthread_getspecific(auto_mem_key);
93 }
94
95 static void
set_auto_allocs(struct auto_mem * am)96 set_auto_allocs(struct auto_mem *am)
97 {
98 pthread_setspecific(auto_mem_key, am);
99 }
100 #else
101 static struct auto_mem *auto_allocs = NULL;
102
103 #define get_auto_allocs() (auto_allocs)
104 #define set_auto_allocs(am) do { auto_allocs = (am); } while(0)
105 #endif
106
107 char *
ecpg_auto_alloc(long size,int lineno)108 ecpg_auto_alloc(long size, int lineno)
109 {
110 void *ptr = (void *) ecpg_alloc(size, lineno);
111
112 if (!ptr)
113 return NULL;
114
115 if (!ecpg_add_mem(ptr, lineno))
116 {
117 ecpg_free(ptr);
118 return NULL;
119 }
120 return ptr;
121 }
122
123 bool
ecpg_add_mem(void * ptr,int lineno)124 ecpg_add_mem(void *ptr, int lineno)
125 {
126 struct auto_mem *am = (struct auto_mem *) ecpg_alloc(sizeof(struct auto_mem), lineno);
127
128 if (!am)
129 return false;
130
131 am->pointer = ptr;
132 am->next = get_auto_allocs();
133 set_auto_allocs(am);
134 return true;
135 }
136
137 void
ECPGfree_auto_mem(void)138 ECPGfree_auto_mem(void)
139 {
140 struct auto_mem *am = get_auto_allocs();
141
142 /* free all memory we have allocated for the user */
143 if (am)
144 {
145 do
146 {
147 struct auto_mem *act = am;
148
149 am = am->next;
150 ecpg_free(act->pointer);
151 ecpg_free(act);
152 } while (am);
153 set_auto_allocs(NULL);
154 }
155 }
156
157 void
ecpg_clear_auto_mem(void)158 ecpg_clear_auto_mem(void)
159 {
160 struct auto_mem *am = get_auto_allocs();
161
162 /* only free our own structure */
163 if (am)
164 {
165 do
166 {
167 struct auto_mem *act = am;
168
169 am = am->next;
170 ecpg_free(act);
171 } while (am);
172 set_auto_allocs(NULL);
173 }
174 }
175