summaryrefslogtreecommitdiffstats
path: root/include/asm-cris/smp_lock.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/asm-cris/smp_lock.h')
-rw-r--r--include/asm-cris/smp_lock.h73
1 files changed, 73 insertions, 0 deletions
diff --git a/include/asm-cris/smp_lock.h b/include/asm-cris/smp_lock.h
new file mode 100644
index 000000000..085543014
--- /dev/null
+++ b/include/asm-cris/smp_lock.h
@@ -0,0 +1,73 @@
+#ifndef __CRIS_SMPLOCK_H
+#define __CRIS_SMPLOCK_H
+
+#include <linux/config.h>
+
+#ifdef CONFIG_SMP
+
+#error "SMP is not supported for CRIS"
+
+/*
+ * Locking the kernel
+ */
+
+extern __inline void lock_kernel(void)
+{
+ unsigned long flags;
+ int proc = smp_processor_id();
+
+ save_flags(flags);
+ cli();
+ /* set_bit works atomic in SMP machines */
+ while(set_bit(0, (void *)&kernel_flag))
+ {
+ /*
+ * We just start another level if we have the lock
+ */
+ if (proc == active_kernel_processor)
+ break;
+ do
+ {
+#ifdef __SMP_PROF__
+ smp_spins[smp_processor_id()]++;
+#endif
+ /*
+ * Doing test_bit here doesn't lock the bus
+ */
+ if (test_bit(proc, (void *)&smp_invalidate_needed))
+ if (clear_bit(proc, (void *)&smp_invalidate_needed))
+ local_flush_tlb();
+ }
+ while(test_bit(0, (void *)&kernel_flag));
+ }
+ /*
+ * We got the lock, so tell the world we are here and increment
+ * the level counter
+ */
+ active_kernel_processor = proc;
+ kernel_counter++;
+ restore_flags(flags);
+}
+
+extern __inline void unlock_kernel(void)
+{
+ unsigned long flags;
+ save_flags(flags);
+ cli();
+ /*
+ * If it's the last level we have in the kernel, then
+ * free the lock
+ */
+ if (kernel_counter == 0)
+ panic("Kernel counter wrong.\n"); /* FIXME: Why is kernel_counter sometimes 0 here? */
+
+ if(! --kernel_counter)
+ {
+ active_kernel_processor = NO_PROC_ID;
+ clear_bit(0, (void *)&kernel_flag);
+ }
+ restore_flags(flags);
+}
+
+#endif
+#endif