Date: Wed, 26 Aug 1998 20:03:54 +0200 (CEST)
From: Geert Uytterhoeven <Geert.Uytterhoeven@cs.kuleuven.ac.be>
To: Alan Cox <alan@cymru.net>
cc: "Andre M. Hedrick" <hedrick@Astro.Dyer.Vanderbilt.Edu>,
        Mark Lord <mlord@pobox.com>,
        Michael Schmitz <SCHMITZ@LCBVAX.CCHEM.BERKELEY.EDU>,
        Linux kernel <linux-kernel@vger.rutgers.edu>,
        Linux/m68k <linux-m68k@lists.linux-m68k.org>
Subject: Re: timer race condition? (was: RE: L68K: Re: IDE-Driver Update ::
In-Reply-To: <Pine.LNX.4.02A.9808260137400.22875-100000@mercator.cs.kuleuven.ac.be>
Sender: owner-linux-m68k@phil.uni-sb.de


Finally I found the problem: in ide_do_request(), add_timer() may be called
while hwgroup->timer is still active, causing a major mess up of the timer
scheduling subsystem. The other call to add_timer() in ide_set_handler() seems
to be clean.

The included patch fixes the problem. I don't know whether this is the
`correct' fix. Maybe we need two timers, one for normal requests and one to put
devices to sleep? At least my system survives now. I'm just wondering: how come
no one ever noticed this? Does it show up on slow machines only?

To find out whether a timer is active or inactive, you can test the fields
timer.next and timer.prev. Both must be NULL for an inactive timer.

--- ide.c.orig	Wed Aug 26 19:51:52 1998
+++ ide.c	Wed Aug 26 19:53:35 1998
@@ -1104,8 +1104,7 @@
 			if (sleep) {
 				if (0 < (signed long)(jiffies + WAIT_MIN_SLEEP - sleep)) 
 					sleep = jiffies + WAIT_MIN_SLEEP;
-				hwgroup->timer.expires = sleep;
-				add_timer(&hwgroup->timer);
+				mod_timer(&hwgroup->timer, sleep);
 			} else {
 				/* Ugly, but how can we sleep for the lock otherwise? perhaps from tq_scheduler? */
 				ide_release_lock(&ide_lock);	/* for atari only */

Greetings,

						Geert

P.S. Andre: I'll test your 2.1.118.ide+apm.patch.20.gz RSN.
--
Geert Uytterhoeven                     Geert.Uytterhoeven@cs.kuleuven.ac.be
Wavelets, Linux/{m68k~Amiga,PPC~CHRP}  http://www.cs.kuleuven.ac.be/~geert/
Department of Computer Science -- Katholieke Universiteit Leuven -- Belgium

