/* spinlock.h - spinlocks for i386
                Files that include this file should be compiled with the flags
		  gcc -O2 -W -Wall ...
 */

#ifndef _SPINLOCK_H_
#define _SPINLOCK_H_

/*VVVVVVVVVVV This code was extracted from the Linux Kernel VVVVVVVVV*/

#ifdef __SMP__
#define LOCK_PREFIX "lock ; "
#else
#define LOCK_PREFIX ""
#endif
struct __dummy { unsigned long a[100]; };
#define ADDR (*(volatile struct __dummy *) addr)


extern __inline__ int test_and_set_bit(int nr, volatile void * addr)
{
         int oldbit;
 
         __asm__ __volatile__( LOCK_PREFIX
                 "btsl %2,%1\n\tsbbl %0,%0"
                 :"=r" (oldbit),"=m" (ADDR)
                 :"Ir" (nr));
         return oldbit;
 }

/*^^^^^^^^^^^ This code was extracted from the Linux Kernel ^^^^^^^^^*/

/* This implementation of spinlocks does not disable interrupts, so
   there is a danger of deadlocks. It uses busy waiting. It can be 
   used for mutual exclusion between processes. 
   The variable x below must be a pointer to a location in memory
   shared between the communicating processes
 */

#define spin_lock_init(x) {*x = 0;}
#define spin_lock(x) {while (test_and_set_bit(0,x));}
#define spin_unlock(x) {*x = 0;}

#endif

