diff options
Diffstat (limited to 'src/third_party/wiredtiger/src/include/serial_inline.h')
-rw-r--r-- | src/third_party/wiredtiger/src/include/serial_inline.h | 22 |
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]) |