summaryrefslogtreecommitdiff
path: root/lib/resource.h
blob: 810334c14264fca43c24aa6df25ffb12ba1448bc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
/*
 *	BIRD Resource Manager
 *
 *	(c) 1998--1999 Martin Mares <mj@ucw.cz>
 *	(c) 2021 Maria Matejka <mq@jmq.cz>
 *
 *	Can be freely distributed and used under the terms of the GNU GPL.
 */

#ifndef _BIRD_RESOURCE_H_
#define _BIRD_RESOURCE_H_

#include "lib/locking.h"
#include "lib/tlists.h"

#include <stdarg.h>

struct resmem {
  size_t effective;			/* Memory actually used for data storage */
  size_t overhead;			/* Overhead memory imposed by allocator strategies */
};

/* Resource */

#define TLIST_PREFIX resource
#define TLIST_TYPE struct resource
#define TLIST_ITEM n
#define TLIST_WANT_WALK
#define TLIST_WANT_ADD_TAIL
#define TLIST_WANT_UPDATE_NODE

typedef struct resource {
  TLIST_DEFAULT_NODE;			/* Inside resource pool */
  const struct resclass *class;		/* Resource class */
} resource;

#include "lib/tlists.h"

/* Resource class */

struct resclass {
  char *name;				/* Resource class name */
  unsigned size;			/* Standard size of single resource */
  void (*free)(resource *);		/* Freeing function */
  void (*dump)(resource *, unsigned indent);		/* Dump to debug output */
  resource *(*lookup)(resource *, unsigned long);	/* Look up address (only for debugging) */
  struct resmem (*memsize)(resource *);	/* Return size of memory used by the resource, may be NULL */
};

/* Estimate of system allocator overhead per item, for memory consumtion stats */
#define ALLOC_OVERHEAD		16

/* Generic resource manipulation */

typedef struct pool {
  resource r;
  TLIST_LIST(resource) inside;
  struct domain_generic *domain;
  const char *name;
} pool;


void resource_init(void);
void rfree(void *);			/* Free single resource */
void rdump(void *, unsigned indent);	/* Dump to debug output */
struct resmem rmemsize(void *res);		/* Return size of memory used by the resource */
void rlookup(unsigned long);		/* Look up address (only for debugging) */
void rmove(void *, pool *);		/* Move to a different pool */

void *ralloc(pool *, struct resclass *);

pool *rp_new(pool *, struct domain_generic *, const char *);		/* Create a new pool */
pool *rp_newf(pool *, struct domain_generic *, const char *, ...);	/* Create a new pool with a formatted string as its name */
pool *rp_vnewf(pool *, struct domain_generic *, const char *, va_list);	/* Create a new pool with a formatted string as its name */
void rp_free(pool *p);							/* Free the whole pool */

extern pool root_pool;

/* Normal memory blocks */

void *mb_alloc(pool *, unsigned size);
void *mb_allocz(pool *, unsigned size);
void *mb_realloc(void *m, unsigned size);
void mb_free(void *);

/* Memory pools with linear allocation */

typedef struct linpool linpool;

typedef struct lp_state {
  void *current, *large;
  byte *ptr;
  uint total_large;
} lp_state;

linpool *lp_new(pool *);
void *lp_alloc(linpool *, unsigned size);	/* Aligned */
void *lp_allocu(linpool *, unsigned size);	/* Unaligned */
void *lp_allocz(linpool *, unsigned size);	/* With clear */
void lp_flush(linpool *);			/* Free everything, but leave linpool */
void lp_save(linpool *m, lp_state *p);		/* Save state */
void lp_restore(linpool *m, lp_state *p);	/* Restore state */

struct tmp_resources {
  pool *pool, *parent;
  linpool *lp;
  struct domain_generic *domain;
};

extern _Thread_local struct tmp_resources tmp_res;

#define tmp_linpool	tmp_res.lp
#define tmp_alloc(sz)	lp_alloc(tmp_linpool, sz)
#define tmp_allocu(sz)	lp_allocu(tmp_linpool, sz)
#define tmp_allocz(sz)	lp_allocz(tmp_linpool, sz)

void tmp_init(pool *p, struct domain_generic *dg);
void tmp_flush(void);


#define lp_new_default	lp_new

/* Slabs */

typedef struct slab slab;

slab *sl_new(pool *, unsigned size);
void *sl_alloc(slab *);
void *sl_allocz(slab *);
void sl_free(void *);
void sl_delete(slab *);

/*
 * Low-level memory allocation functions, please don't use
 * outside resource manager and possibly sysdep code.
 */

void buffer_realloc(void **buf, unsigned *size, unsigned need, unsigned item_size);

/* Allocator of whole pages; for use in slabs and other high-level allocators. */
#define PAGE_HEAD(x)	((void *) (((uintptr_t) (x)) & ~(page_size-1)))
extern long page_size;
extern _Atomic int pages_kept;
extern _Atomic int pages_kept_locally;
void *alloc_page(void);
void free_page(void *);
void flush_local_pages(void);

void resource_sys_init(void);

#ifdef HAVE_LIBDMALLOC
/*
 * The standard dmalloc macros tend to produce lots of namespace
 * conflicts and we use only xmalloc, xrealloc and xfree, so we
 * can define the stubs ourselves.
 */
#define DMALLOC_DISABLE
#include <dmalloc.h>
#define xmalloc(size) \
  dmalloc_malloc(__FILE__, __LINE__, (size), DMALLOC_FUNC_MALLOC, 0, 1)
#define xrealloc(ptr, size) \
  dmalloc_realloc(__FILE__, __LINE__, (ptr), (size), DMALLOC_FUNC_REALLOC, 1)
#define xfree(ptr) \
  dmalloc_free(__FILE__, __LINE__, (ptr), DMALLOC_FUNC_FREE)

#else
/*
 * Unfortunately, several libraries we might want to link to define
 * their own xmalloc and we don't want to interfere with them, hence
 * the renaming.
 */
#define xmalloc bird_xmalloc
#define xrealloc bird_xrealloc
void *xmalloc(unsigned);
void *xrealloc(void *, unsigned);
#define xfree(x) free(x)
#endif

#endif