YAZ 5.35.1
nmem.c
Go to the documentation of this file.
1/* This file is part of the YAZ toolkit.
2 * Copyright (C) Index Data
3 * See the file LICENSE for details.
4 */
5
14#if HAVE_CONFIG_H
15#include <config.h>
16#endif
17
18#include <assert.h>
19#include <stdlib.h>
20#include <string.h>
21#include <errno.h>
22#include <stddef.h>
23#include <yaz/xmalloc.h>
24#include <yaz/nmem.h>
25#include <yaz/log.h>
26#include <yaz/snprintf.h>
27
28#if YAZ_POSIX_THREADS
29#include <pthread.h>
30#endif
31
32#if YAZ_POSIX_THREADS
33static pthread_mutex_t nmem_mutex = PTHREAD_MUTEX_INITIALIZER;
34#endif
35static size_t no_nmem_handles = 0;
36static size_t no_nmem_blocks = 0;
37static size_t nmem_allocated = 0;
38
39#define NMEM_CHUNK (4*1024)
40
42{
43 char *buf; /* memory allocated in this block */
44 size_t size; /* size of buf */
45 size_t top; /* top of buffer */
47};
48
50{
51 size_t total;
54};
55
56struct align {
57 char x;
58 union {
59 char c;
60 short s;
61 int i;
62 long l;
63#if HAVE_LONG_LONG
64 long long ll;
65#endif
66 float f;
67 double d;
68 } u;
69};
70
71#define NMEM_ALIGN (offsetof(struct align, u))
72
73static int log_level = 0;
74static int log_level_initialized = 0;
75
76static void nmem_lock(void)
77{
78#if YAZ_POSIX_THREADS
79 pthread_mutex_lock(&nmem_mutex);
80#endif
81}
82
83static void nmem_unlock(void)
84{
85#if YAZ_POSIX_THREADS
86 pthread_mutex_unlock(&nmem_mutex);
87#endif
88}
89
90static void free_block(struct nmem_block *p)
91{
92 nmem_lock();
94 nmem_allocated -= p->size;
96 xfree(p->buf);
97 xfree(p);
98 if (log_level)
99 yaz_log(log_level, "nmem free_block p=%p", p);
100}
101
102/*
103 * acquire a block with a minimum of size free bytes.
104 */
105static struct nmem_block *get_block(size_t size)
106{
107 struct nmem_block *r;
108 size_t get = NMEM_CHUNK;
109
110 if (log_level)
111 yaz_log(log_level, "nmem get_block size=%ld", (long) size);
112
113 if (get < size)
114 get = size;
115 if (log_level)
116 yaz_log(log_level, "nmem get_block alloc new block size=%ld",
117 (long) get);
118
119 r = (struct nmem_block *) xmalloc(sizeof(*r));
120 r->buf = (char *)xmalloc(r->size = get);
121 r->top = 0;
122 nmem_lock();
124 nmem_allocated += r->size;
125 nmem_unlock();
126 return r;
127}
128
130{
131 struct nmem_block *t;
132
133 yaz_log(log_level, "nmem_reset p=%p", n);
134 if (!n)
135 return;
136 while (n->blocks)
137 {
138 t = n->blocks;
139 n->blocks = n->blocks->next;
140 free_block(t);
141 }
142 n->total = 0;
143}
144
145void *nmem_malloc(NMEM n, size_t size)
146{
147 struct nmem_block *p;
148 char *r;
149
150 if (!n)
151 {
152 yaz_log(YLOG_FATAL, "calling nmem_malloc with an null pointer");
153 abort();
154 }
155 p = n->blocks;
156 if (!p || p->size < size + p->top)
157 {
158 p = get_block(size);
159 p->next = n->blocks;
160 n->blocks = p;
161 }
162 r = p->buf + p->top;
163 /* align size */
164 p->top += (size + (NMEM_ALIGN - 1)) & ~(NMEM_ALIGN - 1);
165 n->total += size;
166 return r;
167}
168
170{
171 return n->total;
172}
173
175{
176#if YAZ_POSIX_THREADS
177 pthread_atfork(nmem_lock, nmem_unlock, nmem_unlock);
178#endif
179}
180
182{
183 NMEM r;
184
185 nmem_lock();
187 nmem_unlock();
189 {
190 /* below will call nmem_init_globals once */
193 }
194
195 r = (struct nmem_control *)xmalloc(sizeof(*r));
196
197 r->blocks = 0;
198 r->total = 0;
199 r->next = 0;
200
201 return r;
202}
203
205{
206 if (!n)
207 return;
208
209 nmem_reset(n);
210 xfree(n);
211 nmem_lock();
213 nmem_unlock();
214}
215
216void nmem_transfer(NMEM dst, NMEM src)
217{
218 struct nmem_block *t;
219 while ((t = src->blocks))
220 {
221 src->blocks = t->next;
222 t->next = dst->blocks;
223 dst->blocks = t;
224 }
225 dst->total += src->total;
226 src->total = 0;
227}
228
229int nmem_get_status(char *dst, size_t l)
230{
231 size_t handles, blocks, allocated;
232
233 nmem_lock();
234 handles = no_nmem_handles;
235 blocks = no_nmem_blocks;
236 allocated = nmem_allocated;
237 nmem_unlock();
238 yaz_snprintf(dst, l,
239 "<nmem>\n"
240 " <handles>%zd</handles>\n"
241 " <blocks>%zd</blocks>\n"
242 " <allocated>%zd</allocated>\n"
243 "</nmem>\n", handles, blocks, allocated);
244 return 0;
245}
246/*
247 * Local variables:
248 * c-basic-offset: 4
249 * c-file-style: "Stroustrup"
250 * indent-tabs-mode: nil
251 * End:
252 * vim: shiftwidth=4 tabstop=8 expandtab
253 */
254
Header for errno utilities.
void yaz_log(int level, const char *fmt,...)
Writes log message.
Definition log.c:487
int yaz_log_module_level(const char *name)
returns level for module
Definition log.c:586
Logging utility.
#define YLOG_FATAL
log level: fatal
Definition log.h:42
void nmem_init_globals(void)
Definition nmem.c:174
void nmem_transfer(NMEM dst, NMEM src)
transfers memory from one NMEM handle to another
Definition nmem.c:216
static void free_block(struct nmem_block *p)
Definition nmem.c:90
static struct nmem_block * get_block(size_t size)
Definition nmem.c:105
static size_t no_nmem_blocks
Definition nmem.c:36
static void nmem_lock(void)
Definition nmem.c:76
static size_t nmem_allocated
Definition nmem.c:37
static size_t no_nmem_handles
Definition nmem.c:35
void nmem_reset(NMEM n)
releases memory associaged with an NMEM handle
Definition nmem.c:129
int nmem_get_status(char *dst, size_t l)
returns memory status for NMEM - as XML
Definition nmem.c:229
#define NMEM_CHUNK
Definition nmem.c:39
static void nmem_unlock(void)
Definition nmem.c:83
static int log_level
Definition nmem.c:73
NMEM nmem_create(void)
returns new NMEM handle
Definition nmem.c:181
size_t nmem_total(NMEM n)
returns size in bytes of memory for NMEM handle
Definition nmem.c:169
void * nmem_malloc(NMEM n, size_t size)
allocates memory block on NMEM handle
Definition nmem.c:145
static int log_level_initialized
Definition nmem.c:74
#define NMEM_ALIGN
Definition nmem.c:71
void nmem_destroy(NMEM n)
destroys NMEM handle and memory associated with it
Definition nmem.c:204
Header for Nibble Memory functions.
void yaz_snprintf(char *buf, size_t size, const char *fmt,...)
Definition snprintf.c:31
Header for config file reading utilities.
Definition nmem.c:56
double d
Definition nmem.c:67
float f
Definition nmem.c:66
long l
Definition nmem.c:62
union align::@6 u
int i
Definition nmem.c:61
char c
Definition nmem.c:59
char x
Definition nmem.c:57
short s
Definition nmem.c:60
size_t top
Definition nmem.c:45
size_t size
Definition nmem.c:44
struct nmem_block * next
Definition nmem.c:46
char * buf
Definition nmem.c:43
struct nmem_control * next
Definition nmem.c:53
struct nmem_block * blocks
Definition nmem.c:52
size_t total
Definition nmem.c:51
Header for memory handling functions.
#define xfree(x)
utility macro which calls xfree_f
Definition xmalloc.h:53
#define xmalloc(x)
utility macro which calls malloc_f
Definition xmalloc.h:49