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 "ecpglib_extern.h"
11
12void
13ecpg_free(void *ptr)
14{
15 free(ptr);
16}
17
18char *
19ecpg_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
32char *
33ecpg_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
46char *
47ecpg_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 */
65struct auto_mem
66{
67 void *pointer;
68 struct auto_mem *next;
69};
70
71#ifdef ENABLE_THREAD_SAFETY
72static pthread_key_t auto_mem_key;
73static pthread_once_t auto_mem_once = PTHREAD_ONCE_INIT;
74
75static void
76auto_mem_destructor(void *arg)
77{
78 (void) arg; /* keep the compiler quiet */
79 ECPGfree_auto_mem();
80}
81
82static void
83auto_mem_key_init(void)
84{
85 pthread_key_create(&auto_mem_key, auto_mem_destructor);
86}
87
88static struct auto_mem *
89get_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
95static void
96set_auto_allocs(struct auto_mem *am)
97{
98 pthread_setspecific(auto_mem_key, am);
99}
100#else
101static 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
107char *
108ecpg_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
123bool
124ecpg_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
137void
138ECPGfree_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
157void
158ecpg_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