patch-1.3.31 linux/include/asm-i386/locks.h

Next file: linux/include/asm-i386/page.h
Previous file: linux/include/asm-i386/irq.h
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v1.3.30/linux/include/asm-i386/locks.h linux/include/asm-i386/locks.h
@@ -0,0 +1,133 @@
+/*
+ *	SMP locks primitives for building ix86 locks
+ *	(not yet used).
+ *
+ *		Alan Cox, alan@cymru.net, 1995
+ */
+ 
+/*
+ *	This would be much easier but far less clear and easy
+ *	to borrow for other processors if it was just assembler.
+ */
+
+extern __inline__ void prim_spin_lock(struct spinlock *sp)
+{
+	int processor=smp_processor_id();
+	
+	/*
+	 *	Grab the lock bit
+	 */
+	 
+	while(lock_set_bit(0,&sp->lock))
+	{
+		/*
+		 *	Failed, but thats cos we own it!
+		 */
+		 
+		if(sp->cpu==processor)
+		{
+			sp->users++;
+			return 0;
+		}
+		/*
+		 *	Spin in the cache S state if possible
+		 */
+		while(sp->lock)
+		{
+			/*
+			 *	Wait for any invalidates to go off
+			 */
+			 
+			if(smp_invalidate_needed&(1<<processor));
+				while(lock_clear_bit(processor,&smp_invalidate_needed))
+					local_invalidate();
+			sp->spins++;
+		}
+		/*
+		 *	Someone wrote the line, we go 'I' and get
+		 *	the cache entry. Now try and regrab
+		 */
+	}
+	sp->users++;sp->cpu=processor;
+	return 1;
+}
+
+/*
+ *	Release a spin lock
+ */
+ 
+extern __inline__ int prim_spin_unlock(struct spinlock *sp)
+{
+	/* This is safe. The decrement is still guarded by the lock. A multilock would
+	   not be safe this way */
+	if(!--sp->users)
+	{
+		lock_clear_bit(0,&sp->lock);sp->cpu= NO_PROC_ID;
+		return 1;
+	}
+	return 0;
+}
+
+
+/*
+ *	Non blocking lock grab
+ */
+ 
+extern __inline__ int prim_spin_lock_nb(struct spinlock *sp)
+{
+	if(lock_set_bit(0,&sp->lock))
+		return 0;		/* Locked already */
+	sp->users++;
+	return 1;			/* We got the lock */
+}
+
+
+/*
+ *	These wrap the locking primtives up for usage
+ */
+ 
+extern __inline__ void spinlock(struct spinlock *sp)
+{
+	if(sp->priority<current->lock_order)
+		panic("lock order violation: %s (%d)\n", sp->name, current->lock_order);
+	if(prim_spin_lock(sp))
+	{
+		/*
+		 *	We got a new lock. Update the priority chain
+		 */
+		sp->oldpri=current->lock_order;
+		current->lock_order=sp->priority;
+	}
+}
+
+extern __inline__ void spinunlock(struct spinlock *sp)
+{
+	if(current->lock_order!=sp->priority)
+		panic("lock release order violation %s (%d)\n", sp->name, current->lock_order);
+	if(prim_spin_unlock(sp))
+	{
+		/*
+		 *	Update the debugging lock priority chain. We dumped
+		 *	our last right to the lock.
+		 */
+		current->lock_order=sp->oldpri;
+	}	
+}
+
+extern __inline__ void spintestlock(struct spinlock *sp)
+{
+	/*
+	 *	We do no sanity checks, its legal to optimistically
+	 *	get a lower lock.
+	 */
+	prim_spin_lock_nb(sp);
+}
+
+extern __inline__ void spintestunlock(struct spinlock *sp)
+{
+	/*
+	 *	A testlock doesnt update the lock chain so we
+	 *	must not update it on free
+	 */
+	prim_spin_unlock(sp);
+}

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov with Sam's (original) version
of this