On Friday 25 August 2006 04:06, Joe Hsu wrote: > 2006/8/25, Timothy Miller <[EMAIL PROTECTED]>: > > What we do is this: In a page of DMA buffer, we have some shared > > variables between GPU and CPU. As the GPU consumes ring buffer > > entries, it'll periodically update a shared variable that indicates > > the "head" of the queue, where words are extracted from the > > circular buffer. Similarly, as the driver fills commands into the > > ring buffer, it'll update the "tail" pointer to indicate to the GPU > > where the end of the queue is. Whenever the GPU runs to the end of > > what it thinks locally is the tail pointer (no more DMA reads), > > it'll reread the pointer in the host. If what it reads is > > different from the old value, it keeps going. If what it reads is > > the same, it stops (nothing more to do) and raises an interrupt. > > When the driver thinking DMA is still running and > then trying to update the "tail" pointer, at the almost > same time, DMA might be thinking the "tail" pointer is > the same as old one. Then the DMA engine stops. > > I think there may be some condition in the following: > > 1. CPU check if the DMA engine stops ==> NO > 2. GPU check if the tail pounter updated > before letting DMA stopped ==> same old tail pointer, DMA > stops 3. CPU update tail pointer > > Then we have to add work-around in the driver to > fix the condition, right?
What if we did it like this. Shared variables are prefixed shared_,
local ones (to CPU or GPU) local_.
GPU:
local_head := shared_head
local_tail := shared_tail
do {
wait until PIO_start_processing
do {
read entry at local_head
++shared_head
++local_head
execute entry
if (local_head == local_tail)
local_tail := shared_tail
if (local_head == local_tail)
raise interrupt "DMA Idle"
break to outer loop
} loop
} loop
CPU:
local_head := shared_head
local_tail := shared_tail
do {
if (local_head == local_tail)
local_head := shared_head
if (local_head == local_tail)
wait until there is room or DMA_idle
or: until interrupt "Buffer almost empty"
write entry at local_tail
++shared_tail
++local_tail
if DMA_idle
DMA_idle := false
PIO_start_processing
} loop
handle_interrupt {
DMA_idle := true
}
We should probably check this for deadlocks and other hazards carefully.
It's probably simple enough to make a Promela model and run it through
the Spin model checker.
Lourens
pgpeTi0iIm9mF.pgp
Description: PGP signature
_______________________________________________ Open-graphics mailing list [email protected] http://lists.duskglow.com/mailman/listinfo/open-graphics List service provided by Duskglow Consulting, LLC (www.duskglow.com)
