Branch data 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 : 3262827 : ecpg_free(void *ptr)
14 : : {
15 : 3262827 : free(ptr);
16 : 3262827 : }
17 : :
18 : : char *
19 : 3233552 : ecpg_alloc(long size, int lineno)
20 : : {
21 : 3233552 : char *new = (char *) calloc(1L, size);
22 : :
23 [ - + ]: 3233552 : 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 : 3233552 : return new;
30 : : }
31 : :
32 : : char *
33 : 10722 : ecpg_realloc(void *ptr, long size, int lineno)
34 : : {
35 : 10722 : char *new = (char *) realloc(ptr, size);
36 : :
37 [ - + ]: 10722 : 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 : 10722 : 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 : 11354 : ecpg_strdup(const char *string, int lineno, bool *alloc_failed)
55 : : {
56 : : char *new;
57 : :
58 [ - + ]: 11354 : if (string == NULL)
59 : 0 : return NULL;
60 : :
61 : 11354 : new = strdup(string);
62 [ - + ]: 11354 : 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 : 11354 : 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 : 32 : auto_mem_destructor(void *arg)
85 : : {
86 : : (void) arg; /* keep the compiler quiet */
87 : 32 : ECPGfree_auto_mem();
88 : 32 : }
89 : :
90 : : static void
91 : 119 : auto_mem_key_init(void)
92 : : {
93 : 119 : pthread_key_create(&auto_mem_key, auto_mem_destructor);
94 : 119 : }
95 : :
96 : : static struct auto_mem *
97 : 7477 : get_auto_allocs(void)
98 : : {
99 : 7477 : pthread_once(&auto_mem_once, auto_mem_key_init);
100 : 7477 : return (struct auto_mem *) pthread_getspecific(auto_mem_key);
101 : : }
102 : :
103 : : static void
104 : 3260 : set_auto_allocs(struct auto_mem *am)
105 : : {
106 : 3260 : pthread_setspecific(auto_mem_key, am);
107 : 3260 : }
108 : :
109 : : char *
110 : 1672 : ecpg_auto_alloc(long size, int lineno)
111 : : {
112 : 1672 : void *ptr = ecpg_alloc(size, lineno);
113 : :
114 [ - + ]: 1672 : if (!ptr)
115 : 0 : return NULL;
116 : :
117 [ - + ]: 1672 : if (!ecpg_add_mem(ptr, lineno))
118 : : {
119 : 0 : ecpg_free(ptr);
120 : 0 : return NULL;
121 : : }
122 : 1672 : return ptr;
123 : : }
124 : :
125 : : bool
126 : 1672 : ecpg_add_mem(void *ptr, int lineno)
127 : : {
128 : 1672 : struct auto_mem *am = (struct auto_mem *) ecpg_alloc(sizeof(struct auto_mem), lineno);
129 : :
130 [ - + ]: 1672 : if (!am)
131 : 0 : return false;
132 : :
133 : 1672 : am->pointer = ptr;
134 : 1672 : am->next = get_auto_allocs();
135 : 1672 : set_auto_allocs(am);
136 : 1672 : return true;
137 : : }
138 : :
139 : : void
140 : 177 : ECPGfree_auto_mem(void)
141 : : {
142 : 177 : struct auto_mem *am = get_auto_allocs();
143 : :
144 : : /* free all memory we have allocated for the user */
145 [ + + ]: 177 : if (am)
146 : : {
147 : : do
148 : : {
149 : 40 : struct auto_mem *act = am;
150 : :
151 : 40 : am = am->next;
152 : 40 : ecpg_free(act->pointer);
153 : 40 : ecpg_free(act);
154 [ + + ]: 40 : } while (am);
155 : 4 : set_auto_allocs(NULL);
156 : : }
157 : 177 : }
158 : :
159 : : void
160 : 5628 : ecpg_clear_auto_mem(void)
161 : : {
162 : 5628 : struct auto_mem *am = get_auto_allocs();
163 : :
164 : : /* only free our own structure */
165 [ + + ]: 5628 : if (am)
166 : : {
167 : : do
168 : : {
169 : 1594 : struct auto_mem *act = am;
170 : :
171 : 1594 : am = am->next;
172 : 1594 : ecpg_free(act);
173 [ + + ]: 1594 : } while (am);
174 : 1584 : set_auto_allocs(NULL);
175 : : }
176 : 5628 : }
|