Skip to contentSkip to conversation

preempt_count overflow with brlocks

PATCH New Robert Love 1 participant 1 message Oct 8, 2002 Library code

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 preempt_count overflow with brlocks

Linus,

Now that brlocks loop over NR_CPUS, on SMP every brlock/brunlock results in the acquire/release of 32 locks. This incs/decs the preempt_count by 32.

Since we only have 7 bits now for actually storing the lock depth, we cannot nest but 3 locks deep. I doubt we ever acquire three brlocks concurrently, but it is still a concern.

Attached patch disables/enables preemption explicitly once and only once for each lock/unlock. This is also an optimization as it removes 31 incs, decs, and conditionals. :)

Problem reported by Andrew Morton.

Patch is against 2.5.41, please apply.

Robert Love

lib/brlock.c +7 -4
diff -urN linux-2.5.41/lib/brlock.c linux/lib/brlock.c
@@ -24,8 +24,9 @@
 {
 	int i;
 
+	preempt_disable();
 	for (i = 0; i < NR_CPUS; i++)
-		write_lock(&__brlock_array[i][idx]);
+		_raw_write_lock(&__brlock_array[i][idx]);
 }
 
 void __br_write_unlock (enum brlock_indices idx)
@@ -33,7 +34,8 @@
 	int i;
 
 	for (i = 0; i < NR_CPUS; i++)
-		write_unlock(&__brlock_array[i][idx]);
+		_raw_write_unlock(&__brlock_array[i][idx]);
+	preempt_enable();
 }
 
 #else /* ! __BRLOCK_USE_ATOMICS */
@@ -48,11 +50,12 @@
 {
 	int i;
 
+	preempt_disable();
 again:
-	spin_lock(&__br_write_locks[idx].lock);
+	_raw_spin_lock(&__br_write_locks[idx].lock);
 	for (i = 0; i < NR_CPUS; i++)
 		if (__brlock_array[i][idx] != 0) {
-			spin_unlock(&__br_write_locks[idx].lock);
+			_raw_spin_unlock(&__br_write_locks[idx].lock);
 			barrier();
 			cpu_relax();
 			goto again;