diff options
Diffstat (limited to 'include/asm-cris/smp_lock.h')
-rw-r--r-- | include/asm-cris/smp_lock.h | 73 |
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 |