1 /* SPDX-License-Identifier: BSD-3-Clause */
2 /* Copyright(c) 2007-2026 Intel Corporation */
3 #ifndef LAC_LOCK_FREE_STACK_H_1
4 #define LAC_LOCK_FREE_STACK_H_1
5 #include "lac_mem_pools.h"
6
7 #ifdef __LP64__
8 typedef unsigned int atomic_int __attribute__((mode(TI)));
9 #else
10 typedef unsigned int atomic_int __attribute__((mode(DI)));
11 #endif
12
13 typedef union {
14 struct {
15 unsigned long ctr;
16 void *ptr;
17 };
18 atomic_int atomic;
19 } pointer_t;
20
21 typedef struct {
22 volatile pointer_t top;
23 } lock_free_stack_t;
24
25 static inline char
lac_atomic_cmp_swap(volatile pointer_t * ptr,pointer_t old_val,pointer_t new_val)26 lac_atomic_cmp_swap(volatile pointer_t *ptr,
27 pointer_t old_val,
28 pointer_t new_val)
29 {
30 uint64_t new_high, new_low, old_high, old_low;
31 char res;
32
33 old_low = old_val.ctr;
34 old_high = (uintptr_t)old_val.ptr;
35 new_low = new_val.ctr;
36 new_high = (uintptr_t)new_val.ptr;
37
38 __asm volatile("lock;cmpxchg16b\t%1"
39 : "=@cce"(res), "+m"(*ptr), "+a"(old_low), "+d"(old_high)
40 : "b"(new_low), "c"(new_high)
41 : "memory", "cc");
42 return (res);
43 }
44
45 static inline lac_mem_blk_t *
pop(lock_free_stack_t * stack)46 pop(lock_free_stack_t *stack)
47 {
48 pointer_t old_top;
49 pointer_t new_top;
50 lac_mem_blk_t *next;
51
52 do {
53 old_top.atomic = stack->top.atomic;
54 next = old_top.ptr;
55 if (NULL == next)
56 return next;
57
58 new_top.ptr = next->pNext;
59 new_top.ctr = old_top.ctr + 1;
60 } while (!lac_atomic_cmp_swap(&stack->top, old_top, new_top));
61
62 return next;
63 }
64
65 static inline void
push(lock_free_stack_t * stack,lac_mem_blk_t * val)66 push(lock_free_stack_t *stack, lac_mem_blk_t *val)
67 {
68 pointer_t new_top;
69 pointer_t old_top;
70
71 do {
72 old_top.atomic = stack->top.atomic;
73 val->pNext = old_top.ptr;
74 new_top.ptr = val;
75 new_top.ctr = old_top.ctr + 1;
76 } while (!lac_atomic_cmp_swap(&stack->top, old_top, new_top));
77 }
78
79 static inline lock_free_stack_t
_init_stack(void)80 _init_stack(void)
81 {
82 lock_free_stack_t stack = { .top.atomic = 0 };
83 return stack;
84 }
85
86 static inline lac_mem_blk_t *
top(lock_free_stack_t * stack)87 top(lock_free_stack_t *stack)
88 {
89 pointer_t old_top = stack->top;
90 lac_mem_blk_t *next = old_top.ptr;
91 return next;
92 }
93
94 #endif
95