1() PMDK Programmer's Manual ()
2
3
4
6 OID_IS_NULL(), OID_EQUALS(), pmemobj_direct(), pmemobj_oid(), pmemo‐
7 bj_type_num(), pmemobj_pool_by_oid(), pmemobj_pool_by_ptr() - functions
8 that allow mapping operations between object addresses, object handles,
9 oids or type numbers
10
12 #include <libpmemobj.h>
13
14 OID_IS_NULL(PMEMoid oid)
15 OID_EQUALS(PMEMoid lhs, PMEMoid rhs)
16
17 void *pmemobj_direct(PMEMoid oid);
18 PMEMoid pmemobj_oid(const void *addr);
19 uint64_t pmemobj_type_num(PMEMoid oid);
20 PMEMobjpool *pmemobj_pool_by_oid(PMEMoid oid);
21 PMEMobjpool *pmemobj_pool_by_ptr(const void *addr);
22 void *pmemobj_volatile(PMEMobjpool *pop, struct pmemvlt *vlt,
23 size_t size, void *ptr,
24 int (*constr)(void *ptr, void *arg), void *arg); (EXPERIMENTAL)
25
27 Each object stored in a persistent memory pool is represented by an ob‐
28 ject handle of type PMEMoid. In practice, such a handle is a unique
29 Object IDentifier (OID) of global scope, which means that two objects
30 from different pools will never have the same OID. The special
31 OID_NULL macro defines a NULL-like handle that does not represent any
32 object. The size of a single object is limited by PMEMOBJ_MAX_AL‐
33 LOC_SIZE. Thus an allocation with a requested size greater than this
34 value will fail.
35
36 An OID cannot be used as a direct pointer to an object. Each time the
37 program attempts to read or write object data, it must obtain the cur‐
38 rent memory address of the object by converting its OID into a pointer.
39
40 In contrast to the memory address, the OID value for given object does
41 not change during the life of an object (except for realloc), and re‐
42 mains valid after closing and reopening the pool. For this reason, if
43 an object contains a reference to another persistent object, for exam‐
44 ple, to build some kind of a linked data structure, the reference must
45 be an OID and not a memory address.
46
47 pmemobj_direct() returns a pointer to the PMEMoid object with handle
48 oid.
49
50 pmemobj_oid() returns a PMEMoid handle to the object pointed to by ad‐
51 dr.
52
53 pmemobj_type_num() returns the type number of the PMEMoid object with
54 handle oid.
55
56 pmemobj_pool_by_oid() returns a PMEMobjpool* handle to the pool con‐
57 taining the PMEMoid object with handle oid.
58
59 pmemobj_pool_by_ptr() returns a PMEMobjpool* handle to the pool con‐
60 taining the address addr.
61
62 At the time of allocation (or reallocation), each object may be as‐
63 signed a number representing its type. Such a type number may be used
64 to arrange the persistent objects based on their actual user-defined
65 structure type, thus facilitating implementation of a simple run-time
66 type safety mechanism. This also allows iterating through all the ob‐
67 jects of a given type that are stored in the persistent memory pool.
68 See pmemobj_first(3) for more information.
69
70 The OID_IS_NULL() macro checks if PMEMoid represents a NULL object.
71
72 The OID_EQUALS() macro compares two PMEMoid objects.
73
74 For special cases where volatile (transient) variables need to be
75 stored on persistent memory, there’s a mechanism composed of struct
76 pmemvlt type and pmemobj_volatile() function. To use it, the struct
77 pmemvlt needs to be placed in the neighborhood of transient data re‐
78 gion. The PMEMvlt macro can be used to construct such a region. The
79 struct pmemvlt must be zeroed prior to use. This can be easily done in
80 object constructor or in a transaction directly after an allocation.
81 When the pmemobj_volatile() function is called on a struct pmemvlt, it
82 will return the pointer to the data and it will ensure that the provid‐
83 ed constructor function is called exactly once in the current instance
84 of the pmemobj pool. The constructor is called with the ptr pointer to
85 the data, and this function will return the same pointer if the con‐
86 structor returns 0, otherwise NULL is returned. The size argument must
87 accurately describe the total size of the volatile memory region that
88 will be accessed. Calling pmemobj_volatile() on the same region with
89 different sizes is undefined behavior. For this mechanism to be effec‐
90 tive, all accesses to transient variables must go through it, otherwise
91 there’s a risk of the constructor not being called on the first load.
92 Maintaining transient state on persistent memory is challenging due to
93 difficulties with dynamic resources acquisition and subsequent resource
94 release. For example, one needs to consider what happens with volatile
95 state of an object which is being freed inside of a transaction, espe‐
96 cially with regards to the possibility of an abort. It’s generally
97 recommended to entirely separate the persistent and transient states,
98 and when it’s not possible, to only store types which do not require
99 lifecycle management (i.e., primitive types) inside of volatile re‐
100 gions.
101
103 The pmemobj_direct() function returns a pointer to the object repre‐
104 sented by oid. If oid is OID_NULL, pmemobj_direct() returns NULL.
105
106 The pmemobj_oid() function returns a PMEMoid handle to the object
107 pointed to by addr. If addr is not from within a pmemobj pool,
108 OID_NULL is returned. If addr is not the start of an object (does not
109 point to the beginning of a valid allocation), the resulting PMEMoid
110 can be safely used only with:
111
112 • pmemobj_pool_by_oid()
113
114 • pmemobj_direct()
115
116 • pmemobj_tx_add_range(3)
117
118 The pmemobj_type_num() function returns the type number of the object
119 represented by oid.
120
121 The pmemobj_pool_by_oid() function returns a handle to the pool that
122 contains the object represented by oid. If the pool is not open or oid
123 is OID_NULL, pmemobj_pool_by_oid() returns NULL.
124
125 The pmemobj_pool_by_ptr() function returns a handle to the pool that
126 contains the address, or NULL if the address does not belong to any
127 open pool.
128
130 For performance reasons, on Linux and FreeBSD the pmemobj_direct()
131 function is inlined by default. To use the non-inlined variant of
132 pmemobj_direct(), define PMEMOBJ_DIRECT_NON_INLINE prior to the #in‐
133 clude of <libpmemobj.h>, either with #define or with the -D option to
134 the compiler.
135
137 The following code shows how to store transient variables on persistent
138 memory.
139
140 struct my_data {
141 PMEMvlt(uint64_t) foo;
142 uint64_t bar;
143 };
144
145 int
146 my_data_constructor(void *ptr, void *arg)
147 {
148 uint64_t *foo = ptr;
149 *foo = 0;
150
151 return 0;
152 }
153
154 PMEMobjpool *pop = ...;
155
156 struct my_data *data = D_RW(...);
157
158 uint64_t *foo = pmemobj_volatile(pop, &data->foo.vlt, &data->foo.value,
159 my_data_constructor, NULL);
160
161 assert(*foo == 0);
162
164 libpmemobj(7) and <https://pmem.io>
165
166
167
168PMDK - 2023-06-05 ()