TLA 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 CBC 1630905 : ecpg_free(void *ptr)
14 : {
15 1630905 : free(ptr);
16 1630905 : }
17 :
18 : char *
19 1616542 : ecpg_alloc(long size, int lineno)
20 : {
21 1616542 : char *new = (char *) calloc(1L, size);
22 :
23 1616542 : if (!new)
24 : {
25 UBC 0 : ecpg_raise(lineno, ECPG_OUT_OF_MEMORY, ECPG_SQLSTATE_ECPG_OUT_OF_MEMORY, NULL);
26 0 : return NULL;
27 : }
28 :
29 CBC 1616542 : return new;
30 : }
31 :
32 : char *
33 5325 : ecpg_realloc(void *ptr, long size, int lineno)
34 : {
35 5325 : char *new = (char *) realloc(ptr, size);
36 :
37 5325 : if (!new)
38 : {
39 UBC 0 : ecpg_raise(lineno, ECPG_OUT_OF_MEMORY, ECPG_SQLSTATE_ECPG_OUT_OF_MEMORY, NULL);
40 0 : return NULL;
41 : }
42 :
43 CBC 5325 : return new;
44 : }
45 :
46 : char *
47 5591 : ecpg_strdup(const char *string, int lineno)
48 : {
49 : char *new;
50 :
51 5591 : if (string == NULL)
52 UBC 0 : return NULL;
53 :
54 CBC 5591 : new = strdup(string);
55 5591 : if (!new)
56 : {
57 UBC 0 : ecpg_raise(lineno, ECPG_OUT_OF_MEMORY, ECPG_SQLSTATE_ECPG_OUT_OF_MEMORY, NULL);
58 0 : return NULL;
59 : }
60 :
61 CBC 5591 : 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
76 16 : auto_mem_destructor(void *arg)
77 : {
78 : (void) arg; /* keep the compiler quiet */
79 16 : ECPGfree_auto_mem();
80 16 : }
81 :
82 : static void
83 56 : auto_mem_key_init(void)
84 : {
85 56 : pthread_key_create(&auto_mem_key, auto_mem_destructor);
86 56 : }
87 :
88 : static struct auto_mem *
89 3662 : get_auto_allocs(void)
90 : {
91 3662 : pthread_once(&auto_mem_once, auto_mem_key_init);
92 3662 : return (struct auto_mem *) pthread_getspecific(auto_mem_key);
93 : }
94 :
95 : static void
96 1630 : set_auto_allocs(struct auto_mem *am)
97 : {
98 1630 : pthread_setspecific(auto_mem_key, am);
99 1630 : }
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 *
108 836 : ecpg_auto_alloc(long size, int lineno)
109 : {
110 836 : void *ptr = (void *) ecpg_alloc(size, lineno);
111 :
112 836 : if (!ptr)
113 UBC 0 : return NULL;
114 :
115 CBC 836 : if (!ecpg_add_mem(ptr, lineno))
116 : {
117 UBC 0 : ecpg_free(ptr);
118 0 : return NULL;
119 : }
120 CBC 836 : return ptr;
121 : }
122 :
123 : bool
124 836 : ecpg_add_mem(void *ptr, int lineno)
125 : {
126 836 : struct auto_mem *am = (struct auto_mem *) ecpg_alloc(sizeof(struct auto_mem), lineno);
127 :
128 836 : if (!am)
129 UBC 0 : return false;
130 :
131 CBC 836 : am->pointer = ptr;
132 836 : am->next = get_auto_allocs();
133 836 : set_auto_allocs(am);
134 836 : return true;
135 : }
136 :
137 : void
138 70 : ECPGfree_auto_mem(void)
139 : {
140 70 : struct auto_mem *am = get_auto_allocs();
141 :
142 : /* free all memory we have allocated for the user */
143 70 : if (am)
144 : {
145 : do
146 : {
147 20 : struct auto_mem *act = am;
148 :
149 20 : am = am->next;
150 20 : ecpg_free(act->pointer);
151 20 : ecpg_free(act);
152 20 : } while (am);
153 2 : set_auto_allocs(NULL);
154 : }
155 70 : }
156 :
157 : void
158 2756 : ecpg_clear_auto_mem(void)
159 : {
160 2756 : struct auto_mem *am = get_auto_allocs();
161 :
162 : /* only free our own structure */
163 2756 : if (am)
164 : {
165 : do
166 : {
167 797 : struct auto_mem *act = am;
168 :
169 797 : am = am->next;
170 797 : ecpg_free(act);
171 797 : } while (am);
172 792 : set_auto_allocs(NULL);
173 : }
174 2756 : }
|