2017-01-25 4 views
0

私はMIPSエミュレータを学習プロジェクトとして取り組んでいます。希望のパフォーマンスを得るために、私は各プロセッサを常に自分のスレッドでスリープさせたいと思います.DMA転送が発生すると処理が開始されます。C#でのエミュレータのマルチスレッドに関するアドバイス。パターン/コンセプト

以前はBackgroundWorkerを使っていましたが、async/away命令の使用を開始したばかりです。スレッドプーリングについては読んだことがあります。 「メモリ空間」は共有されるため、DMAステータスビットは「自然な」ロックメカニズムです。これらのスレッド技法は私が望むことをしていないようです。私は何が欠けていますか?

多分、このコード例(コンパイルは機能しません)は、私が何を考えているかを説明します。

public class ThreadingEmulatorCode 
{ 
    static Memory memory = new Memory(); 

    public ThreadingEmulatorCode() 
    { 
     CPU cpu = new CPU(); 
     memory.OnDMAZero += cpu.zero.Execute(new DMAEventArgs()); 
     memory.OnDMAOne += cpu.one.Execute(new DMAEventArgs()); 
     cpu.Run(ref memory); 
    } 
} 

public delegate void dmazero(DMAEventArgs args); 
public delegate void dmaone(DMAEventArgs args); 

public class DMAEventArgs : EventArgs 
{ 
    public byte[] Data { get; set; } 
    public uint Address { get; set; } 
} 

public class Memory 
{ 
    public event dmazero OnDMAZero; 
    public event dmaone OnDMAOne; 

    private const uint CoprocZeroDMA = 0x1FC00000; 
    private const uint CoprocOneDMA = 0xBFC00000; 
    private byte[] memory; 

    public Memory() 
    { 
     this.memory = new byte[(8 * 1024 * 1024)]; 
    } 

    public byte this[uint address] 
    { 
     get 
     { 
      return memory[address]; 
     } 
     set 
     { 
      memory[address] = value; 
      if (address == CoprocZeroDMA && OnDMAZero != null) 
       OnDMAZero(new DMAEventArgs()); 
      if (address == CoprocOneDMA && OnDMAOne != null) 
       OnDMAOne(new DMAEventArgs()); 
     } 
    } 
} 

public class CPU 
{ 
    public CoprocZero zero; 
    public CoprocOne one; 

    public void Run(ref Memory memory) 
    { 
     /* Start Executing Instructions */ 
    } 

    public CPU() 
    { 
     zero = new CoprocZero(); 
     one = new CoprocOne(); 
    } 
} 

public class CoprocZero 
{ 
    public CoprocZero(/* Start Listening Thread */) { } 

    public dmazero Execute(DMAEventArgs dmaEvent) 
    { 
     /* Process DMA'd Data */ 
     throw new NotImplementedException(); 
    } 
} 

public class CoprocOne 
{ 
    public CoprocOne(/* Start Listening Thread */) { } 

    public dmaone Execute(DMAEventArgs dmaEvent) 
    { 
     /* Process DMA'd Data */ 
     throw new NotImplementedException(); 
    } 
} 

アイデアまたは提案ですか?ありがとう。

+0

実際に何が起こっているのかと期待していることは何ですか? – gmiley

+0

私は、スリープスレッドに新しいワークロードを与える方法が明確ではないと思います。 – James

+0

まず、あなたの例ではマルチスレッドを実行していません。ここにあるものはすべて1つのスレッドで実行されます。マルチスレッドの場合は、 'System.Threading'名前空間を調べることが望ましいでしょう。 – gmiley

答えて

0

私はちょうどコードでもっと時間を費やす必要があるように見えます。ごめんなさい。もともと私は、TryPeekのCPUが最大になるとは思っていましたが、プロセスリストのゼロCPUに座っていました。私はまだ全体のパフォーマンスを確認していないが、これはうまくいくと思う。

// Code to Test 
// ThreadingExampleCode stackOverflow = new ThreadingExampleCode(); 
// Thread.Sleep(new TimeSpan(1, 0, 0)); 
public class ThreadingExampleCode 
{ 
    public static Memory memory; 
    private CoprocZero zero; 
    private CoprocOne one; 
    private CPU cpu; 
    private Thread coprocZero; 
    private Thread coprocOne; 
    ConcurrentQueue<uint> coprocZeroQueue = new ConcurrentQueue<uint>(); 
    ConcurrentQueue<uint> coprocOneQueue = new ConcurrentQueue<uint>(); 

    public ThreadingExampleCode() 
    { 
     memory = new Memory(); 
     memory.OnDMAZero += MemoryOnOnDmaZero; 
     memory.OnDMAOne += MemoryOnOnDmaOne; 

     cpu = new CPU(memory); 
     zero = new CoprocZero(memory, coprocZeroQueue); 
     one = new CoprocOne(memory, coprocOneQueue); 
     coprocZero = new Thread(zero.RunParm); 
     coprocZero.Start(); 

     coprocOne = new Thread(one.RunParm); 
     coprocOne.Start(); 

     cpu.Run(); 
    } 

    private void MemoryOnOnDmaOne(DMAEventArgs args) 
    { 
     coprocOneQueue.Enqueue(args.Address); 
    } 

    private void MemoryOnOnDmaZero(DMAEventArgs args) 
    { 
     coprocZeroQueue.Enqueue(args.Address); 
    } 
} 

public delegate void dmazero(DMAEventArgs args); 

public delegate void dmaone(DMAEventArgs args); 

public class DMAEventArgs : EventArgs 
{ 
    public uint Address { get; set; } 
} 

public class Memory 
{ 
    public event dmazero OnDMAZero; 
    public event dmaone OnDMAOne; 

    public const uint CoprocZeroDMA = 1 * 1024 * 1024; 
    public const uint CoprocOneDMA = 2 * 1024 * 1024; 
    private byte[] memory; 

    public Memory() 
    { 
     this.memory = new byte[(8 * 1024 * 1024)]; 
    } 

    public byte this[uint address] 
    { 
     get { return memory[address]; } 
     set 
     { 
      memory[address] = value; 
      if (address == CoprocZeroDMA && OnDMAZero != null) 
       OnDMAZero(new DMAEventArgs()); 
      if (address == CoprocOneDMA && OnDMAOne != null) 
       OnDMAOne(new DMAEventArgs()); 
     } 
    } 
} 

public class CPU 
{ 
    private Memory memory; 
    public CPU(Memory inMemory) 
    { 
     memory = inMemory; 
    } 

    public void Run() 
    { 
     /* Start Executing Instructions */ 
     memory[Memory.CoprocZeroDMA] = 0x01; 
     memory[Memory.CoprocOneDMA] = 0x01; 
    } 
} 

public class CoprocZero 
{ 
    private ConcurrentQueue<uint> queueToMonitor; 
    private Memory memory; 
    public CoprocZero(Memory inMemory, ConcurrentQueue<uint> queue) 
    { 
     memory = inMemory; 
     queueToMonitor = queue; 
    } 

    public void RunParm() 
    { 
     uint memoryAddress; 
     while (!queueToMonitor.TryPeek(out memoryAddress)) { }; 

     if (queueToMonitor.TryDequeue(out memoryAddress)) 
     { 
      Debugger.Break(); 
     } 
    } 
} 

public class CoprocOne 
{ 
    private Memory memory; 
    private ConcurrentQueue<uint> queueToMonitor; 
    public CoprocOne(Memory inMemory, ConcurrentQueue<uint> queue) 
    { 
     memory = inMemory; 
     queueToMonitor = queue; 
    } 

    public void RunParm() 
    { 
     uint memoryAddress; 
     while (!queueToMonitor.TryPeek(out memoryAddress)) { }; 

     if (queueToMonitor.TryDequeue(out memoryAddress)) 
     { 
      Debugger.Break(); 
     } 
    } 
} 
関連する問題