Blame view
fs/erofs/tagptr.h
2.97 KB
29b24f6ca staging: erofs: u... |
1 2 3 |
/* SPDX-License-Identifier: GPL-2.0-only */ /* * A tagged pointer implementation |
b8b58b328 staging: erofs: <... |
4 5 6 |
* * Copyright (C) 2018 Gao Xiang <gaoxiang25@huawei.com> */ |
57b78c9fd staging: erofs: r... |
7 8 |
#ifndef __EROFS_FS_TAGPTR_H #define __EROFS_FS_TAGPTR_H |
b8b58b328 staging: erofs: <... |
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 |
#include <linux/types.h> #include <linux/build_bug.h> /* * the name of tagged pointer types are tagptr{1, 2, 3...}_t * avoid directly using the internal structs __tagptr{1, 2, 3...} */ #define __MAKE_TAGPTR(n) \ typedef struct __tagptr##n { \ uintptr_t v; \ } tagptr##n##_t; __MAKE_TAGPTR(1) __MAKE_TAGPTR(2) __MAKE_TAGPTR(3) __MAKE_TAGPTR(4) #undef __MAKE_TAGPTR extern void __compiletime_error("bad tagptr tags") __bad_tagptr_tags(void); extern void __compiletime_error("bad tagptr type") __bad_tagptr_type(void); /* fix the broken usage of "#define tagptr2_t tagptr3_t" by users */ #define __tagptr_mask_1(ptr, n) \ __builtin_types_compatible_p(typeof(ptr), struct __tagptr##n) ? \ (1UL << (n)) - 1 : #define __tagptr_mask(ptr) (\ __tagptr_mask_1(ptr, 1) ( \ __tagptr_mask_1(ptr, 2) ( \ __tagptr_mask_1(ptr, 3) ( \ __tagptr_mask_1(ptr, 4) ( \ __bad_tagptr_type(), 0))))) /* generate a tagged pointer from a raw value */ #define tagptr_init(type, val) \ ((typeof(type)){ .v = (uintptr_t)(val) }) /* * directly cast a tagged pointer to the native pointer type, which * could be used for backward compatibility of existing code. */ #define tagptr_cast_ptr(tptr) ((void *)(tptr).v) /* encode tagged pointers */ #define tagptr_fold(type, ptr, _tags) ({ \ const typeof(_tags) tags = (_tags); \ if (__builtin_constant_p(tags) && (tags & ~__tagptr_mask(type))) \ __bad_tagptr_tags(); \ tagptr_init(type, (uintptr_t)(ptr) | tags); }) /* decode tagged pointers */ #define tagptr_unfold_ptr(tptr) \ ((void *)((tptr).v & ~__tagptr_mask(tptr))) #define tagptr_unfold_tags(tptr) \ ((tptr).v & __tagptr_mask(tptr)) /* operations for the tagger pointer */ #define tagptr_eq(_tptr1, _tptr2) ({ \ typeof(_tptr1) tptr1 = (_tptr1); \ typeof(_tptr2) tptr2 = (_tptr2); \ (void)(&tptr1 == &tptr2); \ (tptr1).v == (tptr2).v; }) /* lock-free CAS operation */ #define tagptr_cmpxchg(_ptptr, _o, _n) ({ \ typeof(_ptptr) ptptr = (_ptptr); \ typeof(_o) o = (_o); \ typeof(_n) n = (_n); \ (void)(&o == &n); \ (void)(&o == ptptr); \ tagptr_init(o, cmpxchg(&ptptr->v, o.v, n.v)); }) /* wrap WRITE_ONCE if atomic update is needed */ #define tagptr_replace_tags(_ptptr, tags) ({ \ typeof(_ptptr) ptptr = (_ptptr); \ *ptptr = tagptr_fold(*ptptr, tagptr_unfold_ptr(*ptptr), tags); \ *ptptr; }) #define tagptr_set_tags(_ptptr, _tags) ({ \ typeof(_ptptr) ptptr = (_ptptr); \ const typeof(_tags) tags = (_tags); \ if (__builtin_constant_p(tags) && (tags & ~__tagptr_mask(*ptptr))) \ __bad_tagptr_tags(); \ ptptr->v |= tags; \ *ptptr; }) #define tagptr_clear_tags(_ptptr, _tags) ({ \ typeof(_ptptr) ptptr = (_ptptr); \ const typeof(_tags) tags = (_tags); \ if (__builtin_constant_p(tags) && (tags & ~__tagptr_mask(*ptptr))) \ __bad_tagptr_tags(); \ ptptr->v &= ~tags; \ *ptptr; }) |
57b78c9fd staging: erofs: r... |
108 |
#endif /* __EROFS_FS_TAGPTR_H */ |
b8b58b328 staging: erofs: <... |
109 |