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
|
/*-------------------------------------------------------------------------
*
* mspan.h
* Memory span management.
*
* Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* src/include/utils/mspan.h
*
*-------------------------------------------------------------------------
*/
#ifndef MSPAN_H
#define MSPAN_H
#include "utils/aspace_map.h"
/*
* Relative pointers.
*
* These are intended to be used when storing an address that may be
* relative either to the base of the processes address space or some
* dynamic shared memory segment mapped therein.
*
* The idea here is that you declare a relative pointer as relptr(type)
* and then use relptr_access to dereference it and relptr_store to change
* it. The use of a union here is a hack, because what's stored in the
* relptr is always a Size, never an actual pointer. But including a pointer
* in the union allows us to use stupid macro tricks to provide some measure
* of type-safety.
*/
#define relptr(type) union { type *relptr_type; Size relptr_off; }
#define relptr_access(base, rp) \
(AssertVariableIsOfTypeMacro(base, char *), \
(__typeof__((rp).relptr_type)) ((rp).relptr_off == 0 ? NULL : \
(base + (rp).relptr_off)))
#define relptr_is_null(rp) \
((rp).relptr_off == 0)
#define relptr_store(base, rp, val) \
(AssertVariableIsOfTypeMacro(base, char *), \
AssertVariableIsOfTypeMacro(val, __typeof__((rp).relptr_type)), \
(rp).relptr_off = ((val) == NULL ? 0 : ((char *) (val)) - (base)))
/*
* Flags that can be associated with memory allocations.
*/
#define MSPAN_ALLOW_HUGE 0x0001 /* allow allocations > 1 GB */
#define MSPAN_SOFT_FAIL 0x0002 /* return NULL on failure */
/*
* Large objects - and the superblocks used to satisfy smaller allocations -
* are allocated from free lists. Each free list except the last holds
* available spans of one particular size; the final free list holds all
* the remaining ones.
*/
#define MSPAN_NUM_FREE_LISTS 256
/* Forward declarations. */
struct mspan;
struct mspan_context;
struct mspan_manager;
typedef struct mspan mspan;
typedef struct mspan_context mspan_context;
typedef struct mspan_manager mspan_manager;
/*
* One mspan_manager is needed for each allocation space. This means that
* we have one for our own address space, which is stored in a static variable;
* and one for each dynamic shared memory segment in which we want to use
* this facility, which should be stored within that segment.
*/
struct mspan_manager
{
Size npages; /* # of managed pages in dsm; 0 for private */
Size base; /* offset of page 0 within dsm; 0 for private */
Size boundary; /* first unallocated page in dsm; 0 for private */
Size ncontexts; /* # of outstanding contexts */
Size nsyschunks; /* # of chunks allocated from OS */
relptr(mspan) span_of_spans; /* superblock for span descriptors */
relptr(mspan_context) freecontext; /* allocatable context object */
aspace_map page_map; /* map pages to mspans */
relptr(mspan) freelist[MSPAN_NUM_FREE_LISTS]; /* spans for freespace */
};
/* Manager for backend-private address space. */
extern mspan_manager private_mspan_manager;
/* Initialization a manager in private or dynamic shared memory. */
extern void mspan_initialize_private_manager(mspan_manager *);
extern mspan_manager *mspan_initialize_dsm_manager(dsm_segment *,
void *, Size nbytes);
/* Create or destroy a memory context. */
extern mspan_context *mspan_context_create(dsm_segment *, mspan_manager *);
extern void mspan_context_destroy(dsm_segment *, mspan_context *);
/* Allocate or free memory. */
extern void *mspan_alloc(dsm_segment *, mspan_context *, Size size, int flags);
extern void *mspan_free(dsm_segment *, void *);
#endif
|