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