s390: fix crashes with CPU_FLAGS=4
[ajla.git] / rwlock.h
blob833fd1d416ad7251123c9f8aa07bfc7ecc43eadc
1 /*
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
9 * version.
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_RWLOCK_H
20 #define AJLA_RWLOCK_H
22 #include "list.h"
23 #include "thread.h"
25 #ifndef THREAD_NONE
26 #define RWLOCK_IMPLEMENTED
27 #endif
29 #ifndef RWLOCK_IMPLEMENTED
31 #define rwlock_decl(name) static mutex_t name
32 #define rwlock_init mutex_init
33 #define rwlock_done mutex_done
34 #define rwlock_lock_read mutex_lock
35 #define rwlock_unlock_read mutex_unlock
36 #define rwlock_lock_write mutex_lock
37 #define rwlock_unlock_write mutex_unlock
39 #else
41 struct rwlock_per_thread {
42 mutex_t mutex;
43 struct list entry;
46 #define rwlock_decl(name) \
47 static tls_decl(struct rwlock_per_thread *, name##_per_thread); \
48 static void name##_set_tls(struct rwlock_per_thread *pt) \
49 { \
50 tls_set(struct rwlock_per_thread *, name##_per_thread, pt); \
51 } \
52 static struct rwlock_per_thread name
54 #define rwlock_init(name) \
55 do { \
56 mutex_init(name.mutex); \
57 list_init(name.entry); \
58 tls_init(struct rwlock_per_thread *, *name##_per_thread); \
59 /*tls_set(struct rwlock_per_thread *, *name##_per_thread, name);*/\
60 (*name##_set_tls)(name); \
61 } while (0)
63 #define rwlock_done(name) \
64 do { \
65 tls_done(struct rwlock_per_thread *, *name##_per_thread); \
66 ajla_assert_lo(list_is_empty(name.entry), (file_line, "rwlock list is not empty"));\
67 mutex_done(name.mutex); \
68 } while (0)
70 struct rwlock_per_thread *rwlock_per_thread_alloc(struct rwlock_per_thread *thread1, void (*set_tls)(struct rwlock_per_thread *));
72 #define rwlock_lock_read(name) \
73 do { \
74 struct rwlock_per_thread *pt_ = tls_get(struct rwlock_per_thread *, *name##_per_thread);\
75 if (unlikely(!pt_)) { \
76 pt_ = rwlock_per_thread_alloc(name, name##_set_tls); \
77 } \
78 mutex_lock(&pt_->mutex); \
79 } while (0)
81 #define rwlock_unlock_read(name) \
82 do { \
83 struct rwlock_per_thread *pt_ = tls_get(struct rwlock_per_thread *, *name##_per_thread);\
84 mutex_unlock(&pt_->mutex); \
85 } while (0)
87 void attr_fastcall rwlock_lock_write(struct rwlock_per_thread *thread1);
88 void attr_fastcall rwlock_unlock_write(struct rwlock_per_thread *thread1);
90 #endif
92 #endif