1PMEMOBJ_ACTION(3) PMDK Programmer's Manual PMEMOBJ_ACTION(3)
2
3
4
6 pmemobj_reserve(), pmemobj_xreserve(), pmemobj_defer_free(), pmemo‐
7 bj_set_value(), pmemobj_publish(), pmemobj_tx_publish(), pmemo‐
8 bj_tx_xpublish(), pmemobj_cancel(), POBJ_RESERVE_NEW(), POBJ_RE‐
9 SERVE_ALLOC(), POBJ_XRESERVE_NEW(),POBJ_XRESERVE_ALLOC() - Delayed
10 atomicity actions (EXPERIMENTAL)
11
13 #include <libpmemobj.h>
14
15 PMEMoid pmemobj_reserve(PMEMobjpool *pop, struct pobj_action *act,
16 size_t size, uint64_t type_num); (EXPERIMENTAL)
17 PMEMoid pmemobj_xreserve(PMEMobjpool *pop, struct pobj_action *act,
18 size_t size, uint64_t type_num, uint64_t flags); (EXPERIMENTAL)
19 void pmemobj_defer_free(PMEMobjpool *pop, PMEMoid oid, struct pobj_action *act);
20 void pmemobj_set_value(PMEMobjpool *pop, struct pobj_action *act,
21 uint64_t *ptr, uint64_t value); (EXPERIMENTAL)
22 int pmemobj_publish(PMEMobjpool *pop, struct pobj_action *actv,
23 size_t actvcnt); (EXPERIMENTAL)
24 int pmemobj_tx_publish(struct pobj_action *actv, size_t actvcnt); (EXPERIMENTAL)
25 int pmemobj_tx_xpublish(struct pobj_action *actv, size_t actvcnt, uint64_t flags); (EXPERIMENTAL)
26 void pmemobj_cancel(PMEMobjpool *pop, struct pobj_action *actv,
27 size_t actvcnt); (EXPERIMENTAL)
28
29 POBJ_RESERVE_NEW(pop, t, act) (EXPERIMENTAL)
30 POBJ_RESERVE_ALLOC(pop, t, size, act) (EXPERIMENTAL)
31 POBJ_XRESERVE_NEW(pop, t, act, flags) (EXPERIMENTAL)
32 POBJ_XRESERVE_ALLOC(pop, t, size, act, flags) (EXPERIMENTAL)
33
35 All of the functions described so far have an immediate effect on the
36 persistent state of the pool, and as such, the cost of maintaining
37 fail-safety is paid outright and, most importantly, in the calling
38 thread. This behavior makes implementing algorithms involving relaxed
39 consistency guarantees difficult, if not outright impossible.
40
41 The following set of functions introduce a mechanism that allows one to
42 delay the persistent publication of a set of prepared actions to an ar‐
43 bitrary moment in time of the execution of a program.
44
45 The publication is fail-safe atomic in the scope of the entire collec‐
46 tion of actions. If a program exits without publishing the actions, or
47 the actions are canceled, any resources reserved by those actions are
48 released and placed back in the pool.
49
50 A single action is represented by a single struct pobj_action. Func‐
51 tions that create actions take that structure by pointer, whereas func‐
52 tions that publish actions take array of actions and the size of the
53 array. The actions can be created, and published, from different
54 threads. When creating actions, the act argument must be non-NULL and
55 point to a struct pobj_action, the structure will be populated by the
56 function and must not be modified or deallocated until after publish‐
57 ing.
58
59 The pmemobj_reserve() functions performs a transient reservation of an
60 object. Behaves similarly to pmemobj_alloc(3), but performs no modifi‐
61 cation to the persistent state. The object returned by this function
62 can be freely modified without worrying about fail-safe atomicity until
63 the object has been published. Any modifications of the object must be
64 manually persisted, just like in the case of the atomic API.
65
66 pmemobj_xreserve() is equivalent to pmemobj_reserve(), but with an ad‐
67 ditional flags argument that is a bitmask of the following values:
68
69 • POBJ_XALLOC_ZERO - zero the allocated object (and persist it)
70
71 • POBJ_CLASS_ID(class_id) - allocate an object from the allocation
72 class class_id. The class id cannot be 0.
73
74 • POBJ_ARENA_ID(arena_id) - allocate an object from the arena specified
75 by arena_id. The arena must exist, otherwise, the behavior is unde‐
76 fined. If arena_id is equal 0, then arena assigned to the current
77 thread will be used.
78
79 pmemobj_defer_free() function creates a deferred free action, meaning
80 that the provided object will be freed when the action is published.
81 Calling this function with a NULL OID is invalid and causes undefined
82 behavior.
83
84 The pmemobj_set_value function prepares an action that, once published,
85 will modify the memory location pointed to by ptr to value.
86
87 The pmemobj_publish function publishes the provided set of actions.
88 The publication is fail-safe atomic. Once done, the persistent state
89 will reflect the changes contained in the actions.
90
91 The pmemobj_tx_publish function moves the provided actions to the scope
92 of the transaction in which it is called. Only object reservations are
93 supported in transactional publish. Once done, the reserved objects
94 will follow normal transactional semantics. Can only be called during
95 TX_STAGE_WORK.
96
97 The pmemobj_tx_xpublish() function behaves exactly the same as pmemo‐
98 bj_tx_publish() when flags equals zero. flags is a bitmask of the fol‐
99 lowing values:
100
101 • POBJ_XPUBLISH_NO_ABORT - if the function does not end successfully,
102 do not abort the transaction.
103
104 The pmemobj_cancel function releases any resources held by the provided
105 set of actions and invalidates all actions.
106
107 The POBJ_RESERVE_NEW macro is a typed variant of pmemobj_reserve. The
108 size of the reservation is determined from the provided type t.
109
110 The POBJ_RESERVE_ALLOC macro is a typed variant of pmemobj_reserve.
111 The size of the reservation is user-provided.
112
113 The POBJ_XRESERVE_NEW and the POBJ_XRESERVE_ALLOC macros are equivalent
114 to POBJ_RESERVE_NEW and the POBJ_RESERVE_ALLOC, but with an additional
115 flags argument defined for pmemobj_xreserve().
116
118 The following code shows atomic append of two objects into a singly
119 linked list.
120
121 struct list_node {
122 int value;
123 PMEMoid next;
124 };
125 /* statically allocate the array of actions */
126 struct pobj_action actv[4];
127
128 /* reserve, populate and persist the first object */
129 PMEMoid tail = pmemobj_reserve(pop, &actv[0], sizeof(struct list_node), 0);
130 if (TOID_IS_NULL(tail))
131 return -1;
132 D_RW(tail)->value = 1;
133 D_RW(tail)->next = OID_NULL;
134 pmemobj_persist(pop, D_RW(tail), sizeof(struct list_node));
135
136 /* reserve, populate and persist the second object */
137 PMEMoid head = pmemobj_reserve(pop, &actv[1], sizeof(struct list_node), 0);
138 if (TOID_IS_NULL(head))
139 return -1;
140 D_RW(head)->value = 2;
141 D_RW(head)->next = tail;
142 pmemobj_persist(pop, D_RW(head), sizeof(struct list_node));
143
144 /* create actions to set the PMEMoid to the new values */
145 pmemobj_set_value(pop, &actv[2], &D_RO(root)->head.pool_uuid_lo, head.pool_uuid_lo);
146 pmemobj_set_value(pop, &actv[3], &D_RO(root)->head.off, head.off);
147
148 /* atomically publish the above actions */
149 pmemobj_publish(pop, actv, 4);
150
152 On success, pmemobj_reserve() functions return a handle to the newly
153 reserved object. Otherwise an OID_NULL is returned.
154
155 On success, pmemobj_tx_publish() returns 0. Otherwise, the transaction
156 is aborted, the stage is changed to TX_STAGE_ONABORT and errno is set
157 appropriately.
158
159 On success, pmemobj_tx_xpublish() returns 0. Otherwise, the error num‐
160 ber is returned, errno is set and when flags do not contain POBJ_XPUB‐
161 LISH_NO_ABORT, the transaction is aborted.
162
163 On success, pmemobj_publish() returns 0. Otherwise, returns -1 and er‐
164 rno is set appropriately.
165
167 pmemobj_alloc(3), pmemobj_tx_alloc(3), libpmemobj(7) and
168 <https://pmem.io>
169
170
171
172PMDK - pmemobj API version 2.3 2022-05-24 PMEMOBJ_ACTION(3)