xref: /aosp_15_r20/external/lzma/C/MtDec.c (revision f6dc9357d832569d4d1f5d24eacdb3935a1ae8e6)
1*f6dc9357SAndroid Build Coastguard Worker /* MtDec.c -- Multi-thread Decoder
2*f6dc9357SAndroid Build Coastguard Worker 2024-02-20 : Igor Pavlov : Public domain */
3*f6dc9357SAndroid Build Coastguard Worker 
4*f6dc9357SAndroid Build Coastguard Worker #include "Precomp.h"
5*f6dc9357SAndroid Build Coastguard Worker 
6*f6dc9357SAndroid Build Coastguard Worker // #define SHOW_DEBUG_INFO
7*f6dc9357SAndroid Build Coastguard Worker 
8*f6dc9357SAndroid Build Coastguard Worker // #include <stdio.h>
9*f6dc9357SAndroid Build Coastguard Worker #include <string.h>
10*f6dc9357SAndroid Build Coastguard Worker 
11*f6dc9357SAndroid Build Coastguard Worker #ifdef SHOW_DEBUG_INFO
12*f6dc9357SAndroid Build Coastguard Worker #include <stdio.h>
13*f6dc9357SAndroid Build Coastguard Worker #endif
14*f6dc9357SAndroid Build Coastguard Worker 
15*f6dc9357SAndroid Build Coastguard Worker #include "MtDec.h"
16*f6dc9357SAndroid Build Coastguard Worker 
17*f6dc9357SAndroid Build Coastguard Worker #ifndef Z7_ST
18*f6dc9357SAndroid Build Coastguard Worker 
19*f6dc9357SAndroid Build Coastguard Worker #ifdef SHOW_DEBUG_INFO
20*f6dc9357SAndroid Build Coastguard Worker #define PRF(x) x
21*f6dc9357SAndroid Build Coastguard Worker #else
22*f6dc9357SAndroid Build Coastguard Worker #define PRF(x)
23*f6dc9357SAndroid Build Coastguard Worker #endif
24*f6dc9357SAndroid Build Coastguard Worker 
25*f6dc9357SAndroid Build Coastguard Worker #define PRF_STR_INT(s, d) PRF(printf("\n" s " %d\n", (unsigned)d))
26*f6dc9357SAndroid Build Coastguard Worker 
MtProgress_Init(CMtProgress * p,ICompressProgressPtr progress)27*f6dc9357SAndroid Build Coastguard Worker void MtProgress_Init(CMtProgress *p, ICompressProgressPtr progress)
28*f6dc9357SAndroid Build Coastguard Worker {
29*f6dc9357SAndroid Build Coastguard Worker   p->progress = progress;
30*f6dc9357SAndroid Build Coastguard Worker   p->res = SZ_OK;
31*f6dc9357SAndroid Build Coastguard Worker   p->totalInSize = 0;
32*f6dc9357SAndroid Build Coastguard Worker   p->totalOutSize = 0;
33*f6dc9357SAndroid Build Coastguard Worker }
34*f6dc9357SAndroid Build Coastguard Worker 
35*f6dc9357SAndroid Build Coastguard Worker 
MtProgress_Progress_ST(CMtProgress * p)36*f6dc9357SAndroid Build Coastguard Worker SRes MtProgress_Progress_ST(CMtProgress *p)
37*f6dc9357SAndroid Build Coastguard Worker {
38*f6dc9357SAndroid Build Coastguard Worker   if (p->res == SZ_OK && p->progress)
39*f6dc9357SAndroid Build Coastguard Worker     if (ICompressProgress_Progress(p->progress, p->totalInSize, p->totalOutSize) != SZ_OK)
40*f6dc9357SAndroid Build Coastguard Worker       p->res = SZ_ERROR_PROGRESS;
41*f6dc9357SAndroid Build Coastguard Worker   return p->res;
42*f6dc9357SAndroid Build Coastguard Worker }
43*f6dc9357SAndroid Build Coastguard Worker 
44*f6dc9357SAndroid Build Coastguard Worker 
MtProgress_ProgressAdd(CMtProgress * p,UInt64 inSize,UInt64 outSize)45*f6dc9357SAndroid Build Coastguard Worker SRes MtProgress_ProgressAdd(CMtProgress *p, UInt64 inSize, UInt64 outSize)
46*f6dc9357SAndroid Build Coastguard Worker {
47*f6dc9357SAndroid Build Coastguard Worker   SRes res;
48*f6dc9357SAndroid Build Coastguard Worker   CriticalSection_Enter(&p->cs);
49*f6dc9357SAndroid Build Coastguard Worker 
50*f6dc9357SAndroid Build Coastguard Worker   p->totalInSize += inSize;
51*f6dc9357SAndroid Build Coastguard Worker   p->totalOutSize += outSize;
52*f6dc9357SAndroid Build Coastguard Worker   if (p->res == SZ_OK && p->progress)
53*f6dc9357SAndroid Build Coastguard Worker     if (ICompressProgress_Progress(p->progress, p->totalInSize, p->totalOutSize) != SZ_OK)
54*f6dc9357SAndroid Build Coastguard Worker       p->res = SZ_ERROR_PROGRESS;
55*f6dc9357SAndroid Build Coastguard Worker   res = p->res;
56*f6dc9357SAndroid Build Coastguard Worker 
57*f6dc9357SAndroid Build Coastguard Worker   CriticalSection_Leave(&p->cs);
58*f6dc9357SAndroid Build Coastguard Worker   return res;
59*f6dc9357SAndroid Build Coastguard Worker }
60*f6dc9357SAndroid Build Coastguard Worker 
61*f6dc9357SAndroid Build Coastguard Worker 
MtProgress_GetError(CMtProgress * p)62*f6dc9357SAndroid Build Coastguard Worker SRes MtProgress_GetError(CMtProgress *p)
63*f6dc9357SAndroid Build Coastguard Worker {
64*f6dc9357SAndroid Build Coastguard Worker   SRes res;
65*f6dc9357SAndroid Build Coastguard Worker   CriticalSection_Enter(&p->cs);
66*f6dc9357SAndroid Build Coastguard Worker   res = p->res;
67*f6dc9357SAndroid Build Coastguard Worker   CriticalSection_Leave(&p->cs);
68*f6dc9357SAndroid Build Coastguard Worker   return res;
69*f6dc9357SAndroid Build Coastguard Worker }
70*f6dc9357SAndroid Build Coastguard Worker 
71*f6dc9357SAndroid Build Coastguard Worker 
MtProgress_SetError(CMtProgress * p,SRes res)72*f6dc9357SAndroid Build Coastguard Worker void MtProgress_SetError(CMtProgress *p, SRes res)
73*f6dc9357SAndroid Build Coastguard Worker {
74*f6dc9357SAndroid Build Coastguard Worker   CriticalSection_Enter(&p->cs);
75*f6dc9357SAndroid Build Coastguard Worker   if (p->res == SZ_OK)
76*f6dc9357SAndroid Build Coastguard Worker     p->res = res;
77*f6dc9357SAndroid Build Coastguard Worker   CriticalSection_Leave(&p->cs);
78*f6dc9357SAndroid Build Coastguard Worker }
79*f6dc9357SAndroid Build Coastguard Worker 
80*f6dc9357SAndroid Build Coastguard Worker 
81*f6dc9357SAndroid Build Coastguard Worker #define RINOK_THREAD(x) RINOK_WRes(x)
82*f6dc9357SAndroid Build Coastguard Worker 
83*f6dc9357SAndroid Build Coastguard Worker 
84*f6dc9357SAndroid Build Coastguard Worker struct CMtDecBufLink_
85*f6dc9357SAndroid Build Coastguard Worker {
86*f6dc9357SAndroid Build Coastguard Worker   struct CMtDecBufLink_ *next;
87*f6dc9357SAndroid Build Coastguard Worker   void *pad[3];
88*f6dc9357SAndroid Build Coastguard Worker };
89*f6dc9357SAndroid Build Coastguard Worker 
90*f6dc9357SAndroid Build Coastguard Worker typedef struct CMtDecBufLink_ CMtDecBufLink;
91*f6dc9357SAndroid Build Coastguard Worker 
92*f6dc9357SAndroid Build Coastguard Worker #define MTDEC__LINK_DATA_OFFSET sizeof(CMtDecBufLink)
93*f6dc9357SAndroid Build Coastguard Worker #define MTDEC__DATA_PTR_FROM_LINK(link) ((Byte *)(link) + MTDEC__LINK_DATA_OFFSET)
94*f6dc9357SAndroid Build Coastguard Worker 
95*f6dc9357SAndroid Build Coastguard Worker 
96*f6dc9357SAndroid Build Coastguard Worker 
97*f6dc9357SAndroid Build Coastguard Worker static THREAD_FUNC_DECL MtDec_ThreadFunc(void *pp);
98*f6dc9357SAndroid Build Coastguard Worker 
99*f6dc9357SAndroid Build Coastguard Worker 
MtDecThread_CreateEvents(CMtDecThread * t)100*f6dc9357SAndroid Build Coastguard Worker static WRes MtDecThread_CreateEvents(CMtDecThread *t)
101*f6dc9357SAndroid Build Coastguard Worker {
102*f6dc9357SAndroid Build Coastguard Worker   WRes wres = AutoResetEvent_OptCreate_And_Reset(&t->canWrite);
103*f6dc9357SAndroid Build Coastguard Worker   if (wres == 0)
104*f6dc9357SAndroid Build Coastguard Worker   {
105*f6dc9357SAndroid Build Coastguard Worker     wres = AutoResetEvent_OptCreate_And_Reset(&t->canRead);
106*f6dc9357SAndroid Build Coastguard Worker     if (wres == 0)
107*f6dc9357SAndroid Build Coastguard Worker       return SZ_OK;
108*f6dc9357SAndroid Build Coastguard Worker   }
109*f6dc9357SAndroid Build Coastguard Worker   return wres;
110*f6dc9357SAndroid Build Coastguard Worker }
111*f6dc9357SAndroid Build Coastguard Worker 
112*f6dc9357SAndroid Build Coastguard Worker 
MtDecThread_CreateAndStart(CMtDecThread * t)113*f6dc9357SAndroid Build Coastguard Worker static SRes MtDecThread_CreateAndStart(CMtDecThread *t)
114*f6dc9357SAndroid Build Coastguard Worker {
115*f6dc9357SAndroid Build Coastguard Worker   WRes wres = MtDecThread_CreateEvents(t);
116*f6dc9357SAndroid Build Coastguard Worker   // wres = 17; // for test
117*f6dc9357SAndroid Build Coastguard Worker   if (wres == 0)
118*f6dc9357SAndroid Build Coastguard Worker   {
119*f6dc9357SAndroid Build Coastguard Worker     if (Thread_WasCreated(&t->thread))
120*f6dc9357SAndroid Build Coastguard Worker       return SZ_OK;
121*f6dc9357SAndroid Build Coastguard Worker     wres = Thread_Create(&t->thread, MtDec_ThreadFunc, t);
122*f6dc9357SAndroid Build Coastguard Worker     if (wres == 0)
123*f6dc9357SAndroid Build Coastguard Worker       return SZ_OK;
124*f6dc9357SAndroid Build Coastguard Worker   }
125*f6dc9357SAndroid Build Coastguard Worker   return MY_SRes_HRESULT_FROM_WRes(wres);
126*f6dc9357SAndroid Build Coastguard Worker }
127*f6dc9357SAndroid Build Coastguard Worker 
128*f6dc9357SAndroid Build Coastguard Worker 
MtDecThread_FreeInBufs(CMtDecThread * t)129*f6dc9357SAndroid Build Coastguard Worker void MtDecThread_FreeInBufs(CMtDecThread *t)
130*f6dc9357SAndroid Build Coastguard Worker {
131*f6dc9357SAndroid Build Coastguard Worker   if (t->inBuf)
132*f6dc9357SAndroid Build Coastguard Worker   {
133*f6dc9357SAndroid Build Coastguard Worker     void *link = t->inBuf;
134*f6dc9357SAndroid Build Coastguard Worker     t->inBuf = NULL;
135*f6dc9357SAndroid Build Coastguard Worker     do
136*f6dc9357SAndroid Build Coastguard Worker     {
137*f6dc9357SAndroid Build Coastguard Worker       void *next = ((CMtDecBufLink *)link)->next;
138*f6dc9357SAndroid Build Coastguard Worker       ISzAlloc_Free(t->mtDec->alloc, link);
139*f6dc9357SAndroid Build Coastguard Worker       link = next;
140*f6dc9357SAndroid Build Coastguard Worker     }
141*f6dc9357SAndroid Build Coastguard Worker     while (link);
142*f6dc9357SAndroid Build Coastguard Worker   }
143*f6dc9357SAndroid Build Coastguard Worker }
144*f6dc9357SAndroid Build Coastguard Worker 
145*f6dc9357SAndroid Build Coastguard Worker 
MtDecThread_CloseThread(CMtDecThread * t)146*f6dc9357SAndroid Build Coastguard Worker static void MtDecThread_CloseThread(CMtDecThread *t)
147*f6dc9357SAndroid Build Coastguard Worker {
148*f6dc9357SAndroid Build Coastguard Worker   if (Thread_WasCreated(&t->thread))
149*f6dc9357SAndroid Build Coastguard Worker   {
150*f6dc9357SAndroid Build Coastguard Worker     Event_Set(&t->canWrite); /* we can disable it. There are no threads waiting canWrite in normal cases */
151*f6dc9357SAndroid Build Coastguard Worker     Event_Set(&t->canRead);
152*f6dc9357SAndroid Build Coastguard Worker     Thread_Wait_Close(&t->thread);
153*f6dc9357SAndroid Build Coastguard Worker   }
154*f6dc9357SAndroid Build Coastguard Worker 
155*f6dc9357SAndroid Build Coastguard Worker   Event_Close(&t->canRead);
156*f6dc9357SAndroid Build Coastguard Worker   Event_Close(&t->canWrite);
157*f6dc9357SAndroid Build Coastguard Worker }
158*f6dc9357SAndroid Build Coastguard Worker 
MtDec_CloseThreads(CMtDec * p)159*f6dc9357SAndroid Build Coastguard Worker static void MtDec_CloseThreads(CMtDec *p)
160*f6dc9357SAndroid Build Coastguard Worker {
161*f6dc9357SAndroid Build Coastguard Worker   unsigned i;
162*f6dc9357SAndroid Build Coastguard Worker   for (i = 0; i < MTDEC_THREADS_MAX; i++)
163*f6dc9357SAndroid Build Coastguard Worker     MtDecThread_CloseThread(&p->threads[i]);
164*f6dc9357SAndroid Build Coastguard Worker }
165*f6dc9357SAndroid Build Coastguard Worker 
MtDecThread_Destruct(CMtDecThread * t)166*f6dc9357SAndroid Build Coastguard Worker static void MtDecThread_Destruct(CMtDecThread *t)
167*f6dc9357SAndroid Build Coastguard Worker {
168*f6dc9357SAndroid Build Coastguard Worker   MtDecThread_CloseThread(t);
169*f6dc9357SAndroid Build Coastguard Worker   MtDecThread_FreeInBufs(t);
170*f6dc9357SAndroid Build Coastguard Worker }
171*f6dc9357SAndroid Build Coastguard Worker 
172*f6dc9357SAndroid Build Coastguard Worker 
173*f6dc9357SAndroid Build Coastguard Worker 
MtDec_GetError_Spec(CMtDec * p,UInt64 interruptIndex,BoolInt * wasInterrupted)174*f6dc9357SAndroid Build Coastguard Worker static SRes MtDec_GetError_Spec(CMtDec *p, UInt64 interruptIndex, BoolInt *wasInterrupted)
175*f6dc9357SAndroid Build Coastguard Worker {
176*f6dc9357SAndroid Build Coastguard Worker   SRes res;
177*f6dc9357SAndroid Build Coastguard Worker   CriticalSection_Enter(&p->mtProgress.cs);
178*f6dc9357SAndroid Build Coastguard Worker   *wasInterrupted = (p->needInterrupt && interruptIndex > p->interruptIndex);
179*f6dc9357SAndroid Build Coastguard Worker   res = p->mtProgress.res;
180*f6dc9357SAndroid Build Coastguard Worker   CriticalSection_Leave(&p->mtProgress.cs);
181*f6dc9357SAndroid Build Coastguard Worker   return res;
182*f6dc9357SAndroid Build Coastguard Worker }
183*f6dc9357SAndroid Build Coastguard Worker 
MtDec_Progress_GetError_Spec(CMtDec * p,UInt64 inSize,UInt64 outSize,UInt64 interruptIndex,BoolInt * wasInterrupted)184*f6dc9357SAndroid Build Coastguard Worker static SRes MtDec_Progress_GetError_Spec(CMtDec *p, UInt64 inSize, UInt64 outSize, UInt64 interruptIndex, BoolInt *wasInterrupted)
185*f6dc9357SAndroid Build Coastguard Worker {
186*f6dc9357SAndroid Build Coastguard Worker   SRes res;
187*f6dc9357SAndroid Build Coastguard Worker   CriticalSection_Enter(&p->mtProgress.cs);
188*f6dc9357SAndroid Build Coastguard Worker 
189*f6dc9357SAndroid Build Coastguard Worker   p->mtProgress.totalInSize += inSize;
190*f6dc9357SAndroid Build Coastguard Worker   p->mtProgress.totalOutSize += outSize;
191*f6dc9357SAndroid Build Coastguard Worker   if (p->mtProgress.res == SZ_OK && p->mtProgress.progress)
192*f6dc9357SAndroid Build Coastguard Worker     if (ICompressProgress_Progress(p->mtProgress.progress, p->mtProgress.totalInSize, p->mtProgress.totalOutSize) != SZ_OK)
193*f6dc9357SAndroid Build Coastguard Worker       p->mtProgress.res = SZ_ERROR_PROGRESS;
194*f6dc9357SAndroid Build Coastguard Worker 
195*f6dc9357SAndroid Build Coastguard Worker   *wasInterrupted = (p->needInterrupt && interruptIndex > p->interruptIndex);
196*f6dc9357SAndroid Build Coastguard Worker   res = p->mtProgress.res;
197*f6dc9357SAndroid Build Coastguard Worker 
198*f6dc9357SAndroid Build Coastguard Worker   CriticalSection_Leave(&p->mtProgress.cs);
199*f6dc9357SAndroid Build Coastguard Worker 
200*f6dc9357SAndroid Build Coastguard Worker   return res;
201*f6dc9357SAndroid Build Coastguard Worker }
202*f6dc9357SAndroid Build Coastguard Worker 
MtDec_Interrupt(CMtDec * p,UInt64 interruptIndex)203*f6dc9357SAndroid Build Coastguard Worker static void MtDec_Interrupt(CMtDec *p, UInt64 interruptIndex)
204*f6dc9357SAndroid Build Coastguard Worker {
205*f6dc9357SAndroid Build Coastguard Worker   CriticalSection_Enter(&p->mtProgress.cs);
206*f6dc9357SAndroid Build Coastguard Worker   if (!p->needInterrupt || interruptIndex < p->interruptIndex)
207*f6dc9357SAndroid Build Coastguard Worker   {
208*f6dc9357SAndroid Build Coastguard Worker     p->interruptIndex = interruptIndex;
209*f6dc9357SAndroid Build Coastguard Worker     p->needInterrupt = True;
210*f6dc9357SAndroid Build Coastguard Worker   }
211*f6dc9357SAndroid Build Coastguard Worker   CriticalSection_Leave(&p->mtProgress.cs);
212*f6dc9357SAndroid Build Coastguard Worker }
213*f6dc9357SAndroid Build Coastguard Worker 
MtDec_GetCrossBuff(CMtDec * p)214*f6dc9357SAndroid Build Coastguard Worker Byte *MtDec_GetCrossBuff(CMtDec *p)
215*f6dc9357SAndroid Build Coastguard Worker {
216*f6dc9357SAndroid Build Coastguard Worker   Byte *cr = p->crossBlock;
217*f6dc9357SAndroid Build Coastguard Worker   if (!cr)
218*f6dc9357SAndroid Build Coastguard Worker   {
219*f6dc9357SAndroid Build Coastguard Worker     cr = (Byte *)ISzAlloc_Alloc(p->alloc, MTDEC__LINK_DATA_OFFSET + p->inBufSize);
220*f6dc9357SAndroid Build Coastguard Worker     if (!cr)
221*f6dc9357SAndroid Build Coastguard Worker       return NULL;
222*f6dc9357SAndroid Build Coastguard Worker     p->crossBlock = cr;
223*f6dc9357SAndroid Build Coastguard Worker   }
224*f6dc9357SAndroid Build Coastguard Worker   return MTDEC__DATA_PTR_FROM_LINK(cr);
225*f6dc9357SAndroid Build Coastguard Worker }
226*f6dc9357SAndroid Build Coastguard Worker 
227*f6dc9357SAndroid Build Coastguard Worker 
228*f6dc9357SAndroid Build Coastguard Worker /*
229*f6dc9357SAndroid Build Coastguard Worker   MtDec_ThreadFunc2() returns:
230*f6dc9357SAndroid Build Coastguard Worker   0      - in all normal cases (even for stream error or memory allocation error)
231*f6dc9357SAndroid Build Coastguard Worker   (!= 0) - WRes error return by system threading function
232*f6dc9357SAndroid Build Coastguard Worker */
233*f6dc9357SAndroid Build Coastguard Worker 
234*f6dc9357SAndroid Build Coastguard Worker // #define MTDEC_ProgessStep (1 << 22)
235*f6dc9357SAndroid Build Coastguard Worker #define MTDEC_ProgessStep (1 << 0)
236*f6dc9357SAndroid Build Coastguard Worker 
MtDec_ThreadFunc2(CMtDecThread * t)237*f6dc9357SAndroid Build Coastguard Worker static WRes MtDec_ThreadFunc2(CMtDecThread *t)
238*f6dc9357SAndroid Build Coastguard Worker {
239*f6dc9357SAndroid Build Coastguard Worker   CMtDec *p = t->mtDec;
240*f6dc9357SAndroid Build Coastguard Worker 
241*f6dc9357SAndroid Build Coastguard Worker   PRF_STR_INT("MtDec_ThreadFunc2", t->index)
242*f6dc9357SAndroid Build Coastguard Worker 
243*f6dc9357SAndroid Build Coastguard Worker   // SetThreadAffinityMask(GetCurrentThread(), 1 << t->index);
244*f6dc9357SAndroid Build Coastguard Worker 
245*f6dc9357SAndroid Build Coastguard Worker   for (;;)
246*f6dc9357SAndroid Build Coastguard Worker   {
247*f6dc9357SAndroid Build Coastguard Worker     SRes res, codeRes;
248*f6dc9357SAndroid Build Coastguard Worker     BoolInt wasInterrupted, isAllocError, overflow, finish;
249*f6dc9357SAndroid Build Coastguard Worker     SRes threadingErrorSRes;
250*f6dc9357SAndroid Build Coastguard Worker     BoolInt needCode, needWrite, needContinue;
251*f6dc9357SAndroid Build Coastguard Worker 
252*f6dc9357SAndroid Build Coastguard Worker     size_t inDataSize_Start;
253*f6dc9357SAndroid Build Coastguard Worker     UInt64 inDataSize;
254*f6dc9357SAndroid Build Coastguard Worker     // UInt64 inDataSize_Full;
255*f6dc9357SAndroid Build Coastguard Worker 
256*f6dc9357SAndroid Build Coastguard Worker     UInt64 blockIndex;
257*f6dc9357SAndroid Build Coastguard Worker 
258*f6dc9357SAndroid Build Coastguard Worker     UInt64 inPrev = 0;
259*f6dc9357SAndroid Build Coastguard Worker     UInt64 outPrev = 0;
260*f6dc9357SAndroid Build Coastguard Worker     UInt64 inCodePos;
261*f6dc9357SAndroid Build Coastguard Worker     UInt64 outCodePos;
262*f6dc9357SAndroid Build Coastguard Worker 
263*f6dc9357SAndroid Build Coastguard Worker     Byte *afterEndData = NULL;
264*f6dc9357SAndroid Build Coastguard Worker     size_t afterEndData_Size = 0;
265*f6dc9357SAndroid Build Coastguard Worker     BoolInt afterEndData_IsCross = False;
266*f6dc9357SAndroid Build Coastguard Worker 
267*f6dc9357SAndroid Build Coastguard Worker     BoolInt canCreateNewThread = False;
268*f6dc9357SAndroid Build Coastguard Worker     // CMtDecCallbackInfo parse;
269*f6dc9357SAndroid Build Coastguard Worker     CMtDecThread *nextThread;
270*f6dc9357SAndroid Build Coastguard Worker 
271*f6dc9357SAndroid Build Coastguard Worker     PRF_STR_INT("=============== Event_Wait(&t->canRead)", t->index)
272*f6dc9357SAndroid Build Coastguard Worker 
273*f6dc9357SAndroid Build Coastguard Worker     RINOK_THREAD(Event_Wait(&t->canRead))
274*f6dc9357SAndroid Build Coastguard Worker     if (p->exitThread)
275*f6dc9357SAndroid Build Coastguard Worker       return 0;
276*f6dc9357SAndroid Build Coastguard Worker 
277*f6dc9357SAndroid Build Coastguard Worker     PRF_STR_INT("after Event_Wait(&t->canRead)", t->index)
278*f6dc9357SAndroid Build Coastguard Worker 
279*f6dc9357SAndroid Build Coastguard Worker     // if (t->index == 3) return 19; // for test
280*f6dc9357SAndroid Build Coastguard Worker 
281*f6dc9357SAndroid Build Coastguard Worker     blockIndex = p->blockIndex++;
282*f6dc9357SAndroid Build Coastguard Worker 
283*f6dc9357SAndroid Build Coastguard Worker     // PRF(printf("\ncanRead\n"))
284*f6dc9357SAndroid Build Coastguard Worker 
285*f6dc9357SAndroid Build Coastguard Worker     res = MtDec_Progress_GetError_Spec(p, 0, 0, blockIndex, &wasInterrupted);
286*f6dc9357SAndroid Build Coastguard Worker 
287*f6dc9357SAndroid Build Coastguard Worker     finish = p->readWasFinished;
288*f6dc9357SAndroid Build Coastguard Worker     needCode = False;
289*f6dc9357SAndroid Build Coastguard Worker     needWrite = False;
290*f6dc9357SAndroid Build Coastguard Worker     isAllocError = False;
291*f6dc9357SAndroid Build Coastguard Worker     overflow = False;
292*f6dc9357SAndroid Build Coastguard Worker 
293*f6dc9357SAndroid Build Coastguard Worker     inDataSize_Start = 0;
294*f6dc9357SAndroid Build Coastguard Worker     inDataSize = 0;
295*f6dc9357SAndroid Build Coastguard Worker     // inDataSize_Full = 0;
296*f6dc9357SAndroid Build Coastguard Worker 
297*f6dc9357SAndroid Build Coastguard Worker     if (res == SZ_OK && !wasInterrupted)
298*f6dc9357SAndroid Build Coastguard Worker     {
299*f6dc9357SAndroid Build Coastguard Worker       // if (p->inStream)
300*f6dc9357SAndroid Build Coastguard Worker       {
301*f6dc9357SAndroid Build Coastguard Worker         CMtDecBufLink *prev = NULL;
302*f6dc9357SAndroid Build Coastguard Worker         CMtDecBufLink *link = (CMtDecBufLink *)t->inBuf;
303*f6dc9357SAndroid Build Coastguard Worker         size_t crossSize = p->crossEnd - p->crossStart;
304*f6dc9357SAndroid Build Coastguard Worker 
305*f6dc9357SAndroid Build Coastguard Worker         PRF(printf("\ncrossSize = %d\n", crossSize));
306*f6dc9357SAndroid Build Coastguard Worker 
307*f6dc9357SAndroid Build Coastguard Worker         for (;;)
308*f6dc9357SAndroid Build Coastguard Worker         {
309*f6dc9357SAndroid Build Coastguard Worker           if (!link)
310*f6dc9357SAndroid Build Coastguard Worker           {
311*f6dc9357SAndroid Build Coastguard Worker             link = (CMtDecBufLink *)ISzAlloc_Alloc(p->alloc, MTDEC__LINK_DATA_OFFSET + p->inBufSize);
312*f6dc9357SAndroid Build Coastguard Worker             if (!link)
313*f6dc9357SAndroid Build Coastguard Worker             {
314*f6dc9357SAndroid Build Coastguard Worker               finish = True;
315*f6dc9357SAndroid Build Coastguard Worker               // p->allocError_for_Read_BlockIndex = blockIndex;
316*f6dc9357SAndroid Build Coastguard Worker               isAllocError = True;
317*f6dc9357SAndroid Build Coastguard Worker               break;
318*f6dc9357SAndroid Build Coastguard Worker             }
319*f6dc9357SAndroid Build Coastguard Worker             link->next = NULL;
320*f6dc9357SAndroid Build Coastguard Worker             if (prev)
321*f6dc9357SAndroid Build Coastguard Worker             {
322*f6dc9357SAndroid Build Coastguard Worker               // static unsigned g_num = 0;
323*f6dc9357SAndroid Build Coastguard Worker               // printf("\n%6d : %x", ++g_num, (unsigned)(size_t)((Byte *)link - (Byte *)prev));
324*f6dc9357SAndroid Build Coastguard Worker               prev->next = link;
325*f6dc9357SAndroid Build Coastguard Worker             }
326*f6dc9357SAndroid Build Coastguard Worker             else
327*f6dc9357SAndroid Build Coastguard Worker               t->inBuf = (void *)link;
328*f6dc9357SAndroid Build Coastguard Worker           }
329*f6dc9357SAndroid Build Coastguard Worker 
330*f6dc9357SAndroid Build Coastguard Worker           {
331*f6dc9357SAndroid Build Coastguard Worker             Byte *data = MTDEC__DATA_PTR_FROM_LINK(link);
332*f6dc9357SAndroid Build Coastguard Worker             Byte *parseData = data;
333*f6dc9357SAndroid Build Coastguard Worker             size_t size;
334*f6dc9357SAndroid Build Coastguard Worker 
335*f6dc9357SAndroid Build Coastguard Worker             if (crossSize != 0)
336*f6dc9357SAndroid Build Coastguard Worker             {
337*f6dc9357SAndroid Build Coastguard Worker               inDataSize = crossSize;
338*f6dc9357SAndroid Build Coastguard Worker               // inDataSize_Full = inDataSize;
339*f6dc9357SAndroid Build Coastguard Worker               inDataSize_Start = crossSize;
340*f6dc9357SAndroid Build Coastguard Worker               size = crossSize;
341*f6dc9357SAndroid Build Coastguard Worker               parseData = MTDEC__DATA_PTR_FROM_LINK(p->crossBlock) + p->crossStart;
342*f6dc9357SAndroid Build Coastguard Worker               PRF(printf("\ncross : crossStart = %7d  crossEnd = %7d finish = %1d",
343*f6dc9357SAndroid Build Coastguard Worker                   (int)p->crossStart, (int)p->crossEnd, (int)finish));
344*f6dc9357SAndroid Build Coastguard Worker             }
345*f6dc9357SAndroid Build Coastguard Worker             else
346*f6dc9357SAndroid Build Coastguard Worker             {
347*f6dc9357SAndroid Build Coastguard Worker               size = p->inBufSize;
348*f6dc9357SAndroid Build Coastguard Worker 
349*f6dc9357SAndroid Build Coastguard Worker               res = SeqInStream_ReadMax(p->inStream, data, &size);
350*f6dc9357SAndroid Build Coastguard Worker 
351*f6dc9357SAndroid Build Coastguard Worker               // size = 10; // test
352*f6dc9357SAndroid Build Coastguard Worker 
353*f6dc9357SAndroid Build Coastguard Worker               inDataSize += size;
354*f6dc9357SAndroid Build Coastguard Worker               // inDataSize_Full = inDataSize;
355*f6dc9357SAndroid Build Coastguard Worker               if (!prev)
356*f6dc9357SAndroid Build Coastguard Worker                 inDataSize_Start = size;
357*f6dc9357SAndroid Build Coastguard Worker 
358*f6dc9357SAndroid Build Coastguard Worker               p->readProcessed += size;
359*f6dc9357SAndroid Build Coastguard Worker               finish = (size != p->inBufSize);
360*f6dc9357SAndroid Build Coastguard Worker               if (finish)
361*f6dc9357SAndroid Build Coastguard Worker                 p->readWasFinished = True;
362*f6dc9357SAndroid Build Coastguard Worker 
363*f6dc9357SAndroid Build Coastguard Worker               // res = E_INVALIDARG; // test
364*f6dc9357SAndroid Build Coastguard Worker 
365*f6dc9357SAndroid Build Coastguard Worker               if (res != SZ_OK)
366*f6dc9357SAndroid Build Coastguard Worker               {
367*f6dc9357SAndroid Build Coastguard Worker                 // PRF(printf("\nRead error = %d\n", res))
368*f6dc9357SAndroid Build Coastguard Worker                 // we want to decode all data before error
369*f6dc9357SAndroid Build Coastguard Worker                 p->readRes = res;
370*f6dc9357SAndroid Build Coastguard Worker                 // p->readError_BlockIndex = blockIndex;
371*f6dc9357SAndroid Build Coastguard Worker                 p->readWasFinished = True;
372*f6dc9357SAndroid Build Coastguard Worker                 finish = True;
373*f6dc9357SAndroid Build Coastguard Worker                 res = SZ_OK;
374*f6dc9357SAndroid Build Coastguard Worker                 // break;
375*f6dc9357SAndroid Build Coastguard Worker               }
376*f6dc9357SAndroid Build Coastguard Worker 
377*f6dc9357SAndroid Build Coastguard Worker               if (inDataSize - inPrev >= MTDEC_ProgessStep)
378*f6dc9357SAndroid Build Coastguard Worker               {
379*f6dc9357SAndroid Build Coastguard Worker                 res = MtDec_Progress_GetError_Spec(p, 0, 0, blockIndex, &wasInterrupted);
380*f6dc9357SAndroid Build Coastguard Worker                 if (res != SZ_OK || wasInterrupted)
381*f6dc9357SAndroid Build Coastguard Worker                   break;
382*f6dc9357SAndroid Build Coastguard Worker                 inPrev = inDataSize;
383*f6dc9357SAndroid Build Coastguard Worker               }
384*f6dc9357SAndroid Build Coastguard Worker             }
385*f6dc9357SAndroid Build Coastguard Worker 
386*f6dc9357SAndroid Build Coastguard Worker             {
387*f6dc9357SAndroid Build Coastguard Worker               CMtDecCallbackInfo parse;
388*f6dc9357SAndroid Build Coastguard Worker 
389*f6dc9357SAndroid Build Coastguard Worker               parse.startCall = (prev == NULL);
390*f6dc9357SAndroid Build Coastguard Worker               parse.src = parseData;
391*f6dc9357SAndroid Build Coastguard Worker               parse.srcSize = size;
392*f6dc9357SAndroid Build Coastguard Worker               parse.srcFinished = finish;
393*f6dc9357SAndroid Build Coastguard Worker               parse.canCreateNewThread = True;
394*f6dc9357SAndroid Build Coastguard Worker 
395*f6dc9357SAndroid Build Coastguard Worker               PRF(printf("\nParse size = %d\n", (unsigned)size));
396*f6dc9357SAndroid Build Coastguard Worker 
397*f6dc9357SAndroid Build Coastguard Worker               p->mtCallback->Parse(p->mtCallbackObject, t->index, &parse);
398*f6dc9357SAndroid Build Coastguard Worker 
399*f6dc9357SAndroid Build Coastguard Worker               PRF(printf("   Parse processed = %d, state = %d \n", (unsigned)parse.srcSize, (unsigned)parse.state));
400*f6dc9357SAndroid Build Coastguard Worker 
401*f6dc9357SAndroid Build Coastguard Worker               needWrite = True;
402*f6dc9357SAndroid Build Coastguard Worker               canCreateNewThread = parse.canCreateNewThread;
403*f6dc9357SAndroid Build Coastguard Worker 
404*f6dc9357SAndroid Build Coastguard Worker               // printf("\n\n%12I64u %12I64u", (UInt64)p->mtProgress.totalInSize, (UInt64)p->mtProgress.totalOutSize);
405*f6dc9357SAndroid Build Coastguard Worker 
406*f6dc9357SAndroid Build Coastguard Worker               if (
407*f6dc9357SAndroid Build Coastguard Worker                   // parseRes != SZ_OK ||
408*f6dc9357SAndroid Build Coastguard Worker                   // inDataSize - (size - parse.srcSize) > p->inBlockMax
409*f6dc9357SAndroid Build Coastguard Worker                   // ||
410*f6dc9357SAndroid Build Coastguard Worker                   parse.state == MTDEC_PARSE_OVERFLOW
411*f6dc9357SAndroid Build Coastguard Worker                   // || wasInterrupted
412*f6dc9357SAndroid Build Coastguard Worker                   )
413*f6dc9357SAndroid Build Coastguard Worker               {
414*f6dc9357SAndroid Build Coastguard Worker                 // Overflow or Parse error - switch from MT decoding to ST decoding
415*f6dc9357SAndroid Build Coastguard Worker                 finish = True;
416*f6dc9357SAndroid Build Coastguard Worker                 overflow = True;
417*f6dc9357SAndroid Build Coastguard Worker 
418*f6dc9357SAndroid Build Coastguard Worker                 {
419*f6dc9357SAndroid Build Coastguard Worker                   PRF(printf("\n Overflow"));
420*f6dc9357SAndroid Build Coastguard Worker                   // PRF(printf("\nisBlockFinished = %d", (unsigned)parse.blockWasFinished));
421*f6dc9357SAndroid Build Coastguard Worker                   PRF(printf("\n inDataSize = %d", (unsigned)inDataSize));
422*f6dc9357SAndroid Build Coastguard Worker                 }
423*f6dc9357SAndroid Build Coastguard Worker 
424*f6dc9357SAndroid Build Coastguard Worker                 if (crossSize != 0)
425*f6dc9357SAndroid Build Coastguard Worker                   memcpy(data, parseData, size);
426*f6dc9357SAndroid Build Coastguard Worker                 p->crossStart = 0;
427*f6dc9357SAndroid Build Coastguard Worker                 p->crossEnd = 0;
428*f6dc9357SAndroid Build Coastguard Worker                 break;
429*f6dc9357SAndroid Build Coastguard Worker               }
430*f6dc9357SAndroid Build Coastguard Worker 
431*f6dc9357SAndroid Build Coastguard Worker               if (crossSize != 0)
432*f6dc9357SAndroid Build Coastguard Worker               {
433*f6dc9357SAndroid Build Coastguard Worker                 memcpy(data, parseData, parse.srcSize);
434*f6dc9357SAndroid Build Coastguard Worker                 p->crossStart += parse.srcSize;
435*f6dc9357SAndroid Build Coastguard Worker               }
436*f6dc9357SAndroid Build Coastguard Worker 
437*f6dc9357SAndroid Build Coastguard Worker               if (parse.state != MTDEC_PARSE_CONTINUE || finish)
438*f6dc9357SAndroid Build Coastguard Worker               {
439*f6dc9357SAndroid Build Coastguard Worker                 // we don't need to parse in current thread anymore
440*f6dc9357SAndroid Build Coastguard Worker 
441*f6dc9357SAndroid Build Coastguard Worker                 if (parse.state == MTDEC_PARSE_END)
442*f6dc9357SAndroid Build Coastguard Worker                   finish = True;
443*f6dc9357SAndroid Build Coastguard Worker 
444*f6dc9357SAndroid Build Coastguard Worker                 needCode = True;
445*f6dc9357SAndroid Build Coastguard Worker                 // p->crossFinished = finish;
446*f6dc9357SAndroid Build Coastguard Worker 
447*f6dc9357SAndroid Build Coastguard Worker                 if (parse.srcSize == size)
448*f6dc9357SAndroid Build Coastguard Worker                 {
449*f6dc9357SAndroid Build Coastguard Worker                   // full parsed - no cross transfer
450*f6dc9357SAndroid Build Coastguard Worker                   p->crossStart = 0;
451*f6dc9357SAndroid Build Coastguard Worker                   p->crossEnd = 0;
452*f6dc9357SAndroid Build Coastguard Worker                   break;
453*f6dc9357SAndroid Build Coastguard Worker                 }
454*f6dc9357SAndroid Build Coastguard Worker 
455*f6dc9357SAndroid Build Coastguard Worker                 if (parse.state == MTDEC_PARSE_END)
456*f6dc9357SAndroid Build Coastguard Worker                 {
457*f6dc9357SAndroid Build Coastguard Worker                   afterEndData = parseData + parse.srcSize;
458*f6dc9357SAndroid Build Coastguard Worker                   afterEndData_Size = size - parse.srcSize;
459*f6dc9357SAndroid Build Coastguard Worker                   if (crossSize != 0)
460*f6dc9357SAndroid Build Coastguard Worker                     afterEndData_IsCross = True;
461*f6dc9357SAndroid Build Coastguard Worker                   // we reduce data size to required bytes (parsed only)
462*f6dc9357SAndroid Build Coastguard Worker                   inDataSize -= afterEndData_Size;
463*f6dc9357SAndroid Build Coastguard Worker                   if (!prev)
464*f6dc9357SAndroid Build Coastguard Worker                     inDataSize_Start = parse.srcSize;
465*f6dc9357SAndroid Build Coastguard Worker                   break;
466*f6dc9357SAndroid Build Coastguard Worker                 }
467*f6dc9357SAndroid Build Coastguard Worker 
468*f6dc9357SAndroid Build Coastguard Worker                 {
469*f6dc9357SAndroid Build Coastguard Worker                   // partial parsed - need cross transfer
470*f6dc9357SAndroid Build Coastguard Worker                   if (crossSize != 0)
471*f6dc9357SAndroid Build Coastguard Worker                     inDataSize = parse.srcSize; // it's only parsed now
472*f6dc9357SAndroid Build Coastguard Worker                   else
473*f6dc9357SAndroid Build Coastguard Worker                   {
474*f6dc9357SAndroid Build Coastguard Worker                     // partial parsed - is not in initial cross block - we need to copy new data to cross block
475*f6dc9357SAndroid Build Coastguard Worker                     Byte *cr = MtDec_GetCrossBuff(p);
476*f6dc9357SAndroid Build Coastguard Worker                     if (!cr)
477*f6dc9357SAndroid Build Coastguard Worker                     {
478*f6dc9357SAndroid Build Coastguard Worker                       {
479*f6dc9357SAndroid Build Coastguard Worker                         PRF(printf("\ncross alloc error error\n"));
480*f6dc9357SAndroid Build Coastguard Worker                         // res = SZ_ERROR_MEM;
481*f6dc9357SAndroid Build Coastguard Worker                         finish = True;
482*f6dc9357SAndroid Build Coastguard Worker                         // p->allocError_for_Read_BlockIndex = blockIndex;
483*f6dc9357SAndroid Build Coastguard Worker                         isAllocError = True;
484*f6dc9357SAndroid Build Coastguard Worker                         break;
485*f6dc9357SAndroid Build Coastguard Worker                       }
486*f6dc9357SAndroid Build Coastguard Worker                     }
487*f6dc9357SAndroid Build Coastguard Worker 
488*f6dc9357SAndroid Build Coastguard Worker                     {
489*f6dc9357SAndroid Build Coastguard Worker                       size_t crSize = size - parse.srcSize;
490*f6dc9357SAndroid Build Coastguard Worker                       inDataSize -= crSize;
491*f6dc9357SAndroid Build Coastguard Worker                       p->crossEnd = crSize;
492*f6dc9357SAndroid Build Coastguard Worker                       p->crossStart = 0;
493*f6dc9357SAndroid Build Coastguard Worker                       memcpy(cr, parseData + parse.srcSize, crSize);
494*f6dc9357SAndroid Build Coastguard Worker                     }
495*f6dc9357SAndroid Build Coastguard Worker                   }
496*f6dc9357SAndroid Build Coastguard Worker 
497*f6dc9357SAndroid Build Coastguard Worker                   // inDataSize_Full = inDataSize;
498*f6dc9357SAndroid Build Coastguard Worker                   if (!prev)
499*f6dc9357SAndroid Build Coastguard Worker                     inDataSize_Start = parse.srcSize; // it's partial size (parsed only)
500*f6dc9357SAndroid Build Coastguard Worker 
501*f6dc9357SAndroid Build Coastguard Worker                   finish = False;
502*f6dc9357SAndroid Build Coastguard Worker                   break;
503*f6dc9357SAndroid Build Coastguard Worker                 }
504*f6dc9357SAndroid Build Coastguard Worker               }
505*f6dc9357SAndroid Build Coastguard Worker 
506*f6dc9357SAndroid Build Coastguard Worker               if (parse.srcSize != size)
507*f6dc9357SAndroid Build Coastguard Worker               {
508*f6dc9357SAndroid Build Coastguard Worker                 res = SZ_ERROR_FAIL;
509*f6dc9357SAndroid Build Coastguard Worker                 PRF(printf("\nfinished error SZ_ERROR_FAIL = %d\n", res));
510*f6dc9357SAndroid Build Coastguard Worker                 break;
511*f6dc9357SAndroid Build Coastguard Worker               }
512*f6dc9357SAndroid Build Coastguard Worker             }
513*f6dc9357SAndroid Build Coastguard Worker           }
514*f6dc9357SAndroid Build Coastguard Worker 
515*f6dc9357SAndroid Build Coastguard Worker           prev = link;
516*f6dc9357SAndroid Build Coastguard Worker           link = link->next;
517*f6dc9357SAndroid Build Coastguard Worker 
518*f6dc9357SAndroid Build Coastguard Worker           if (crossSize != 0)
519*f6dc9357SAndroid Build Coastguard Worker           {
520*f6dc9357SAndroid Build Coastguard Worker             crossSize = 0;
521*f6dc9357SAndroid Build Coastguard Worker             p->crossStart = 0;
522*f6dc9357SAndroid Build Coastguard Worker             p->crossEnd = 0;
523*f6dc9357SAndroid Build Coastguard Worker           }
524*f6dc9357SAndroid Build Coastguard Worker         }
525*f6dc9357SAndroid Build Coastguard Worker       }
526*f6dc9357SAndroid Build Coastguard Worker 
527*f6dc9357SAndroid Build Coastguard Worker       if (res == SZ_OK)
528*f6dc9357SAndroid Build Coastguard Worker         res = MtDec_GetError_Spec(p, blockIndex, &wasInterrupted);
529*f6dc9357SAndroid Build Coastguard Worker     }
530*f6dc9357SAndroid Build Coastguard Worker 
531*f6dc9357SAndroid Build Coastguard Worker     codeRes = SZ_OK;
532*f6dc9357SAndroid Build Coastguard Worker 
533*f6dc9357SAndroid Build Coastguard Worker     if (res == SZ_OK && needCode && !wasInterrupted)
534*f6dc9357SAndroid Build Coastguard Worker     {
535*f6dc9357SAndroid Build Coastguard Worker       codeRes = p->mtCallback->PreCode(p->mtCallbackObject, t->index);
536*f6dc9357SAndroid Build Coastguard Worker       if (codeRes != SZ_OK)
537*f6dc9357SAndroid Build Coastguard Worker       {
538*f6dc9357SAndroid Build Coastguard Worker         needCode = False;
539*f6dc9357SAndroid Build Coastguard Worker         finish = True;
540*f6dc9357SAndroid Build Coastguard Worker         // SZ_ERROR_MEM is expected error here.
541*f6dc9357SAndroid Build Coastguard Worker         //   if (codeRes == SZ_ERROR_MEM) - we will try single-thread decoding later.
542*f6dc9357SAndroid Build Coastguard Worker         //   if (codeRes != SZ_ERROR_MEM) - we can stop decoding or try single-thread decoding.
543*f6dc9357SAndroid Build Coastguard Worker       }
544*f6dc9357SAndroid Build Coastguard Worker     }
545*f6dc9357SAndroid Build Coastguard Worker 
546*f6dc9357SAndroid Build Coastguard Worker     if (res != SZ_OK || wasInterrupted)
547*f6dc9357SAndroid Build Coastguard Worker       finish = True;
548*f6dc9357SAndroid Build Coastguard Worker 
549*f6dc9357SAndroid Build Coastguard Worker     nextThread = NULL;
550*f6dc9357SAndroid Build Coastguard Worker     threadingErrorSRes = SZ_OK;
551*f6dc9357SAndroid Build Coastguard Worker 
552*f6dc9357SAndroid Build Coastguard Worker     if (!finish)
553*f6dc9357SAndroid Build Coastguard Worker     {
554*f6dc9357SAndroid Build Coastguard Worker       if (p->numStartedThreads < p->numStartedThreads_Limit && canCreateNewThread)
555*f6dc9357SAndroid Build Coastguard Worker       {
556*f6dc9357SAndroid Build Coastguard Worker         SRes res2 = MtDecThread_CreateAndStart(&p->threads[p->numStartedThreads]);
557*f6dc9357SAndroid Build Coastguard Worker         if (res2 == SZ_OK)
558*f6dc9357SAndroid Build Coastguard Worker         {
559*f6dc9357SAndroid Build Coastguard Worker           // if (p->numStartedThreads % 1000 == 0) PRF(printf("\n numStartedThreads=%d\n", p->numStartedThreads));
560*f6dc9357SAndroid Build Coastguard Worker           p->numStartedThreads++;
561*f6dc9357SAndroid Build Coastguard Worker         }
562*f6dc9357SAndroid Build Coastguard Worker         else
563*f6dc9357SAndroid Build Coastguard Worker         {
564*f6dc9357SAndroid Build Coastguard Worker           PRF(printf("\nERROR: numStartedThreads=%d\n", p->numStartedThreads));
565*f6dc9357SAndroid Build Coastguard Worker           if (p->numStartedThreads == 1)
566*f6dc9357SAndroid Build Coastguard Worker           {
567*f6dc9357SAndroid Build Coastguard Worker             // if only one thread is possible, we leave muti-threading code
568*f6dc9357SAndroid Build Coastguard Worker             finish = True;
569*f6dc9357SAndroid Build Coastguard Worker             needCode = False;
570*f6dc9357SAndroid Build Coastguard Worker             threadingErrorSRes = res2;
571*f6dc9357SAndroid Build Coastguard Worker           }
572*f6dc9357SAndroid Build Coastguard Worker           else
573*f6dc9357SAndroid Build Coastguard Worker             p->numStartedThreads_Limit = p->numStartedThreads;
574*f6dc9357SAndroid Build Coastguard Worker         }
575*f6dc9357SAndroid Build Coastguard Worker       }
576*f6dc9357SAndroid Build Coastguard Worker 
577*f6dc9357SAndroid Build Coastguard Worker       if (!finish)
578*f6dc9357SAndroid Build Coastguard Worker       {
579*f6dc9357SAndroid Build Coastguard Worker         unsigned nextIndex = t->index + 1;
580*f6dc9357SAndroid Build Coastguard Worker         nextThread = &p->threads[nextIndex >= p->numStartedThreads ? 0 : nextIndex];
581*f6dc9357SAndroid Build Coastguard Worker         RINOK_THREAD(Event_Set(&nextThread->canRead))
582*f6dc9357SAndroid Build Coastguard Worker         // We have started executing for new iteration (with next thread)
583*f6dc9357SAndroid Build Coastguard Worker         // And that next thread now is responsible for possible exit from decoding (threading_code)
584*f6dc9357SAndroid Build Coastguard Worker       }
585*f6dc9357SAndroid Build Coastguard Worker     }
586*f6dc9357SAndroid Build Coastguard Worker 
587*f6dc9357SAndroid Build Coastguard Worker     // each call of Event_Set(&nextThread->canRead) must be followed by call of Event_Set(&nextThread->canWrite)
588*f6dc9357SAndroid Build Coastguard Worker     // if ( !finish ) we must call Event_Set(&nextThread->canWrite) in any case
589*f6dc9357SAndroid Build Coastguard Worker     // if (  finish ) we switch to single-thread mode and there are 2 ways at the end of current iteration (current block):
590*f6dc9357SAndroid Build Coastguard Worker     //   - if (needContinue) after Write(&needContinue), we restore decoding with new iteration
591*f6dc9357SAndroid Build Coastguard Worker     //   - otherwise we stop decoding and exit from MtDec_ThreadFunc2()
592*f6dc9357SAndroid Build Coastguard Worker 
593*f6dc9357SAndroid Build Coastguard Worker     // Don't change (finish) variable in the further code
594*f6dc9357SAndroid Build Coastguard Worker 
595*f6dc9357SAndroid Build Coastguard Worker 
596*f6dc9357SAndroid Build Coastguard Worker     // ---------- CODE ----------
597*f6dc9357SAndroid Build Coastguard Worker 
598*f6dc9357SAndroid Build Coastguard Worker     inPrev = 0;
599*f6dc9357SAndroid Build Coastguard Worker     outPrev = 0;
600*f6dc9357SAndroid Build Coastguard Worker     inCodePos = 0;
601*f6dc9357SAndroid Build Coastguard Worker     outCodePos = 0;
602*f6dc9357SAndroid Build Coastguard Worker 
603*f6dc9357SAndroid Build Coastguard Worker     if (res == SZ_OK && needCode && codeRes == SZ_OK)
604*f6dc9357SAndroid Build Coastguard Worker     {
605*f6dc9357SAndroid Build Coastguard Worker       BoolInt isStartBlock = True;
606*f6dc9357SAndroid Build Coastguard Worker       CMtDecBufLink *link = (CMtDecBufLink *)t->inBuf;
607*f6dc9357SAndroid Build Coastguard Worker 
608*f6dc9357SAndroid Build Coastguard Worker       for (;;)
609*f6dc9357SAndroid Build Coastguard Worker       {
610*f6dc9357SAndroid Build Coastguard Worker         size_t inSize;
611*f6dc9357SAndroid Build Coastguard Worker         int stop;
612*f6dc9357SAndroid Build Coastguard Worker 
613*f6dc9357SAndroid Build Coastguard Worker         if (isStartBlock)
614*f6dc9357SAndroid Build Coastguard Worker           inSize = inDataSize_Start;
615*f6dc9357SAndroid Build Coastguard Worker         else
616*f6dc9357SAndroid Build Coastguard Worker         {
617*f6dc9357SAndroid Build Coastguard Worker           UInt64 rem = inDataSize - inCodePos;
618*f6dc9357SAndroid Build Coastguard Worker           inSize = p->inBufSize;
619*f6dc9357SAndroid Build Coastguard Worker           if (inSize > rem)
620*f6dc9357SAndroid Build Coastguard Worker             inSize = (size_t)rem;
621*f6dc9357SAndroid Build Coastguard Worker         }
622*f6dc9357SAndroid Build Coastguard Worker 
623*f6dc9357SAndroid Build Coastguard Worker         inCodePos += inSize;
624*f6dc9357SAndroid Build Coastguard Worker         stop = True;
625*f6dc9357SAndroid Build Coastguard Worker 
626*f6dc9357SAndroid Build Coastguard Worker         codeRes = p->mtCallback->Code(p->mtCallbackObject, t->index,
627*f6dc9357SAndroid Build Coastguard Worker             (const Byte *)MTDEC__DATA_PTR_FROM_LINK(link), inSize,
628*f6dc9357SAndroid Build Coastguard Worker             (inCodePos == inDataSize), // srcFinished
629*f6dc9357SAndroid Build Coastguard Worker             &inCodePos, &outCodePos, &stop);
630*f6dc9357SAndroid Build Coastguard Worker 
631*f6dc9357SAndroid Build Coastguard Worker         if (codeRes != SZ_OK)
632*f6dc9357SAndroid Build Coastguard Worker         {
633*f6dc9357SAndroid Build Coastguard Worker           PRF(printf("\nCode Interrupt error = %x\n", codeRes));
634*f6dc9357SAndroid Build Coastguard Worker           // we interrupt only later blocks
635*f6dc9357SAndroid Build Coastguard Worker           MtDec_Interrupt(p, blockIndex);
636*f6dc9357SAndroid Build Coastguard Worker           break;
637*f6dc9357SAndroid Build Coastguard Worker         }
638*f6dc9357SAndroid Build Coastguard Worker 
639*f6dc9357SAndroid Build Coastguard Worker         if (stop || inCodePos == inDataSize)
640*f6dc9357SAndroid Build Coastguard Worker           break;
641*f6dc9357SAndroid Build Coastguard Worker 
642*f6dc9357SAndroid Build Coastguard Worker         {
643*f6dc9357SAndroid Build Coastguard Worker           const UInt64 inDelta = inCodePos - inPrev;
644*f6dc9357SAndroid Build Coastguard Worker           const UInt64 outDelta = outCodePos - outPrev;
645*f6dc9357SAndroid Build Coastguard Worker           if (inDelta >= MTDEC_ProgessStep || outDelta >= MTDEC_ProgessStep)
646*f6dc9357SAndroid Build Coastguard Worker           {
647*f6dc9357SAndroid Build Coastguard Worker             // Sleep(1);
648*f6dc9357SAndroid Build Coastguard Worker             res = MtDec_Progress_GetError_Spec(p, inDelta, outDelta, blockIndex, &wasInterrupted);
649*f6dc9357SAndroid Build Coastguard Worker             if (res != SZ_OK || wasInterrupted)
650*f6dc9357SAndroid Build Coastguard Worker               break;
651*f6dc9357SAndroid Build Coastguard Worker             inPrev = inCodePos;
652*f6dc9357SAndroid Build Coastguard Worker             outPrev = outCodePos;
653*f6dc9357SAndroid Build Coastguard Worker           }
654*f6dc9357SAndroid Build Coastguard Worker         }
655*f6dc9357SAndroid Build Coastguard Worker 
656*f6dc9357SAndroid Build Coastguard Worker         link = link->next;
657*f6dc9357SAndroid Build Coastguard Worker         isStartBlock = False;
658*f6dc9357SAndroid Build Coastguard Worker       }
659*f6dc9357SAndroid Build Coastguard Worker     }
660*f6dc9357SAndroid Build Coastguard Worker 
661*f6dc9357SAndroid Build Coastguard Worker 
662*f6dc9357SAndroid Build Coastguard Worker     // ---------- WRITE ----------
663*f6dc9357SAndroid Build Coastguard Worker 
664*f6dc9357SAndroid Build Coastguard Worker     RINOK_THREAD(Event_Wait(&t->canWrite))
665*f6dc9357SAndroid Build Coastguard Worker 
666*f6dc9357SAndroid Build Coastguard Worker   {
667*f6dc9357SAndroid Build Coastguard Worker     BoolInt isErrorMode = False;
668*f6dc9357SAndroid Build Coastguard Worker     BoolInt canRecode = True;
669*f6dc9357SAndroid Build Coastguard Worker     BoolInt needWriteToStream = needWrite;
670*f6dc9357SAndroid Build Coastguard Worker 
671*f6dc9357SAndroid Build Coastguard Worker     if (p->exitThread) return 0; // it's never executed in normal cases
672*f6dc9357SAndroid Build Coastguard Worker 
673*f6dc9357SAndroid Build Coastguard Worker     if (p->wasInterrupted)
674*f6dc9357SAndroid Build Coastguard Worker       wasInterrupted = True;
675*f6dc9357SAndroid Build Coastguard Worker     else
676*f6dc9357SAndroid Build Coastguard Worker     {
677*f6dc9357SAndroid Build Coastguard Worker       if (codeRes != SZ_OK) // || !needCode // check it !!!
678*f6dc9357SAndroid Build Coastguard Worker       {
679*f6dc9357SAndroid Build Coastguard Worker         p->wasInterrupted = True;
680*f6dc9357SAndroid Build Coastguard Worker         p->codeRes = codeRes;
681*f6dc9357SAndroid Build Coastguard Worker         if (codeRes == SZ_ERROR_MEM)
682*f6dc9357SAndroid Build Coastguard Worker           isAllocError = True;
683*f6dc9357SAndroid Build Coastguard Worker       }
684*f6dc9357SAndroid Build Coastguard Worker 
685*f6dc9357SAndroid Build Coastguard Worker       if (threadingErrorSRes)
686*f6dc9357SAndroid Build Coastguard Worker       {
687*f6dc9357SAndroid Build Coastguard Worker         p->wasInterrupted = True;
688*f6dc9357SAndroid Build Coastguard Worker         p->threadingErrorSRes = threadingErrorSRes;
689*f6dc9357SAndroid Build Coastguard Worker         needWriteToStream = False;
690*f6dc9357SAndroid Build Coastguard Worker       }
691*f6dc9357SAndroid Build Coastguard Worker       if (isAllocError)
692*f6dc9357SAndroid Build Coastguard Worker       {
693*f6dc9357SAndroid Build Coastguard Worker         p->wasInterrupted = True;
694*f6dc9357SAndroid Build Coastguard Worker         p->isAllocError = True;
695*f6dc9357SAndroid Build Coastguard Worker         needWriteToStream = False;
696*f6dc9357SAndroid Build Coastguard Worker       }
697*f6dc9357SAndroid Build Coastguard Worker       if (overflow)
698*f6dc9357SAndroid Build Coastguard Worker       {
699*f6dc9357SAndroid Build Coastguard Worker         p->wasInterrupted = True;
700*f6dc9357SAndroid Build Coastguard Worker         p->overflow = True;
701*f6dc9357SAndroid Build Coastguard Worker         needWriteToStream = False;
702*f6dc9357SAndroid Build Coastguard Worker       }
703*f6dc9357SAndroid Build Coastguard Worker     }
704*f6dc9357SAndroid Build Coastguard Worker 
705*f6dc9357SAndroid Build Coastguard Worker     if (needCode)
706*f6dc9357SAndroid Build Coastguard Worker     {
707*f6dc9357SAndroid Build Coastguard Worker       if (wasInterrupted)
708*f6dc9357SAndroid Build Coastguard Worker       {
709*f6dc9357SAndroid Build Coastguard Worker         inCodePos = 0;
710*f6dc9357SAndroid Build Coastguard Worker         outCodePos = 0;
711*f6dc9357SAndroid Build Coastguard Worker       }
712*f6dc9357SAndroid Build Coastguard Worker       {
713*f6dc9357SAndroid Build Coastguard Worker         const UInt64 inDelta = inCodePos - inPrev;
714*f6dc9357SAndroid Build Coastguard Worker         const UInt64 outDelta = outCodePos - outPrev;
715*f6dc9357SAndroid Build Coastguard Worker         // if (inDelta != 0 || outDelta != 0)
716*f6dc9357SAndroid Build Coastguard Worker         res = MtProgress_ProgressAdd(&p->mtProgress, inDelta, outDelta);
717*f6dc9357SAndroid Build Coastguard Worker       }
718*f6dc9357SAndroid Build Coastguard Worker     }
719*f6dc9357SAndroid Build Coastguard Worker 
720*f6dc9357SAndroid Build Coastguard Worker     needContinue = (!finish);
721*f6dc9357SAndroid Build Coastguard Worker 
722*f6dc9357SAndroid Build Coastguard Worker     // if (res == SZ_OK && needWrite && !wasInterrupted)
723*f6dc9357SAndroid Build Coastguard Worker     if (needWrite)
724*f6dc9357SAndroid Build Coastguard Worker     {
725*f6dc9357SAndroid Build Coastguard Worker       // p->inProcessed += inCodePos;
726*f6dc9357SAndroid Build Coastguard Worker 
727*f6dc9357SAndroid Build Coastguard Worker       PRF(printf("\n--Write afterSize = %d\n", (unsigned)afterEndData_Size));
728*f6dc9357SAndroid Build Coastguard Worker 
729*f6dc9357SAndroid Build Coastguard Worker       res = p->mtCallback->Write(p->mtCallbackObject, t->index,
730*f6dc9357SAndroid Build Coastguard Worker           res == SZ_OK && needWriteToStream && !wasInterrupted, // needWrite
731*f6dc9357SAndroid Build Coastguard Worker           afterEndData, afterEndData_Size, afterEndData_IsCross,
732*f6dc9357SAndroid Build Coastguard Worker           &needContinue,
733*f6dc9357SAndroid Build Coastguard Worker           &canRecode);
734*f6dc9357SAndroid Build Coastguard Worker 
735*f6dc9357SAndroid Build Coastguard Worker       // res = SZ_ERROR_FAIL; // for test
736*f6dc9357SAndroid Build Coastguard Worker 
737*f6dc9357SAndroid Build Coastguard Worker       PRF(printf("\nAfter Write needContinue = %d\n", (unsigned)needContinue));
738*f6dc9357SAndroid Build Coastguard Worker       PRF(printf("\nprocessed = %d\n", (unsigned)p->inProcessed));
739*f6dc9357SAndroid Build Coastguard Worker 
740*f6dc9357SAndroid Build Coastguard Worker       if (res != SZ_OK)
741*f6dc9357SAndroid Build Coastguard Worker       {
742*f6dc9357SAndroid Build Coastguard Worker         PRF(printf("\nWrite error = %d\n", res));
743*f6dc9357SAndroid Build Coastguard Worker         isErrorMode = True;
744*f6dc9357SAndroid Build Coastguard Worker         p->wasInterrupted = True;
745*f6dc9357SAndroid Build Coastguard Worker       }
746*f6dc9357SAndroid Build Coastguard Worker       if (res != SZ_OK
747*f6dc9357SAndroid Build Coastguard Worker           || (!needContinue && !finish))
748*f6dc9357SAndroid Build Coastguard Worker       {
749*f6dc9357SAndroid Build Coastguard Worker         PRF(printf("\nWrite Interrupt error = %x\n", res));
750*f6dc9357SAndroid Build Coastguard Worker         MtDec_Interrupt(p, blockIndex);
751*f6dc9357SAndroid Build Coastguard Worker       }
752*f6dc9357SAndroid Build Coastguard Worker     }
753*f6dc9357SAndroid Build Coastguard Worker 
754*f6dc9357SAndroid Build Coastguard Worker     if (canRecode)
755*f6dc9357SAndroid Build Coastguard Worker     if (!needCode
756*f6dc9357SAndroid Build Coastguard Worker         || res != SZ_OK
757*f6dc9357SAndroid Build Coastguard Worker         || p->wasInterrupted
758*f6dc9357SAndroid Build Coastguard Worker         || codeRes != SZ_OK
759*f6dc9357SAndroid Build Coastguard Worker         || wasInterrupted
760*f6dc9357SAndroid Build Coastguard Worker         || p->numFilledThreads != 0
761*f6dc9357SAndroid Build Coastguard Worker         || isErrorMode)
762*f6dc9357SAndroid Build Coastguard Worker     {
763*f6dc9357SAndroid Build Coastguard Worker       if (p->numFilledThreads == 0)
764*f6dc9357SAndroid Build Coastguard Worker         p->filledThreadStart = t->index;
765*f6dc9357SAndroid Build Coastguard Worker       if (inDataSize != 0 || !finish)
766*f6dc9357SAndroid Build Coastguard Worker       {
767*f6dc9357SAndroid Build Coastguard Worker         t->inDataSize_Start = inDataSize_Start;
768*f6dc9357SAndroid Build Coastguard Worker         t->inDataSize = inDataSize;
769*f6dc9357SAndroid Build Coastguard Worker         p->numFilledThreads++;
770*f6dc9357SAndroid Build Coastguard Worker       }
771*f6dc9357SAndroid Build Coastguard Worker       PRF(printf("\np->numFilledThreads = %d\n", p->numFilledThreads));
772*f6dc9357SAndroid Build Coastguard Worker       PRF(printf("p->filledThreadStart = %d\n", p->filledThreadStart));
773*f6dc9357SAndroid Build Coastguard Worker     }
774*f6dc9357SAndroid Build Coastguard Worker 
775*f6dc9357SAndroid Build Coastguard Worker     if (!finish)
776*f6dc9357SAndroid Build Coastguard Worker     {
777*f6dc9357SAndroid Build Coastguard Worker       RINOK_THREAD(Event_Set(&nextThread->canWrite))
778*f6dc9357SAndroid Build Coastguard Worker     }
779*f6dc9357SAndroid Build Coastguard Worker     else
780*f6dc9357SAndroid Build Coastguard Worker     {
781*f6dc9357SAndroid Build Coastguard Worker       if (needContinue)
782*f6dc9357SAndroid Build Coastguard Worker       {
783*f6dc9357SAndroid Build Coastguard Worker         // we restore decoding with new iteration
784*f6dc9357SAndroid Build Coastguard Worker         RINOK_THREAD(Event_Set(&p->threads[0].canWrite))
785*f6dc9357SAndroid Build Coastguard Worker       }
786*f6dc9357SAndroid Build Coastguard Worker       else
787*f6dc9357SAndroid Build Coastguard Worker       {
788*f6dc9357SAndroid Build Coastguard Worker         // we exit from decoding
789*f6dc9357SAndroid Build Coastguard Worker         if (t->index == 0)
790*f6dc9357SAndroid Build Coastguard Worker           return SZ_OK;
791*f6dc9357SAndroid Build Coastguard Worker         p->exitThread = True;
792*f6dc9357SAndroid Build Coastguard Worker       }
793*f6dc9357SAndroid Build Coastguard Worker       RINOK_THREAD(Event_Set(&p->threads[0].canRead))
794*f6dc9357SAndroid Build Coastguard Worker     }
795*f6dc9357SAndroid Build Coastguard Worker   }
796*f6dc9357SAndroid Build Coastguard Worker   }
797*f6dc9357SAndroid Build Coastguard Worker }
798*f6dc9357SAndroid Build Coastguard Worker 
799*f6dc9357SAndroid Build Coastguard Worker #ifdef _WIN32
800*f6dc9357SAndroid Build Coastguard Worker #define USE_ALLOCA
801*f6dc9357SAndroid Build Coastguard Worker #endif
802*f6dc9357SAndroid Build Coastguard Worker 
803*f6dc9357SAndroid Build Coastguard Worker #ifdef USE_ALLOCA
804*f6dc9357SAndroid Build Coastguard Worker #ifdef _WIN32
805*f6dc9357SAndroid Build Coastguard Worker #include <malloc.h>
806*f6dc9357SAndroid Build Coastguard Worker #else
807*f6dc9357SAndroid Build Coastguard Worker #include <stdlib.h>
808*f6dc9357SAndroid Build Coastguard Worker #endif
809*f6dc9357SAndroid Build Coastguard Worker #endif
810*f6dc9357SAndroid Build Coastguard Worker 
811*f6dc9357SAndroid Build Coastguard Worker 
812*f6dc9357SAndroid Build Coastguard Worker typedef
813*f6dc9357SAndroid Build Coastguard Worker   #ifdef _WIN32
814*f6dc9357SAndroid Build Coastguard Worker     UINT_PTR
815*f6dc9357SAndroid Build Coastguard Worker   #elif 1
816*f6dc9357SAndroid Build Coastguard Worker     uintptr_t
817*f6dc9357SAndroid Build Coastguard Worker   #else
818*f6dc9357SAndroid Build Coastguard Worker     ptrdiff_t
819*f6dc9357SAndroid Build Coastguard Worker   #endif
820*f6dc9357SAndroid Build Coastguard Worker     MY_uintptr_t;
821*f6dc9357SAndroid Build Coastguard Worker 
MtDec_ThreadFunc1(void * pp)822*f6dc9357SAndroid Build Coastguard Worker static THREAD_FUNC_DECL MtDec_ThreadFunc1(void *pp)
823*f6dc9357SAndroid Build Coastguard Worker {
824*f6dc9357SAndroid Build Coastguard Worker   WRes res;
825*f6dc9357SAndroid Build Coastguard Worker 
826*f6dc9357SAndroid Build Coastguard Worker   CMtDecThread *t = (CMtDecThread *)pp;
827*f6dc9357SAndroid Build Coastguard Worker   CMtDec *p;
828*f6dc9357SAndroid Build Coastguard Worker 
829*f6dc9357SAndroid Build Coastguard Worker   // fprintf(stdout, "\n%d = %p\n", t->index, &t);
830*f6dc9357SAndroid Build Coastguard Worker 
831*f6dc9357SAndroid Build Coastguard Worker   res = MtDec_ThreadFunc2(t);
832*f6dc9357SAndroid Build Coastguard Worker   p = t->mtDec;
833*f6dc9357SAndroid Build Coastguard Worker   if (res == 0)
834*f6dc9357SAndroid Build Coastguard Worker     return (THREAD_FUNC_RET_TYPE)(MY_uintptr_t)p->exitThreadWRes;
835*f6dc9357SAndroid Build Coastguard Worker   {
836*f6dc9357SAndroid Build Coastguard Worker     // it's unexpected situation for some threading function error
837*f6dc9357SAndroid Build Coastguard Worker     if (p->exitThreadWRes == 0)
838*f6dc9357SAndroid Build Coastguard Worker       p->exitThreadWRes = res;
839*f6dc9357SAndroid Build Coastguard Worker     PRF(printf("\nthread exit error = %d\n", res));
840*f6dc9357SAndroid Build Coastguard Worker     p->exitThread = True;
841*f6dc9357SAndroid Build Coastguard Worker     Event_Set(&p->threads[0].canRead);
842*f6dc9357SAndroid Build Coastguard Worker     Event_Set(&p->threads[0].canWrite);
843*f6dc9357SAndroid Build Coastguard Worker     MtProgress_SetError(&p->mtProgress, MY_SRes_HRESULT_FROM_WRes(res));
844*f6dc9357SAndroid Build Coastguard Worker   }
845*f6dc9357SAndroid Build Coastguard Worker   return (THREAD_FUNC_RET_TYPE)(MY_uintptr_t)res;
846*f6dc9357SAndroid Build Coastguard Worker }
847*f6dc9357SAndroid Build Coastguard Worker 
MtDec_ThreadFunc(void * pp)848*f6dc9357SAndroid Build Coastguard Worker static Z7_NO_INLINE THREAD_FUNC_DECL MtDec_ThreadFunc(void *pp)
849*f6dc9357SAndroid Build Coastguard Worker {
850*f6dc9357SAndroid Build Coastguard Worker   #ifdef USE_ALLOCA
851*f6dc9357SAndroid Build Coastguard Worker   CMtDecThread *t = (CMtDecThread *)pp;
852*f6dc9357SAndroid Build Coastguard Worker   // fprintf(stderr, "\n%d = %p - before", t->index, &t);
853*f6dc9357SAndroid Build Coastguard Worker   t->allocaPtr = alloca(t->index * 128);
854*f6dc9357SAndroid Build Coastguard Worker   #endif
855*f6dc9357SAndroid Build Coastguard Worker   return MtDec_ThreadFunc1(pp);
856*f6dc9357SAndroid Build Coastguard Worker }
857*f6dc9357SAndroid Build Coastguard Worker 
858*f6dc9357SAndroid Build Coastguard Worker 
MtDec_PrepareRead(CMtDec * p)859*f6dc9357SAndroid Build Coastguard Worker int MtDec_PrepareRead(CMtDec *p)
860*f6dc9357SAndroid Build Coastguard Worker {
861*f6dc9357SAndroid Build Coastguard Worker   if (p->crossBlock && p->crossStart == p->crossEnd)
862*f6dc9357SAndroid Build Coastguard Worker   {
863*f6dc9357SAndroid Build Coastguard Worker     ISzAlloc_Free(p->alloc, p->crossBlock);
864*f6dc9357SAndroid Build Coastguard Worker     p->crossBlock = NULL;
865*f6dc9357SAndroid Build Coastguard Worker   }
866*f6dc9357SAndroid Build Coastguard Worker 
867*f6dc9357SAndroid Build Coastguard Worker   {
868*f6dc9357SAndroid Build Coastguard Worker     unsigned i;
869*f6dc9357SAndroid Build Coastguard Worker     for (i = 0; i < MTDEC_THREADS_MAX; i++)
870*f6dc9357SAndroid Build Coastguard Worker       if (i > p->numStartedThreads
871*f6dc9357SAndroid Build Coastguard Worker           || p->numFilledThreads <=
872*f6dc9357SAndroid Build Coastguard Worker             (i >= p->filledThreadStart ?
873*f6dc9357SAndroid Build Coastguard Worker               i - p->filledThreadStart :
874*f6dc9357SAndroid Build Coastguard Worker               i + p->numStartedThreads - p->filledThreadStart))
875*f6dc9357SAndroid Build Coastguard Worker         MtDecThread_FreeInBufs(&p->threads[i]);
876*f6dc9357SAndroid Build Coastguard Worker   }
877*f6dc9357SAndroid Build Coastguard Worker 
878*f6dc9357SAndroid Build Coastguard Worker   return (p->numFilledThreads != 0) || (p->crossStart != p->crossEnd);
879*f6dc9357SAndroid Build Coastguard Worker }
880*f6dc9357SAndroid Build Coastguard Worker 
881*f6dc9357SAndroid Build Coastguard Worker 
MtDec_Read(CMtDec * p,size_t * inLim)882*f6dc9357SAndroid Build Coastguard Worker const Byte *MtDec_Read(CMtDec *p, size_t *inLim)
883*f6dc9357SAndroid Build Coastguard Worker {
884*f6dc9357SAndroid Build Coastguard Worker   while (p->numFilledThreads != 0)
885*f6dc9357SAndroid Build Coastguard Worker   {
886*f6dc9357SAndroid Build Coastguard Worker     CMtDecThread *t = &p->threads[p->filledThreadStart];
887*f6dc9357SAndroid Build Coastguard Worker 
888*f6dc9357SAndroid Build Coastguard Worker     if (*inLim != 0)
889*f6dc9357SAndroid Build Coastguard Worker     {
890*f6dc9357SAndroid Build Coastguard Worker       {
891*f6dc9357SAndroid Build Coastguard Worker         void *link = t->inBuf;
892*f6dc9357SAndroid Build Coastguard Worker         void *next = ((CMtDecBufLink *)link)->next;
893*f6dc9357SAndroid Build Coastguard Worker         ISzAlloc_Free(p->alloc, link);
894*f6dc9357SAndroid Build Coastguard Worker         t->inBuf = next;
895*f6dc9357SAndroid Build Coastguard Worker       }
896*f6dc9357SAndroid Build Coastguard Worker 
897*f6dc9357SAndroid Build Coastguard Worker       if (t->inDataSize == 0)
898*f6dc9357SAndroid Build Coastguard Worker       {
899*f6dc9357SAndroid Build Coastguard Worker         MtDecThread_FreeInBufs(t);
900*f6dc9357SAndroid Build Coastguard Worker         if (--p->numFilledThreads == 0)
901*f6dc9357SAndroid Build Coastguard Worker           break;
902*f6dc9357SAndroid Build Coastguard Worker         if (++p->filledThreadStart == p->numStartedThreads)
903*f6dc9357SAndroid Build Coastguard Worker           p->filledThreadStart = 0;
904*f6dc9357SAndroid Build Coastguard Worker         t = &p->threads[p->filledThreadStart];
905*f6dc9357SAndroid Build Coastguard Worker       }
906*f6dc9357SAndroid Build Coastguard Worker     }
907*f6dc9357SAndroid Build Coastguard Worker 
908*f6dc9357SAndroid Build Coastguard Worker     {
909*f6dc9357SAndroid Build Coastguard Worker       size_t lim = t->inDataSize_Start;
910*f6dc9357SAndroid Build Coastguard Worker       if (lim != 0)
911*f6dc9357SAndroid Build Coastguard Worker         t->inDataSize_Start = 0;
912*f6dc9357SAndroid Build Coastguard Worker       else
913*f6dc9357SAndroid Build Coastguard Worker       {
914*f6dc9357SAndroid Build Coastguard Worker         UInt64 rem = t->inDataSize;
915*f6dc9357SAndroid Build Coastguard Worker         lim = p->inBufSize;
916*f6dc9357SAndroid Build Coastguard Worker         if (lim > rem)
917*f6dc9357SAndroid Build Coastguard Worker           lim = (size_t)rem;
918*f6dc9357SAndroid Build Coastguard Worker       }
919*f6dc9357SAndroid Build Coastguard Worker       t->inDataSize -= lim;
920*f6dc9357SAndroid Build Coastguard Worker       *inLim = lim;
921*f6dc9357SAndroid Build Coastguard Worker       return (const Byte *)MTDEC__DATA_PTR_FROM_LINK(t->inBuf);
922*f6dc9357SAndroid Build Coastguard Worker     }
923*f6dc9357SAndroid Build Coastguard Worker   }
924*f6dc9357SAndroid Build Coastguard Worker 
925*f6dc9357SAndroid Build Coastguard Worker   {
926*f6dc9357SAndroid Build Coastguard Worker     size_t crossSize = p->crossEnd - p->crossStart;
927*f6dc9357SAndroid Build Coastguard Worker     if (crossSize != 0)
928*f6dc9357SAndroid Build Coastguard Worker     {
929*f6dc9357SAndroid Build Coastguard Worker       const Byte *data = MTDEC__DATA_PTR_FROM_LINK(p->crossBlock) + p->crossStart;
930*f6dc9357SAndroid Build Coastguard Worker       *inLim = crossSize;
931*f6dc9357SAndroid Build Coastguard Worker       p->crossStart = 0;
932*f6dc9357SAndroid Build Coastguard Worker       p->crossEnd = 0;
933*f6dc9357SAndroid Build Coastguard Worker       return data;
934*f6dc9357SAndroid Build Coastguard Worker     }
935*f6dc9357SAndroid Build Coastguard Worker     *inLim = 0;
936*f6dc9357SAndroid Build Coastguard Worker     if (p->crossBlock)
937*f6dc9357SAndroid Build Coastguard Worker     {
938*f6dc9357SAndroid Build Coastguard Worker       ISzAlloc_Free(p->alloc, p->crossBlock);
939*f6dc9357SAndroid Build Coastguard Worker       p->crossBlock = NULL;
940*f6dc9357SAndroid Build Coastguard Worker     }
941*f6dc9357SAndroid Build Coastguard Worker     return NULL;
942*f6dc9357SAndroid Build Coastguard Worker   }
943*f6dc9357SAndroid Build Coastguard Worker }
944*f6dc9357SAndroid Build Coastguard Worker 
945*f6dc9357SAndroid Build Coastguard Worker 
MtDec_Construct(CMtDec * p)946*f6dc9357SAndroid Build Coastguard Worker void MtDec_Construct(CMtDec *p)
947*f6dc9357SAndroid Build Coastguard Worker {
948*f6dc9357SAndroid Build Coastguard Worker   unsigned i;
949*f6dc9357SAndroid Build Coastguard Worker 
950*f6dc9357SAndroid Build Coastguard Worker   p->inBufSize = (size_t)1 << 18;
951*f6dc9357SAndroid Build Coastguard Worker 
952*f6dc9357SAndroid Build Coastguard Worker   p->numThreadsMax = 0;
953*f6dc9357SAndroid Build Coastguard Worker 
954*f6dc9357SAndroid Build Coastguard Worker   p->inStream = NULL;
955*f6dc9357SAndroid Build Coastguard Worker 
956*f6dc9357SAndroid Build Coastguard Worker   // p->inData = NULL;
957*f6dc9357SAndroid Build Coastguard Worker   // p->inDataSize = 0;
958*f6dc9357SAndroid Build Coastguard Worker 
959*f6dc9357SAndroid Build Coastguard Worker   p->crossBlock = NULL;
960*f6dc9357SAndroid Build Coastguard Worker   p->crossStart = 0;
961*f6dc9357SAndroid Build Coastguard Worker   p->crossEnd = 0;
962*f6dc9357SAndroid Build Coastguard Worker 
963*f6dc9357SAndroid Build Coastguard Worker   p->numFilledThreads = 0;
964*f6dc9357SAndroid Build Coastguard Worker 
965*f6dc9357SAndroid Build Coastguard Worker   p->progress = NULL;
966*f6dc9357SAndroid Build Coastguard Worker   p->alloc = NULL;
967*f6dc9357SAndroid Build Coastguard Worker 
968*f6dc9357SAndroid Build Coastguard Worker   p->mtCallback = NULL;
969*f6dc9357SAndroid Build Coastguard Worker   p->mtCallbackObject = NULL;
970*f6dc9357SAndroid Build Coastguard Worker 
971*f6dc9357SAndroid Build Coastguard Worker   p->allocatedBufsSize = 0;
972*f6dc9357SAndroid Build Coastguard Worker 
973*f6dc9357SAndroid Build Coastguard Worker   for (i = 0; i < MTDEC_THREADS_MAX; i++)
974*f6dc9357SAndroid Build Coastguard Worker   {
975*f6dc9357SAndroid Build Coastguard Worker     CMtDecThread *t = &p->threads[i];
976*f6dc9357SAndroid Build Coastguard Worker     t->mtDec = p;
977*f6dc9357SAndroid Build Coastguard Worker     t->index = i;
978*f6dc9357SAndroid Build Coastguard Worker     t->inBuf = NULL;
979*f6dc9357SAndroid Build Coastguard Worker     Event_Construct(&t->canRead);
980*f6dc9357SAndroid Build Coastguard Worker     Event_Construct(&t->canWrite);
981*f6dc9357SAndroid Build Coastguard Worker     Thread_CONSTRUCT(&t->thread)
982*f6dc9357SAndroid Build Coastguard Worker   }
983*f6dc9357SAndroid Build Coastguard Worker 
984*f6dc9357SAndroid Build Coastguard Worker   // Event_Construct(&p->finishedEvent);
985*f6dc9357SAndroid Build Coastguard Worker 
986*f6dc9357SAndroid Build Coastguard Worker   CriticalSection_Init(&p->mtProgress.cs);
987*f6dc9357SAndroid Build Coastguard Worker }
988*f6dc9357SAndroid Build Coastguard Worker 
989*f6dc9357SAndroid Build Coastguard Worker 
MtDec_Free(CMtDec * p)990*f6dc9357SAndroid Build Coastguard Worker static void MtDec_Free(CMtDec *p)
991*f6dc9357SAndroid Build Coastguard Worker {
992*f6dc9357SAndroid Build Coastguard Worker   unsigned i;
993*f6dc9357SAndroid Build Coastguard Worker 
994*f6dc9357SAndroid Build Coastguard Worker   p->exitThread = True;
995*f6dc9357SAndroid Build Coastguard Worker 
996*f6dc9357SAndroid Build Coastguard Worker   for (i = 0; i < MTDEC_THREADS_MAX; i++)
997*f6dc9357SAndroid Build Coastguard Worker     MtDecThread_Destruct(&p->threads[i]);
998*f6dc9357SAndroid Build Coastguard Worker 
999*f6dc9357SAndroid Build Coastguard Worker   // Event_Close(&p->finishedEvent);
1000*f6dc9357SAndroid Build Coastguard Worker 
1001*f6dc9357SAndroid Build Coastguard Worker   if (p->crossBlock)
1002*f6dc9357SAndroid Build Coastguard Worker   {
1003*f6dc9357SAndroid Build Coastguard Worker     ISzAlloc_Free(p->alloc, p->crossBlock);
1004*f6dc9357SAndroid Build Coastguard Worker     p->crossBlock = NULL;
1005*f6dc9357SAndroid Build Coastguard Worker   }
1006*f6dc9357SAndroid Build Coastguard Worker }
1007*f6dc9357SAndroid Build Coastguard Worker 
1008*f6dc9357SAndroid Build Coastguard Worker 
MtDec_Destruct(CMtDec * p)1009*f6dc9357SAndroid Build Coastguard Worker void MtDec_Destruct(CMtDec *p)
1010*f6dc9357SAndroid Build Coastguard Worker {
1011*f6dc9357SAndroid Build Coastguard Worker   MtDec_Free(p);
1012*f6dc9357SAndroid Build Coastguard Worker 
1013*f6dc9357SAndroid Build Coastguard Worker   CriticalSection_Delete(&p->mtProgress.cs);
1014*f6dc9357SAndroid Build Coastguard Worker }
1015*f6dc9357SAndroid Build Coastguard Worker 
1016*f6dc9357SAndroid Build Coastguard Worker 
MtDec_Code(CMtDec * p)1017*f6dc9357SAndroid Build Coastguard Worker SRes MtDec_Code(CMtDec *p)
1018*f6dc9357SAndroid Build Coastguard Worker {
1019*f6dc9357SAndroid Build Coastguard Worker   unsigned i;
1020*f6dc9357SAndroid Build Coastguard Worker 
1021*f6dc9357SAndroid Build Coastguard Worker   p->inProcessed = 0;
1022*f6dc9357SAndroid Build Coastguard Worker 
1023*f6dc9357SAndroid Build Coastguard Worker   p->blockIndex = 1; // it must be larger than not_defined index (0)
1024*f6dc9357SAndroid Build Coastguard Worker   p->isAllocError = False;
1025*f6dc9357SAndroid Build Coastguard Worker   p->overflow = False;
1026*f6dc9357SAndroid Build Coastguard Worker   p->threadingErrorSRes = SZ_OK;
1027*f6dc9357SAndroid Build Coastguard Worker 
1028*f6dc9357SAndroid Build Coastguard Worker   p->needContinue = True;
1029*f6dc9357SAndroid Build Coastguard Worker 
1030*f6dc9357SAndroid Build Coastguard Worker   p->readWasFinished = False;
1031*f6dc9357SAndroid Build Coastguard Worker   p->needInterrupt = False;
1032*f6dc9357SAndroid Build Coastguard Worker   p->interruptIndex = (UInt64)(Int64)-1;
1033*f6dc9357SAndroid Build Coastguard Worker 
1034*f6dc9357SAndroid Build Coastguard Worker   p->readProcessed = 0;
1035*f6dc9357SAndroid Build Coastguard Worker   p->readRes = SZ_OK;
1036*f6dc9357SAndroid Build Coastguard Worker   p->codeRes = SZ_OK;
1037*f6dc9357SAndroid Build Coastguard Worker   p->wasInterrupted = False;
1038*f6dc9357SAndroid Build Coastguard Worker 
1039*f6dc9357SAndroid Build Coastguard Worker   p->crossStart = 0;
1040*f6dc9357SAndroid Build Coastguard Worker   p->crossEnd = 0;
1041*f6dc9357SAndroid Build Coastguard Worker 
1042*f6dc9357SAndroid Build Coastguard Worker   p->filledThreadStart = 0;
1043*f6dc9357SAndroid Build Coastguard Worker   p->numFilledThreads = 0;
1044*f6dc9357SAndroid Build Coastguard Worker 
1045*f6dc9357SAndroid Build Coastguard Worker   {
1046*f6dc9357SAndroid Build Coastguard Worker     unsigned numThreads = p->numThreadsMax;
1047*f6dc9357SAndroid Build Coastguard Worker     if (numThreads > MTDEC_THREADS_MAX)
1048*f6dc9357SAndroid Build Coastguard Worker       numThreads = MTDEC_THREADS_MAX;
1049*f6dc9357SAndroid Build Coastguard Worker     p->numStartedThreads_Limit = numThreads;
1050*f6dc9357SAndroid Build Coastguard Worker     p->numStartedThreads = 0;
1051*f6dc9357SAndroid Build Coastguard Worker   }
1052*f6dc9357SAndroid Build Coastguard Worker 
1053*f6dc9357SAndroid Build Coastguard Worker   if (p->inBufSize != p->allocatedBufsSize)
1054*f6dc9357SAndroid Build Coastguard Worker   {
1055*f6dc9357SAndroid Build Coastguard Worker     for (i = 0; i < MTDEC_THREADS_MAX; i++)
1056*f6dc9357SAndroid Build Coastguard Worker     {
1057*f6dc9357SAndroid Build Coastguard Worker       CMtDecThread *t = &p->threads[i];
1058*f6dc9357SAndroid Build Coastguard Worker       if (t->inBuf)
1059*f6dc9357SAndroid Build Coastguard Worker         MtDecThread_FreeInBufs(t);
1060*f6dc9357SAndroid Build Coastguard Worker     }
1061*f6dc9357SAndroid Build Coastguard Worker     if (p->crossBlock)
1062*f6dc9357SAndroid Build Coastguard Worker     {
1063*f6dc9357SAndroid Build Coastguard Worker       ISzAlloc_Free(p->alloc, p->crossBlock);
1064*f6dc9357SAndroid Build Coastguard Worker       p->crossBlock = NULL;
1065*f6dc9357SAndroid Build Coastguard Worker     }
1066*f6dc9357SAndroid Build Coastguard Worker 
1067*f6dc9357SAndroid Build Coastguard Worker     p->allocatedBufsSize = p->inBufSize;
1068*f6dc9357SAndroid Build Coastguard Worker   }
1069*f6dc9357SAndroid Build Coastguard Worker 
1070*f6dc9357SAndroid Build Coastguard Worker   MtProgress_Init(&p->mtProgress, p->progress);
1071*f6dc9357SAndroid Build Coastguard Worker 
1072*f6dc9357SAndroid Build Coastguard Worker   // RINOK_THREAD(AutoResetEvent_OptCreate_And_Reset(&p->finishedEvent))
1073*f6dc9357SAndroid Build Coastguard Worker   p->exitThread = False;
1074*f6dc9357SAndroid Build Coastguard Worker   p->exitThreadWRes = 0;
1075*f6dc9357SAndroid Build Coastguard Worker 
1076*f6dc9357SAndroid Build Coastguard Worker   {
1077*f6dc9357SAndroid Build Coastguard Worker     WRes wres;
1078*f6dc9357SAndroid Build Coastguard Worker     SRes sres;
1079*f6dc9357SAndroid Build Coastguard Worker     CMtDecThread *nextThread = &p->threads[p->numStartedThreads++];
1080*f6dc9357SAndroid Build Coastguard Worker     // wres = MtDecThread_CreateAndStart(nextThread);
1081*f6dc9357SAndroid Build Coastguard Worker     wres = MtDecThread_CreateEvents(nextThread);
1082*f6dc9357SAndroid Build Coastguard Worker     if (wres == 0) { wres = Event_Set(&nextThread->canWrite);
1083*f6dc9357SAndroid Build Coastguard Worker     if (wres == 0) { wres = Event_Set(&nextThread->canRead);
1084*f6dc9357SAndroid Build Coastguard Worker     if (wres == 0) { THREAD_FUNC_RET_TYPE res = MtDec_ThreadFunc(nextThread);
1085*f6dc9357SAndroid Build Coastguard Worker     wres = (WRes)(MY_uintptr_t)res;
1086*f6dc9357SAndroid Build Coastguard Worker     if (wres != 0)
1087*f6dc9357SAndroid Build Coastguard Worker     {
1088*f6dc9357SAndroid Build Coastguard Worker       p->needContinue = False;
1089*f6dc9357SAndroid Build Coastguard Worker       MtDec_CloseThreads(p);
1090*f6dc9357SAndroid Build Coastguard Worker     }}}}
1091*f6dc9357SAndroid Build Coastguard Worker 
1092*f6dc9357SAndroid Build Coastguard Worker     // wres = 17; // for test
1093*f6dc9357SAndroid Build Coastguard Worker     // wres = Event_Wait(&p->finishedEvent);
1094*f6dc9357SAndroid Build Coastguard Worker 
1095*f6dc9357SAndroid Build Coastguard Worker     sres = MY_SRes_HRESULT_FROM_WRes(wres);
1096*f6dc9357SAndroid Build Coastguard Worker 
1097*f6dc9357SAndroid Build Coastguard Worker     if (sres != 0)
1098*f6dc9357SAndroid Build Coastguard Worker       p->threadingErrorSRes = sres;
1099*f6dc9357SAndroid Build Coastguard Worker 
1100*f6dc9357SAndroid Build Coastguard Worker     if (
1101*f6dc9357SAndroid Build Coastguard Worker         // wres == 0
1102*f6dc9357SAndroid Build Coastguard Worker         // wres != 0
1103*f6dc9357SAndroid Build Coastguard Worker         // || p->mtc.codeRes == SZ_ERROR_MEM
1104*f6dc9357SAndroid Build Coastguard Worker         p->isAllocError
1105*f6dc9357SAndroid Build Coastguard Worker         || p->threadingErrorSRes != SZ_OK
1106*f6dc9357SAndroid Build Coastguard Worker         || p->overflow)
1107*f6dc9357SAndroid Build Coastguard Worker     {
1108*f6dc9357SAndroid Build Coastguard Worker       // p->needContinue = True;
1109*f6dc9357SAndroid Build Coastguard Worker     }
1110*f6dc9357SAndroid Build Coastguard Worker     else
1111*f6dc9357SAndroid Build Coastguard Worker       p->needContinue = False;
1112*f6dc9357SAndroid Build Coastguard Worker 
1113*f6dc9357SAndroid Build Coastguard Worker     if (p->needContinue)
1114*f6dc9357SAndroid Build Coastguard Worker       return SZ_OK;
1115*f6dc9357SAndroid Build Coastguard Worker 
1116*f6dc9357SAndroid Build Coastguard Worker     // if (sres != SZ_OK)
1117*f6dc9357SAndroid Build Coastguard Worker     return sres;
1118*f6dc9357SAndroid Build Coastguard Worker     // return SZ_ERROR_FAIL;
1119*f6dc9357SAndroid Build Coastguard Worker   }
1120*f6dc9357SAndroid Build Coastguard Worker }
1121*f6dc9357SAndroid Build Coastguard Worker 
1122*f6dc9357SAndroid Build Coastguard Worker #endif
1123*f6dc9357SAndroid Build Coastguard Worker 
1124*f6dc9357SAndroid Build Coastguard Worker #undef PRF
1125