2 * Copyright (C) 2024 Mikulas Patocka
4 * This file is part of Ajla.
6 * Ajla is free software: you can redistribute it and/or modify it under the
7 * terms of the GNU General Public License as published by the Free Software
8 * Foundation, either version 3 of the License, or (at your option) any later
11 * Ajla is distributed in the hope that it will be useful, but WITHOUT ANY
12 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
13 * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License along with
16 * Ajla. If not, see <https://www.gnu.org/licenses/>.
19 #ifndef AJLA_ADDRLOCK_H
20 #define AJLA_ADDRLOCK_H
24 #if defined(barrier_data_dependency) && \
25 defined(barrier_write_before_unlock_lock) && \
26 ((defined(POINTERS_ARE_ATOMIC) && \
27 (defined(POINTER_TAG) || \
28 defined(POINTER_IGNORE_BITS))) || \
30 #define POINTER_FOLLOW_IS_LOCKLESS
34 * We need to determine refcount method here, so that we enable or disable
37 #if !defined(THREAD_NONE) && defined(POINTERS_ARE_ATOMIC) && defined(INLINE_ASM_GCC_X86) && !defined(UNUSUAL_REFCOUNTS)
39 #if defined(INLINE_ASM_GCC_LABELS)
40 #define REFCOUNT_ASM_X86_LABELS
41 #elif defined(HAVE_C11_ATOMICS)
42 #define REFCOUNT_ATOMIC
44 #define REFCOUNT_ASM_X86
47 #elif !defined(THREAD_NONE) && defined(HAVE_C11_ATOMICS) && !defined(UNUSUAL_REFCOUNTS)
49 #define REFCOUNT_ATOMIC
51 #elif !defined(THREAD_NONE) && defined(HAVE_SYNC_AND_FETCH) && !defined(UNUSUAL)
55 #elif !defined(THREAD_NONE) && (defined(OS_WIN32) || defined(OS_CYGWIN)) && !defined(UNUSUAL_THREAD)
57 #define REFCOUNT_WIN32
65 #if defined(REFCOUNT_ATOMIC) || defined(REFCOUNT_WIN32) || defined(POINTERS_ARE_ATOMIC)
66 #define REFCOUNTS_ARE_ATOMIC
72 #ifndef POINTER_FOLLOW_IS_LOCKLESS
81 #if (!defined(HAVE_PREAD) || !defined(HAVE_PWRITE)) && !defined(OS_OS2)
82 #define DO_LOCK_HANDLES
90 #if defined(THREAD_NONE) || defined(DEBUG_ALLOC_INSIDE_LOCKS)
91 #define POINTER_HASH_BITS 0
93 #define POINTER_HASH_BITS 10
95 #define POINTER_HASH_SIZE (1 << POINTER_HASH_BITS)
97 #define mutex_padding_size (sizeof(mutex_t) <= 1 ? 1 : \
98 sizeof(mutex_t) <= 2 ? 2 : \
99 sizeof(mutex_t) <= 4 ? 4 : \
100 sizeof(mutex_t) <= 8 ? 8 : \
101 sizeof(mutex_t) <= 16 ? 16 : \
102 sizeof(mutex_t) <= 32 ? 32 : \
103 sizeof(mutex_t) <= 64 ? 64 : \
104 sizeof(mutex_t) <= 128 ? 128 : \
105 sizeof(mutex_t) <= 256 ? 256 : \
108 #define rwmutex_padding_size (sizeof(rwmutex_t) <= 1 ? 1 : \
109 sizeof(rwmutex_t) <= 2 ? 2 : \
110 sizeof(rwmutex_t) <= 4 ? 4 : \
111 sizeof(rwmutex_t) <= 8 ? 8 : \
112 sizeof(rwmutex_t) <= 16 ? 16 : \
113 sizeof(rwmutex_t) <= 32 ? 32 : \
114 sizeof(rwmutex_t) <= 64 ? 64 : \
115 sizeof(rwmutex_t) <= 128 ? 128 :\
116 sizeof(rwmutex_t) <= 256 ? 256 :\
120 void attr_fastcall
address_lock(const void *, addrlock_depth
);
121 void attr_fastcall
address_unlock(const void *, addrlock_depth
);
122 void attr_fastcall
address_lock_two(const void *, const void *, addrlock_depth
);
123 bool attr_fastcall
address_trylock_second(const void *, const void *, addrlock_depth
);
124 void attr_fastcall
address_unlock_second(const void *, const void *, addrlock_depth
);
125 mutex_t
* attr_fastcall
address_get_mutex(const void *, addrlock_depth
);
127 void address_read_lock(const void *p
);
128 void address_read_unlock(const void *p
);
129 void address_write_lock(const void *p
);
130 void address_write_unlock(const void *p
);
132 #ifdef DEBUG_ALLOC_INSIDE_LOCKS
133 void address_lock_verify(void);
135 static inline void address_lock_verify(void) { }
138 void address_lock_init(void);
139 void address_lock_done(void);