xref: /dpdk/doc/guides/prog_guide/stack_lib.rst (revision 443b949e17953a1094f80532d600a1ee540f2ba4)
105d3b528SGage Eads..  SPDX-License-Identifier: BSD-3-Clause
205d3b528SGage Eads    Copyright(c) 2019 Intel Corporation.
305d3b528SGage Eads
405d3b528SGage EadsStack Library
505d3b528SGage Eads=============
605d3b528SGage Eads
705d3b528SGage EadsDPDK's stack library provides an API for configuration and use of a bounded
805d3b528SGage Eadsstack of pointers.
905d3b528SGage Eads
1005d3b528SGage EadsThe stack library provides the following basic operations:
1105d3b528SGage Eads
1205d3b528SGage Eads*  Create a uniquely named stack of a user-specified size and using a
133340202fSGage Eads   user-specified socket, with either standard (lock-based) or lock-free
143340202fSGage Eads   behavior.
1505d3b528SGage Eads
1605d3b528SGage Eads*  Push and pop a burst of one or more stack objects (pointers). These function
1705d3b528SGage Eads   are multi-threading safe.
1805d3b528SGage Eads
1905d3b528SGage Eads*  Free a previously created stack.
2005d3b528SGage Eads
2105d3b528SGage Eads*  Lookup a pointer to a stack by its name.
2205d3b528SGage Eads
2305d3b528SGage Eads*  Query a stack's current depth and number of free entries.
2405d3b528SGage Eads
2505d3b528SGage EadsImplementation
2605d3b528SGage Eads~~~~~~~~~~~~~~
2705d3b528SGage Eads
283340202fSGage EadsThe library supports two types of stacks: standard (lock-based) and lock-free.
293340202fSGage EadsBoth types use the same set of interfaces, but their implementations differ.
303340202fSGage Eads
311fb6301cSGage Eads.. _Stack_Library_Std_Stack:
321fb6301cSGage Eads
333340202fSGage EadsLock-based Stack
343340202fSGage Eads----------------
353340202fSGage Eads
363340202fSGage EadsThe lock-based stack consists of a contiguous array of pointers, a current
373340202fSGage Eadsindex, and a spinlock. Accesses to the stack are made multi-thread safe by the
383340202fSGage Eadsspinlock.
393340202fSGage Eads
401fb6301cSGage Eads.. _Stack_Library_LF_Stack:
411fb6301cSGage Eads
423340202fSGage EadsLock-free Stack
433340202fSGage Eads------------------
443340202fSGage Eads
453340202fSGage EadsThe lock-free stack consists of a linked list of elements, each containing a
463340202fSGage Eadsdata pointer and a next pointer, and an atomic stack depth counter. The
473340202fSGage Eadslock-free property means that multiple threads can push and pop simultaneously,
483340202fSGage Eadsand one thread being preempted/delayed in a push or pop operation will not
493340202fSGage Eadsimpede the forward progress of any other thread.
503340202fSGage Eads
513340202fSGage EadsThe lock-free push operation enqueues a linked list of pointers by pointing the
523340202fSGage Eadslist's tail to the current stack head, and using a CAS to swing the stack head
533340202fSGage Eadspointer to the head of the list. The operation retries if it is unsuccessful
543340202fSGage Eads(i.e. the list changed between reading the head and modifying it), else it
553340202fSGage Eadsadjusts the stack length and returns.
563340202fSGage Eads
573340202fSGage EadsThe lock-free pop operation first reserves one or more list elements by
583340202fSGage Eadsadjusting the stack length, to ensure the dequeue operation will succeed
593340202fSGage Eadswithout blocking. It then dequeues pointers by walking the list -- starting
603340202fSGage Eadsfrom the head -- then swinging the head pointer (using a CAS as well). While
613340202fSGage Eadswalking the list, the data pointers are recorded in an object table.
623340202fSGage Eads
633340202fSGage EadsThe linked list elements themselves are maintained in a lock-free LIFO, and are
643340202fSGage Eadsallocated before stack pushes and freed after stack pops. Since the stack has a
653340202fSGage Eadsfixed maximum depth, these elements do not need to be dynamically created.
663340202fSGage Eads
673340202fSGage EadsThe lock-free behavior is selected by passing the *RTE_STACK_F_LF* flag to
683340202fSGage Eadsrte_stack_create().
693340202fSGage Eads
703340202fSGage EadsPreventing the ABA Problem
713340202fSGage Eads^^^^^^^^^^^^^^^^^^^^^^^^^^
723340202fSGage Eads
733340202fSGage EadsTo prevent the ABA problem, this algorithm stack uses a 128-bit
743340202fSGage Eadscompare-and-swap instruction to atomically update both the stack top pointer
753340202fSGage Eadsand a modification counter. The ABA problem can occur without a modification
763340202fSGage Eadscounter if, for example:
773340202fSGage Eads
78*443b949eSDavid Marchand#. Thread A reads head pointer X and stores the pointed-to list element.
79*443b949eSDavid Marchand
80*443b949eSDavid Marchand#. Other threads modify the list such that the head pointer is once again X,
813340202fSGage Eads   but its pointed-to data is different than what thread A read.
82*443b949eSDavid Marchand
83*443b949eSDavid Marchand#. Thread A changes the head pointer with a compare-and-swap and succeeds.
843340202fSGage Eads
853340202fSGage EadsIn this case thread A would not detect that the list had changed, and would
863340202fSGage Eadsboth pop stale data and incorrect change the head pointer. By adding a
873340202fSGage Eadsmodification counter that is updated on every push and pop as part of the
883340202fSGage Eadscompare-and-swap, the algorithm can detect when the list changes even if the
893340202fSGage Eadshead pointer remains the same.
90