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

Attachment: 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)

Reply via email to