1 /* SPDX-License-Identifier: GPL-2.0 */
20 /* Only use one lock mechanism. Select which one. */
23 pthread_mutex_t mutex
;
26 static inline void lock_impl_lock(struct lock_impl
*lock
)
28 BUG_ON(pthread_mutex_lock(&lock
->mutex
));
31 static inline void lock_impl_unlock(struct lock_impl
*lock
)
33 BUG_ON(pthread_mutex_unlock(&lock
->mutex
));
36 static inline bool lock_impl_trylock(struct lock_impl
*lock
)
38 int err
= pthread_mutex_trylock(&lock
->mutex
);
42 else if (err
== EBUSY
)
47 static inline void lock_impl_init(struct lock_impl
*lock
)
49 pthread_mutex_init(&lock
->mutex
, NULL
);
52 #define LOCK_IMPL_INITIALIZER {.mutex = PTHREAD_MUTEX_INITIALIZER}
54 #else /* !defined(PTHREAD_LOCK) */
55 /* Spinlock that assumes that it always gets the lock immediately. */
61 static inline bool lock_impl_trylock(struct lock_impl
*lock
)
64 /* TODO: Should this be a test and set? */
65 return __sync_bool_compare_and_swap(&lock
->locked
, false, true);
67 __CPROVER_atomic_begin();
68 bool old_locked
= lock
->locked
;
70 __CPROVER_atomic_end();
72 /* Minimal barrier to prevent accesses leaking out of lock. */
73 __CPROVER_fence("RRfence", "RWfence");
79 static inline void lock_impl_lock(struct lock_impl
*lock
)
82 * CBMC doesn't support busy waiting, so just assume that the
85 assume(lock_impl_trylock(lock
));
88 * If the lock was already held by this thread then the assumption
89 * is unsatisfiable (deadlock).
93 static inline void lock_impl_unlock(struct lock_impl
*lock
)
96 BUG_ON(!__sync_bool_compare_and_swap(&lock
->locked
, true, false));
98 /* Minimal barrier to prevent accesses leaking out of lock. */
99 __CPROVER_fence("RWfence", "WWfence");
101 __CPROVER_atomic_begin();
102 bool old_locked
= lock
->locked
;
103 lock
->locked
= false;
104 __CPROVER_atomic_end();
110 static inline void lock_impl_init(struct lock_impl
*lock
)
112 lock
->locked
= false;
115 #define LOCK_IMPL_INITIALIZER {.locked = false}
117 #endif /* !defined(PTHREAD_LOCK) */
120 * Implement spinlocks using the lock mechanism. Wrap the lock to prevent mixing
121 * locks of different types.
124 struct lock_impl internal_lock
;
127 #define SPIN_LOCK_UNLOCKED {.internal_lock = LOCK_IMPL_INITIALIZER}
128 #define __SPIN_LOCK_UNLOCKED(x) SPIN_LOCK_UNLOCKED
129 #define DEFINE_SPINLOCK(x) spinlock_t x = SPIN_LOCK_UNLOCKED
131 static inline void spin_lock_init(spinlock_t
*lock
)
133 lock_impl_init(&lock
->internal_lock
);
136 static inline void spin_lock(spinlock_t
*lock
)
139 * Spin locks also need to be removed in order to eliminate all
140 * memory barriers. They are only used by the write side anyway.
142 #ifndef NO_SYNC_SMP_MB
144 lock_impl_lock(&lock
->internal_lock
);
148 static inline void spin_unlock(spinlock_t
*lock
)
150 #ifndef NO_SYNC_SMP_MB
151 lock_impl_unlock(&lock
->internal_lock
);
156 /* Don't bother with interrupts */
157 #define spin_lock_irq(lock) spin_lock(lock)
158 #define spin_unlock_irq(lock) spin_unlock(lock)
159 #define spin_lock_irqsave(lock, flags) spin_lock(lock)
160 #define spin_unlock_irqrestore(lock, flags) spin_unlock(lock)
163 * This is supposed to return an int, but I think that a bool should work as
166 static inline bool spin_trylock(spinlock_t
*lock
)
168 #ifndef NO_SYNC_SMP_MB
170 return lock_impl_trylock(&lock
->internal_lock
);
177 /* Hopefuly this won't overflow. */
181 #define COMPLETION_INITIALIZER(x) {.count = 0}
182 #define DECLARE_COMPLETION(x) struct completion x = COMPLETION_INITIALIZER(x)
183 #define DECLARE_COMPLETION_ONSTACK(x) DECLARE_COMPLETION(x)
185 static inline void init_completion(struct completion
*c
)
190 static inline void wait_for_completion(struct completion
*c
)
192 unsigned int prev_count
= __sync_fetch_and_sub(&c
->count
, 1);
197 static inline void complete(struct completion
*c
)
199 unsigned int prev_count
= __sync_fetch_and_add(&c
->count
, 1);
201 BUG_ON(prev_count
== UINT_MAX
);
204 /* This function probably isn't very useful for CBMC. */
205 static inline bool try_wait_for_completion(struct completion
*c
)
210 static inline bool completion_done(struct completion
*c
)
215 /* TODO: Implement complete_all */
216 static inline void complete_all(struct completion
*c
)