summaryrefslogtreecommitdiffstats
path: root/include/asm-sparc/smp_lock.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/asm-sparc/smp_lock.h')
-rw-r--r--include/asm-sparc/smp_lock.h105
1 files changed, 67 insertions, 38 deletions
diff --git a/include/asm-sparc/smp_lock.h b/include/asm-sparc/smp_lock.h
index 7ce71d8ff..4f0a8e5f4 100644
--- a/include/asm-sparc/smp_lock.h
+++ b/include/asm-sparc/smp_lock.h
@@ -1,58 +1,87 @@
-/* smp_lock.h: Locking and unlocking the kernel on the Sparc.
+/* smp_lock.h: 32-bit Sparc SMP master lock primitives.
*
- * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
+ * Copyright (C) 1996,1997 David S. Miller (davem@caip.rutgers.edu)
*/
#ifndef __SPARC_SMPLOCK_H
#define __SPARC_SMPLOCK_H
#include <asm/smp.h>
-#include <asm/bitops.h>
-#include <asm/atops.h>
-#include <asm/pgtable.h>
+#include <asm/ptrace.h>
-#ifdef __SMP__
+#ifndef __SMP__
-/*
- * Locking the kernel
+#define lock_kernel() do { } while(0)
+#define unlock_kernel() do { } while(0)
+#define release_kernel_lock(task, cpu, depth) ((depth) = 1)
+#define reacquire_kernel_lock(task, cpu, depth) do { } while(0)
+
+#else
+
+#include <asm/hardirq.h>
+
+/* Release global kernel lock and global interrupt lock */
+#define release_kernel_lock(task, cpu, depth) \
+do { \
+ if((depth = (task)->lock_depth) != 0) { \
+ __cli(); \
+ (task)->lock_depth = 0; \
+ klock_info.akp = NO_PROC_ID; \
+ klock_info.kernel_flag = 0; \
+ } \
+ release_irqlock(cpu); \
+ __sti(); \
+} while(0)
+
+/* Do not fuck with this without consulting arch/sparc/lib/locks.S first! */
+#define reacquire_kernel_lock(task, cpu, depth) \
+do { \
+ if(depth) { \
+ register struct klock_info *klip asm("g1"); \
+ register int proc asm("g5"); \
+ klip = &klock_info; \
+ proc = cpu; \
+ __asm__ __volatile__("mov %%o7, %%g4\n\t" \
+ "call ___lock_reacquire_kernel\n\t" \
+ " mov %2, %%g2" \
+ : /* No outputs. */ \
+ : "r" (klip), "r" (proc), "r" (depth) \
+ : "g2", "g3", "g4", "g7", "memory", "cc"); \
+ } \
+} while(0)
+
+/* The following acquire and release the master kernel global lock,
+ * the idea is that the usage of this mechanmism becomes less and less
+ * as time goes on, to the point where they are no longer needed at all
+ * and can thus disappear.
*/
-/* Knock knock... */
+/* Do not fuck with this without consulting arch/sparc/lib/locks.S first! */
extern __inline__ void lock_kernel(void)
{
- unsigned long flags;
- int proc = smp_processor_id();
-
- save_flags(flags); cli(); /* need this on sparc? */
- while(ldstub(&kernel_flag)) {
- if(proc == active_kernel_processor)
- break;
- do {
-#ifdef __SMP_PROF__
- smp_spins[smp_processor_id()]++;
-#endif
- barrier();
- } while(kernel_flag); /* Don't lock the bus more than we have to. */
- }
- active_kernel_processor = proc;
- kernel_counter++;
- restore_flags(flags);
+ register struct klock_info *klip asm("g1");
+ register int proc asm("g5");
+ klip = &klock_info;
+ proc = smp_processor_id();
+ __asm__ __volatile__("
+ mov %%o7, %%g4
+ call ___lock_kernel
+ ld [%%g6 + %0], %%g2
+" : : "i" (AOFF_task_lock_depth), "r" (klip), "r" (proc)
+ : "g2", "g3", "g4", "g7", "memory", "cc");
}
-/* I want out... */
+/* Release kernel global lock. */
extern __inline__ void unlock_kernel(void)
{
- unsigned long flags;
-
- save_flags(flags); cli(); /* need this on sparc? */
- if(kernel_counter == 0)
- panic("Bogus kernel counter.\n");
-
- if(!--kernel_counter) {
- active_kernel_processor = NO_PROC_ID;
- kernel_flag = KLOCK_CLEAR;
- }
- restore_flags(flags);
+ register struct klock_info *klip asm("g1");
+ klip = &klock_info;
+ __asm__ __volatile__("
+ mov %%o7, %%g4
+ call ___unlock_kernel
+ ld [%%g6 + %0], %%g2
+" : : "i" (AOFF_task_lock_depth), "r" (klip)
+ : "g2", "g3", "g4", "memory", "cc");
}
#endif /* !(__SPARC_SMPLOCK_H) */