1 /* SPDX-License-Identifier: BSD-3-Clause */
2 /* Copyright(c) 2007-2022 Intel Corporation */
3 /* $FreeBSD$ */
4 #ifndef LAC_LOCK_FREE_STACK_H_1
5 #define LAC_LOCK_FREE_STACK_H_1
6 #include "lac_mem_pools.h"
7
8 typedef union {
9 struct {
10 uint64_t ctr : 16;
11 uint64_t ptr : 48;
12 };
13 uint64_t atomic;
14 } pointer_t;
15
16 typedef struct {
17 volatile pointer_t top;
18 } lock_free_stack_t;
19
20 static inline void *
21 PTR(const uintptr_t addr48)
22 {
23 #ifdef __x86_64__
24 const int64_t addr64 = addr48 << 16;
25
26 /* Do arithmetic shift to restore kernel canonical address (if not NULL)
27 */
28 return (void *)(addr64 >> 16);
29 #else
30 return (void *)(addr48);
31 #endif
32 }
33
34 static inline lac_mem_blk_t *
35 pop(lock_free_stack_t *stack)
36 {
37 pointer_t old_top;
38 pointer_t new_top;
39 lac_mem_blk_t *next;
40
41 do {
42 old_top.atomic = stack->top.atomic;
43 next = PTR(old_top.ptr);
44 if (NULL == next)
45 return next;
46
47 new_top.ptr = (uintptr_t)next->pNext;
48 new_top.ctr = old_top.ctr + 1;
49 } while (!__sync_bool_compare_and_swap(&stack->top.atomic,
50 old_top.atomic,
51 new_top.atomic));
52
53 return next;
54 }
55
56 static inline void
57 push(lock_free_stack_t *stack, lac_mem_blk_t *val)
58 {
59 pointer_t new_top;
60 pointer_t old_top;
61
62 do {
63 old_top.atomic = stack->top.atomic;
64 val->pNext = PTR(old_top.ptr);
65 new_top.ptr = (uintptr_t)val;
66 new_top.ctr = old_top.ctr + 1;
67 } while (!__sync_bool_compare_and_swap(&stack->top.atomic,
68 old_top.atomic,
69 new_top.atomic));
70 }
71
72 static inline lock_free_stack_t
73 _init_stack(void)
74 {
75 lock_free_stack_t stack = { { { 0 } } };
76 return stack;
77 }
78
79 static inline lac_mem_blk_t *
80 top(lock_free_stack_t *stack)
81 {
82 pointer_t old_top = stack->top;
83 lac_mem_blk_t *next = PTR(old_top.ptr);
84 return next;
85 }
86
87 #endif
Cache object: 2a591c9a30755b0b7a042e460edf6799
|