summaryrefslogtreecommitdiff
path: root/src/third_party/wiredtiger/src/include/serial_inline.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/third_party/wiredtiger/src/include/serial_inline.h')
-rw-r--r--src/third_party/wiredtiger/src/include/serial_inline.h22
1 files changed, 20 insertions, 2 deletions
diff --git a/src/third_party/wiredtiger/src/include/serial_inline.h b/src/third_party/wiredtiger/src/include/serial_inline.h
index 12542c64ac9..52b6e7c2dd7 100644
--- a/src/third_party/wiredtiger/src/include/serial_inline.h
+++ b/src/third_party/wiredtiger/src/include/serial_inline.h
@@ -14,6 +14,7 @@ static inline int
__insert_simple_func(
WT_SESSION_IMPL *session, WT_INSERT ***ins_stack, WT_INSERT *new_ins, u_int skipdepth)
{
+ WT_INSERT *old_ins;
u_int i;
WT_UNUSED(session);
@@ -29,7 +30,15 @@ __insert_simple_func(
* implementations read the old value multiple times.
*/
for (i = 0; i < skipdepth; i++) {
- WT_INSERT *old_ins = *ins_stack[i];
+ /*
+ * The insert stack position must be read only once - if the compiler chooses to re-read the
+ * shared variable it could lead to skip list corruption. Specifically the comparison
+ * against the next pointer might indicate that the skip list location is still valid, but
+ * that may no longer be true when the atomic_cas operation executes.
+ *
+ * Place a read barrier here to avoid this issue.
+ */
+ WT_ORDERED_READ(old_ins, *ins_stack[i]);
if (old_ins != new_ins->next[i] || !__wt_atomic_cas_ptr(ins_stack[i], old_ins, new_ins))
return (i == 0 ? WT_RESTART : 0);
}
@@ -45,6 +54,7 @@ static inline int
__insert_serial_func(WT_SESSION_IMPL *session, WT_INSERT_HEAD *ins_head, WT_INSERT ***ins_stack,
WT_INSERT *new_ins, u_int skipdepth)
{
+ WT_INSERT *old_ins;
u_int i;
/* The cursor should be positioned. */
@@ -63,7 +73,15 @@ __insert_serial_func(WT_SESSION_IMPL *session, WT_INSERT_HEAD *ins_head, WT_INSE
* implementations read the old value multiple times.
*/
for (i = 0; i < skipdepth; i++) {
- WT_INSERT *old_ins = *ins_stack[i];
+ /*
+ * The insert stack position must be read only once - if the compiler chooses to re-read the
+ * shared variable it could lead to skip list corruption. Specifically the comparison
+ * against the next pointer might indicate that the skip list location is still valid, but
+ * that may no longer be true when the atomic_cas operation executes.
+ *
+ * Place a read barrier here to avoid this issue.
+ */
+ WT_ORDERED_READ(old_ins, *ins_stack[i]);
if (old_ins != new_ins->next[i] || !__wt_atomic_cas_ptr(ins_stack[i], old_ins, new_ins))
return (i == 0 ? WT_RESTART : 0);
if (ins_head->tail[i] == NULL || ins_stack[i] == &ins_head->tail[i]->next[i])