spu: fix some thread safety issues
authornotaz <notasas@gmail.com>
Mon, 2 Feb 2015 01:51:40 +0000 (03:51 +0200)
committernotaz <notasas@gmail.com>
Mon, 2 Feb 2015 01:51:40 +0000 (03:51 +0200)
reverb and stuff

plugins/dfsound/externals.h
plugins/dfsound/freeze.c
plugins/dfsound/registers.c
plugins/dfsound/reverb.c
plugins/dfsound/spu.c

index f6fc440..8bbf4e0 100644 (file)
@@ -162,14 +162,8 @@ typedef struct
 \r
  int dirty;          // registers changed\r
 \r
- // normalized offsets\r
- int nIIR_DEST_A0, nIIR_DEST_A1, nIIR_DEST_B0, nIIR_DEST_B1,\r
-       nACC_SRC_A0, nACC_SRC_A1, nACC_SRC_B0, nACC_SRC_B1, \r
-       nIIR_SRC_A0, nIIR_SRC_A1, nIIR_SRC_B0, nIIR_SRC_B1,\r
-       nACC_SRC_C0, nACC_SRC_C1, nACC_SRC_D0, nACC_SRC_D1,\r
-       nMIX_DEST_A0, nMIX_DEST_A1, nMIX_DEST_B0, nMIX_DEST_B1;\r
  // MIX_DEST_xx - FB_SRC_x\r
- int nFB_SRC_A0, nFB_SRC_A1, nFB_SRC_B0, nFB_SRC_B1;\r
+ int FB_SRC_A0, FB_SRC_A1, FB_SRC_B0, FB_SRC_B1;\r
 } REVERBInfo;\r
 \r
 ///////////////////////////////////////////////////////////\r
index 5b4267b..72c9d22 100644 (file)
@@ -231,6 +231,8 @@ long CALLBACK SPUfreeze(uint32_t ulFreezeMode, SPUFreeze_t * pF,
 \r
  if(!pF) return 0;                                     // first check\r
 \r
+ do_samples(cycles, 1);\r
+\r
  if(ulFreezeMode)                                      // info or save?\r
   {//--------------------------------------------------//\r
    if(ulFreezeMode==1)                                 \r
@@ -242,8 +244,6 @@ long CALLBACK SPUfreeze(uint32_t ulFreezeMode, SPUFreeze_t * pF,
 \r
    if(ulFreezeMode==2) return 1;                       // info mode? ok, bye\r
                                                        // save mode:\r
-   do_samples(cycles, 1);\r
-\r
    memcpy(pF->cSPURam,spu.spuMem,0x80000);             // copy common infos\r
    memcpy(pF->cSPUPort,spu.regArea,0x200);\r
 \r
index 4588fa7..91bcaf8 100644 (file)
@@ -145,17 +145,6 @@ void CALLBACK SPUwriteRegister(unsigned long reg, unsigned short val,
       break;\r
     //-------------------------------------------------//\r
     case H_SPUReverbAddr:\r
-      if(val==0xFFFF || val<=0x200)\r
-       {spu.rvb->StartAddr=spu.rvb->CurrAddr=0;}\r
-      else\r
-       {\r
-        const long iv=(unsigned long)val<<2;\r
-        if(spu.rvb->StartAddr!=iv)\r
-         {\r
-          spu.rvb->StartAddr=(unsigned long)val<<2;\r
-          spu.rvb->CurrAddr=spu.rvb->StartAddr;\r
-         }\r
-       }\r
       goto rvbd;\r
     //-------------------------------------------------//\r
     case H_SPUirqAddr:\r
@@ -246,38 +235,38 @@ void CALLBACK SPUwriteRegister(unsigned long reg, unsigned short val,
       ReverbOn(16,24,val);\r
       break;\r
     //-------------------------------------------------//\r
-    case H_Reverb+0   : spu.rvb->FB_SRC_A=val*4;         goto rvbd;\r
-    case H_Reverb+2   : spu.rvb->FB_SRC_B=val*4;         goto rvbd;\r
-    case H_Reverb+4   : spu.rvb->IIR_ALPHA=(short)val;   goto rvbd;\r
-    case H_Reverb+6   : spu.rvb->ACC_COEF_A=(short)val;  goto rvbd;\r
-    case H_Reverb+8   : spu.rvb->ACC_COEF_B=(short)val;  goto rvbd;\r
-    case H_Reverb+10  : spu.rvb->ACC_COEF_C=(short)val;  goto rvbd;\r
-    case H_Reverb+12  : spu.rvb->ACC_COEF_D=(short)val;  goto rvbd;\r
-    case H_Reverb+14  : spu.rvb->IIR_COEF=(short)val;    goto rvbd;\r
-    case H_Reverb+16  : spu.rvb->FB_ALPHA=(short)val;    goto rvbd;\r
-    case H_Reverb+18  : spu.rvb->FB_X=(short)val;        goto rvbd;\r
-    case H_Reverb+20  : spu.rvb->IIR_DEST_A0=val*4;      goto rvbd;\r
-    case H_Reverb+22  : spu.rvb->IIR_DEST_A1=val*4;      goto rvbd;\r
-    case H_Reverb+24  : spu.rvb->ACC_SRC_A0=val*4;       goto rvbd;\r
-    case H_Reverb+26  : spu.rvb->ACC_SRC_A1=val*4;       goto rvbd;\r
-    case H_Reverb+28  : spu.rvb->ACC_SRC_B0=val*4;       goto rvbd;\r
-    case H_Reverb+30  : spu.rvb->ACC_SRC_B1=val*4;       goto rvbd;\r
-    case H_Reverb+32  : spu.rvb->IIR_SRC_A0=val*4;       goto rvbd;\r
-    case H_Reverb+34  : spu.rvb->IIR_SRC_A1=val*4;       goto rvbd;\r
-    case H_Reverb+36  : spu.rvb->IIR_DEST_B0=val*4;      goto rvbd;\r
-    case H_Reverb+38  : spu.rvb->IIR_DEST_B1=val*4;      goto rvbd;\r
-    case H_Reverb+40  : spu.rvb->ACC_SRC_C0=val*4;       goto rvbd;\r
-    case H_Reverb+42  : spu.rvb->ACC_SRC_C1=val*4;       goto rvbd;\r
-    case H_Reverb+44  : spu.rvb->ACC_SRC_D0=val*4;       goto rvbd;\r
-    case H_Reverb+46  : spu.rvb->ACC_SRC_D1=val*4;       goto rvbd;\r
-    case H_Reverb+48  : spu.rvb->IIR_SRC_B1=val*4;       goto rvbd;\r
-    case H_Reverb+50  : spu.rvb->IIR_SRC_B0=val*4;       goto rvbd;\r
-    case H_Reverb+52  : spu.rvb->MIX_DEST_A0=val*4;      goto rvbd;\r
-    case H_Reverb+54  : spu.rvb->MIX_DEST_A1=val*4;      goto rvbd;\r
-    case H_Reverb+56  : spu.rvb->MIX_DEST_B0=val*4;      goto rvbd;\r
-    case H_Reverb+58  : spu.rvb->MIX_DEST_B1=val*4;      goto rvbd;\r
-    case H_Reverb+60  : spu.rvb->IN_COEF_L=(short)val;   goto rvbd;\r
-    case H_Reverb+62  : spu.rvb->IN_COEF_R=(short)val;   goto rvbd;\r
+    case H_Reverb+0   : goto rvbd;\r
+    case H_Reverb+2   : goto rvbd;\r
+    case H_Reverb+4   : spu.rvb->IIR_ALPHA=(short)val;   break;\r
+    case H_Reverb+6   : spu.rvb->ACC_COEF_A=(short)val;  break;\r
+    case H_Reverb+8   : spu.rvb->ACC_COEF_B=(short)val;  break;\r
+    case H_Reverb+10  : spu.rvb->ACC_COEF_C=(short)val;  break;\r
+    case H_Reverb+12  : spu.rvb->ACC_COEF_D=(short)val;  break;\r
+    case H_Reverb+14  : spu.rvb->IIR_COEF=(short)val;    break;\r
+    case H_Reverb+16  : spu.rvb->FB_ALPHA=(short)val;    break;\r
+    case H_Reverb+18  : spu.rvb->FB_X=(short)val;        break;\r
+    case H_Reverb+20  : goto rvbd;\r
+    case H_Reverb+22  : goto rvbd;\r
+    case H_Reverb+24  : goto rvbd;\r
+    case H_Reverb+26  : goto rvbd;\r
+    case H_Reverb+28  : goto rvbd;\r
+    case H_Reverb+30  : goto rvbd;\r
+    case H_Reverb+32  : goto rvbd;\r
+    case H_Reverb+34  : goto rvbd;\r
+    case H_Reverb+36  : goto rvbd;\r
+    case H_Reverb+38  : goto rvbd;\r
+    case H_Reverb+40  : goto rvbd;\r
+    case H_Reverb+42  : goto rvbd;\r
+    case H_Reverb+44  : goto rvbd;\r
+    case H_Reverb+46  : goto rvbd;\r
+    case H_Reverb+48  : goto rvbd;\r
+    case H_Reverb+50  : goto rvbd;\r
+    case H_Reverb+52  : goto rvbd;\r
+    case H_Reverb+54  : goto rvbd;\r
+    case H_Reverb+56  : goto rvbd;\r
+    case H_Reverb+58  : goto rvbd;\r
+    case H_Reverb+60  : spu.rvb->IN_COEF_L=(short)val;   break;\r
+    case H_Reverb+62  : spu.rvb->IN_COEF_R=(short)val;   break;\r
    }\r
  return;\r
 \r
index 2ff6edc..ec570fb 100644 (file)
@@ -50,16 +50,16 @@ INLINE int rvb2ram_offs(int curr, int space, int iOff)
 \r
 // get_buffer content helper: takes care about wraps\r
 #define g_buffer(var) \\r
- ((int)(signed short)spu.spuMem[rvb2ram_offs(curr_addr, space, rvb->n##var)])\r
+ ((int)(signed short)spu.spuMem[rvb2ram_offs(curr_addr, space, rvb->var)])\r
 \r
 // saturate iVal and store it as var\r
 #define s_buffer(var, iVal) \\r
  ssat32_to_16(iVal); \\r
- spu.spuMem[rvb2ram_offs(curr_addr, space, rvb->n##var)] = iVal\r
+ spu.spuMem[rvb2ram_offs(curr_addr, space, rvb->var)] = iVal\r
 \r
 #define s_buffer1(var, iVal) \\r
  ssat32_to_16(iVal); \\r
- spu.spuMem[rvb2ram_offs(curr_addr, space, rvb->n##var + 1)] = iVal\r
+ spu.spuMem[rvb2ram_offs(curr_addr, space, rvb->var + 1)] = iVal\r
 \r
 ////////////////////////////////////////////////////////////////////////\r
 \r
@@ -174,43 +174,54 @@ static void MixREVERB_off(int *SSumLR, int ns_to, int curr_addr)
 static void REVERBPrep(void)\r
 {\r
  REVERBInfo *rvb = spu.rvb;\r
- int space = 0x40000 - rvb->StartAddr;\r
- int t;\r
- #define prep_offs(v) \\r
-   t = rvb->v; \\r
+ int space, t;\r
+\r
+ t = spu.regArea[(H_SPUReverbAddr - 0xc00) >> 1];\r
+ if (t == 0xFFFF || t <= 0x200)\r
+  spu.rvb->StartAddr = spu.rvb->CurrAddr = 0;\r
+ else if (spu.rvb->StartAddr != (t << 2))\r
+  spu.rvb->StartAddr = spu.rvb->CurrAddr = t << 2;\r
+\r
+ space = 0x40000 - rvb->StartAddr;\r
+\r
+ #define prep_offs(v, r) \\r
+   t = spu.regArea[(0x1c0 + r) >> 1] * 4; \\r
    while (t >= space) \\r
      t -= space; \\r
-   rvb->n##v = t\r
- #define prep_offs2(d, v1, v2) \\r
-   t = rvb->v1 - rvb->v2; \\r
+   rvb->v = t\r
+ #define prep_offs2(d, r1, r2) \\r
+   t = spu.regArea[(0x1c0 + r1) >> 1] * 4; \\r
+   t -= spu.regArea[(0x1c0 + r2) >> 1] * 4; \\r
+   while (t < 0) \\r
+     t += space; \\r
    while (t >= space) \\r
      t -= space; \\r
-   rvb->n##d = t\r
-\r
- prep_offs(IIR_SRC_A0);\r
- prep_offs(IIR_SRC_A1);\r
- prep_offs(IIR_SRC_B0);\r
- prep_offs(IIR_SRC_B1);\r
- prep_offs(IIR_DEST_A0);\r
- prep_offs(IIR_DEST_A1);\r
- prep_offs(IIR_DEST_B0);\r
- prep_offs(IIR_DEST_B1);\r
- prep_offs(ACC_SRC_A0);\r
- prep_offs(ACC_SRC_A1);\r
- prep_offs(ACC_SRC_B0);\r
- prep_offs(ACC_SRC_B1);\r
- prep_offs(ACC_SRC_C0);\r
- prep_offs(ACC_SRC_C1);\r
- prep_offs(ACC_SRC_D0);\r
- prep_offs(ACC_SRC_D1);\r
- prep_offs(MIX_DEST_A0);\r
- prep_offs(MIX_DEST_A1);\r
- prep_offs(MIX_DEST_B0);\r
- prep_offs(MIX_DEST_B1);\r
- prep_offs2(FB_SRC_A0, MIX_DEST_A0, FB_SRC_A);\r
- prep_offs2(FB_SRC_A1, MIX_DEST_A1, FB_SRC_A);\r
- prep_offs2(FB_SRC_B0, MIX_DEST_B0, FB_SRC_B);\r
- prep_offs2(FB_SRC_B1, MIX_DEST_B1, FB_SRC_B);\r
+   rvb->d = t\r
+\r
+ prep_offs(IIR_SRC_A0, 32);\r
+ prep_offs(IIR_SRC_A1, 34);\r
+ prep_offs(IIR_SRC_B0, 36);\r
+ prep_offs(IIR_SRC_B1, 38);\r
+ prep_offs(IIR_DEST_A0, 20);\r
+ prep_offs(IIR_DEST_A1, 22);\r
+ prep_offs(IIR_DEST_B0, 36);\r
+ prep_offs(IIR_DEST_B1, 38);\r
+ prep_offs(ACC_SRC_A0, 24);\r
+ prep_offs(ACC_SRC_A1, 26);\r
+ prep_offs(ACC_SRC_B0, 28);\r
+ prep_offs(ACC_SRC_B1, 30);\r
+ prep_offs(ACC_SRC_C0, 40);\r
+ prep_offs(ACC_SRC_C1, 42);\r
+ prep_offs(ACC_SRC_D0, 44);\r
+ prep_offs(ACC_SRC_D1, 46);\r
+ prep_offs(MIX_DEST_A0, 52);\r
+ prep_offs(MIX_DEST_A1, 54);\r
+ prep_offs(MIX_DEST_B0, 56);\r
+ prep_offs(MIX_DEST_B1, 58);\r
+ prep_offs2(FB_SRC_A0, 52, 0);\r
+ prep_offs2(FB_SRC_A1, 54, 0);\r
+ prep_offs2(FB_SRC_B0, 56, 2);\r
+ prep_offs2(FB_SRC_B1, 58, 2);\r
 \r
 #undef prep_offs\r
 #undef prep_offs2\r
index 8681d35..193a5d0 100644 (file)
@@ -818,12 +818,8 @@ static void do_channels(int ns_to)
   }
 
   if (spu.rvb->StartAddr) {
-   if (do_rvb) {
-    if (unlikely(spu.rvb->dirty))
-     REVERBPrep();
-
+   if (do_rvb)
     REVERBDo(spu.SSumLR, RVB, ns_to, spu.rvb->CurrAddr);
-   }
 
    spu.rvb->CurrAddr += ns_to / 2;
    while (spu.rvb->CurrAddr >= 0x40000)
@@ -970,11 +966,8 @@ static void queue_channel_work(int ns_to, unsigned int silentch)
 
  work->rvb_addr = 0;
  if (spu.rvb->StartAddr) {
-  if (spu_config.iUseReverb) {
-   if (unlikely(spu.rvb->dirty))
-    REVERBPrep();
+  if (spu_config.iUseReverb)
    work->rvb_addr = spu.rvb->CurrAddr;
-  }
 
   spu.rvb->CurrAddr += ns_to / 2;
   while (spu.rvb->CurrAddr >= 0x40000)
@@ -989,9 +982,9 @@ static void do_channel_work(struct work_item *work)
 {
  unsigned int mask;
  unsigned int decode_dirty_ch = 0;
+ const SPUCHAN *s_chan;
  int *SB, sinc, spos, sbpos;
  int d, ch, ns_to;
- SPUCHAN *s_chan;
 
  ns_to = work->ns_to;
 
@@ -1057,6 +1050,9 @@ static void sync_worker_thread(int force)
  struct work_item *work;
  int done, used_space;
 
+ // rvb offsets will change, thread may be using them
+ force |= spu.rvb->dirty && spu.rvb->StartAddr;
+
  done = thread_get_i_done() - worker->i_reaped;
  used_space = worker->i_ready - worker->i_reaped;
  //printf("done: %d use: %d dsp: %u/%u\n", done, used_space,
@@ -1150,6 +1146,9 @@ void do_samples(unsigned int cycles_to, int do_direct)
      }
    }
 
+  if (unlikely(spu.rvb->dirty))
+   REVERBPrep();
+
   if (do_direct || worker == NULL || !spu_config.iUseThread) {
    do_channels(ns_to);
    do_samples_finish(spu.SSumLR, ns_to, silentch, spu.decode_pos);