diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-04 12:15:05 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-04 12:15:05 +0000 |
commit | 46651ce6fe013220ed397add242004d764fc0153 (patch) | |
tree | 6e5299f990f88e60174a1d3ae6e48eedd2688b2b /src/interfaces/ecpg/ecpglib/memory.c | |
parent | Initial commit. (diff) | |
download | postgresql-14-upstream.tar.xz postgresql-14-upstream.zip |
Adding upstream version 14.5.upstream/14.5upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/interfaces/ecpg/ecpglib/memory.c')
-rw-r--r-- | src/interfaces/ecpg/ecpglib/memory.c | 174 |
1 files changed, 174 insertions, 0 deletions
diff --git a/src/interfaces/ecpg/ecpglib/memory.c b/src/interfaces/ecpg/ecpglib/memory.c new file mode 100644 index 0000000..bd81251 --- /dev/null +++ b/src/interfaces/ecpg/ecpglib/memory.c @@ -0,0 +1,174 @@ +/* src/interfaces/ecpg/ecpglib/memory.c */ + +#define POSTGRES_ECPG_INTERNAL +#include "postgres_fe.h" + +#include "ecpg-pthread-win32.h" +#include "ecpgerrno.h" +#include "ecpglib.h" +#include "ecpglib_extern.h" +#include "ecpgtype.h" + +void +ecpg_free(void *ptr) +{ + free(ptr); +} + +char * +ecpg_alloc(long size, int lineno) +{ + char *new = (char *) calloc(1L, size); + + if (!new) + { + ecpg_raise(lineno, ECPG_OUT_OF_MEMORY, ECPG_SQLSTATE_ECPG_OUT_OF_MEMORY, NULL); + return NULL; + } + + return new; +} + +char * +ecpg_realloc(void *ptr, long size, int lineno) +{ + char *new = (char *) realloc(ptr, size); + + if (!new) + { + ecpg_raise(lineno, ECPG_OUT_OF_MEMORY, ECPG_SQLSTATE_ECPG_OUT_OF_MEMORY, NULL); + return NULL; + } + + return new; +} + +char * +ecpg_strdup(const char *string, int lineno) +{ + char *new; + + if (string == NULL) + return NULL; + + new = strdup(string); + if (!new) + { + ecpg_raise(lineno, ECPG_OUT_OF_MEMORY, ECPG_SQLSTATE_ECPG_OUT_OF_MEMORY, NULL); + return NULL; + } + + return new; +} + +/* keep a list of memory we allocated for the user */ +struct auto_mem +{ + void *pointer; + struct auto_mem *next; +}; + +#ifdef ENABLE_THREAD_SAFETY +static pthread_key_t auto_mem_key; +static pthread_once_t auto_mem_once = PTHREAD_ONCE_INIT; + +static void +auto_mem_destructor(void *arg) +{ + (void) arg; /* keep the compiler quiet */ + ECPGfree_auto_mem(); +} + +static void +auto_mem_key_init(void) +{ + pthread_key_create(&auto_mem_key, auto_mem_destructor); +} + +static struct auto_mem * +get_auto_allocs(void) +{ + pthread_once(&auto_mem_once, auto_mem_key_init); + return (struct auto_mem *) pthread_getspecific(auto_mem_key); +} + +static void +set_auto_allocs(struct auto_mem *am) +{ + pthread_setspecific(auto_mem_key, am); +} +#else +static struct auto_mem *auto_allocs = NULL; + +#define get_auto_allocs() (auto_allocs) +#define set_auto_allocs(am) do { auto_allocs = (am); } while(0) +#endif + +char * +ecpg_auto_alloc(long size, int lineno) +{ + void *ptr = (void *) ecpg_alloc(size, lineno); + + if (!ptr) + return NULL; + + if (!ecpg_add_mem(ptr, lineno)) + { + ecpg_free(ptr); + return NULL; + } + return ptr; +} + +bool +ecpg_add_mem(void *ptr, int lineno) +{ + struct auto_mem *am = (struct auto_mem *) ecpg_alloc(sizeof(struct auto_mem), lineno); + + if (!am) + return false; + + am->pointer = ptr; + am->next = get_auto_allocs(); + set_auto_allocs(am); + return true; +} + +void +ECPGfree_auto_mem(void) +{ + struct auto_mem *am = get_auto_allocs(); + + /* free all memory we have allocated for the user */ + if (am) + { + do + { + struct auto_mem *act = am; + + am = am->next; + ecpg_free(act->pointer); + ecpg_free(act); + } while (am); + set_auto_allocs(NULL); + } +} + +void +ecpg_clear_auto_mem(void) +{ + struct auto_mem *am = get_auto_allocs(); + + /* only free our own structure */ + if (am) + { + do + { + struct auto_mem *act = am; + + am = am->next; + ecpg_free(act); + } while (am); + set_auto_allocs(NULL); + } +} |