aboutsummaryrefslogtreecommitdiffstats
path: root/roms/skiboot/include/lock.h
diff options
context:
space:
mode:
Diffstat (limited to 'roms/skiboot/include/lock.h')
-rw-r--r--roms/skiboot/include/lock.h106
1 files changed, 106 insertions, 0 deletions
diff --git a/roms/skiboot/include/lock.h b/roms/skiboot/include/lock.h
new file mode 100644
index 000000000..244adeaa4
--- /dev/null
+++ b/roms/skiboot/include/lock.h
@@ -0,0 +1,106 @@
+// SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+/* Copyright 2013-2019 IBM Corp. */
+
+#ifndef __LOCK_H
+#define __LOCK_H
+
+#include <stdbool.h>
+#include <processor.h>
+#include <cmpxchg.h>
+#include <ccan/list/list.h>
+#include <ccan/str/str.h>
+
+#ifdef DEBUG_LOCKS_BACKTRACE
+#include <stack.h>
+
+#define LOCKS_BACKTRACE_MAX_ENTS 60
+#endif
+
+struct lock {
+ /* Lock value has bit 63 as lock bit and the PIR of the owner
+ * in the top 32-bit
+ */
+ uint64_t lock_val;
+
+ /*
+ * Set to true if lock is involved in the console flush path
+ * in which case taking it will suspend console flushing
+ */
+ bool in_con_path;
+
+ /* file/line of lock owner */
+ const char *owner;
+
+#ifdef DEBUG_LOCKS_BACKTRACE
+ struct bt_entry bt_buf[LOCKS_BACKTRACE_MAX_ENTS];
+ struct bt_metadata bt_metadata;
+#endif
+
+ /* linkage in per-cpu list of owned locks */
+ struct list_node list;
+};
+
+/* Initializer... not ideal but works for now. If we need different
+ * values for the fields and/or start getting warnings we'll have to
+ * play macro tricks
+ */
+#define LOCK_UNLOCKED { 0 }
+
+/* Note vs. libc and locking:
+ *
+ * The printf() family of
+ * functions use stack based t buffers and call into skiboot
+ * underlying read() and write() which use a console lock.
+ *
+ * The underlying FSP console code will thus operate within that
+ * console lock.
+ *
+ * The libc does *NOT* lock stream buffer operations, so don't
+ * try to scanf() from the same FILE from two different processors.
+ *
+ * FSP operations are locked using an FSP lock, so all processors
+ * can safely call the FSP API
+ *
+ * Note about ordering:
+ *
+ * lock() is a full memory barrier. unlock() is a lwsync
+ *
+ */
+
+extern bool bust_locks;
+
+static inline void init_lock(struct lock *l)
+{
+ *l = (struct lock)LOCK_UNLOCKED;
+}
+
+#define LOCK_CALLER __FILE__ ":" stringify(__LINE__)
+
+#define try_lock(l) try_lock_caller(l, LOCK_CALLER)
+#define lock(l) lock_caller(l, LOCK_CALLER)
+#define lock_recursive(l) lock_recursive_caller(l, LOCK_CALLER)
+
+extern bool try_lock_caller(struct lock *l, const char *caller);
+extern void lock_caller(struct lock *l, const char *caller);
+extern void unlock(struct lock *l);
+
+extern bool lock_held_by_me(struct lock *l);
+
+/* The debug output can happen while the FSP lock, so we need some kind
+ * of recursive lock support here. I don't want all locks to be recursive
+ * though, thus the caller need to explicitly call lock_recursive which
+ * returns false if the lock was already held by this cpu. If it returns
+ * true, then the caller shall release it when done.
+ */
+extern bool lock_recursive_caller(struct lock *l, const char *caller);
+
+/* Called after per-cpu data structures are available */
+extern void init_locks(void);
+
+/* Dump the list of locks held by this CPU */
+extern void dump_locks_list(void);
+
+/* Clean all locks held by CPU (and warn if any) */
+extern void drop_my_locks(bool warn);
+
+#endif /* __LOCK_H */