Date: Wed, 02 Nov 2005 01:49:01 +0800 From: Dinesh Nair <dinesh@alphaque.com> To: Scott Long <scottl@samsco.org> Cc: freebsd-hackers@freebsd.org Subject: Re: locking in a device driver Message-ID: <4367AA8D.3060506@alphaque.com> In-Reply-To: <436791ED.8010808@samsco.org> References: <4360B8EE.4070605@alphaque.com> <4360DD7B.20900@samsco.org> <4361044B.50807@alphaque.com> <20051027.205250.55834228.imp@bsdimp.com> <4361E3E0.4090409@alphaque.com> <43676121.4030801@alphaque.com> <436791ED.8010808@samsco.org>
next in thread | previous in thread | raw e-mail | index | archive | help
On 11/02/05 00:03 Scott Long said the following: > I think this thread has gone too far into hyperbole and conjecture. What > is your code trying to do, and what problems are you seeing? apologies, scott. i'm actually trying to get a driver written for freebsd 5.x backported to 4.x. the driver works like a charm on 5.x. under 4.x, i seem to be getting problems with synchronization/locking. the driver set consists of two drivers, a pseudo driver which the userland reads/writes/ioctls to, and the actual device driver which reads/writes from the device thru DMA and places the data into a ring buffer. this is the sequence of events for data from the device: 1. interrupt handler of device driver called 2. device driver reads data from DMA memory space 3. device driver writes to a shared buffer 4. device driver calls a function inside pseudo driver 5. pseudo driver copies data from shared buffer to another buffer 6. wakeup() is called 7. device driver waits for next interrupt the interrupt handler uses splhigh()/splx() to mask out interrupts during the time it's executing. interrupts happen 1000 times a second consistently. when a read on the pseudo device is called from a -lc_r threaded userland process, the following happens in pseudo device driver: 7. tsleep() is called, (with the same ident as the wakeup() in #6) 8. pseudo device reads from buffer in #5 and uses uiomove to return data to calling process exactly the reverse happens for a write. i believe that steps 3,5,8 need to be protected/synchronized with locks. the code uses mtx_lock/mtx_unlock in the 5.x version, and uses simple_lock in the 4.x version. digging thru the include files, i've noticed that simple_lock is a NOOP in 4.x if you're on a single processor. could i replace the mtx_lock/mtx_unlock with lockmgr(...,LK_EXCLUSIVE/LK_RELEASE) instead ? the earlier notion of using splhigh()/splx() to protect the common areas didnt seem like the right way to do it since the pseudo device driver is not interrupt driven, but rather is driven by open/read/write/ioctl from the userland. also, when the threaded userland reads, it's first put to a tsleep with PZERO|PCATCH and this tsleep is surrounded by a mtx_lock(&Giant) and mtx_unlock(&Giant). what should this be replaced with in 4.x ? when the real device driver has data from the device, it uses wakeup() to wake the tsleep'ed bits in the pseudo device driver. is this the correct way to do this ? also, is there any equivalent for PROC_LOCK()/PROC_UNLOCK() in 4.x or is it unnecessary ? -- Regards, /\_/\ "All dogs go to heaven." dinesh@alphaque.com (0 0) http://www.alphaque.com/ +==========================----oOO--(_)--OOo----==========================+ | for a in past present future; do | | for b in clients employers associates relatives neighbours pets; do | | echo "The opinions here in no way reflect the opinions of my $a $b." | | done; done | +=========================================================================+
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?4367AA8D.3060506>