1370b324cSopenharmony_ci/* MtDec.c -- Multi-thread Decoder 2370b324cSopenharmony_ci2023-04-02 : Igor Pavlov : Public domain */ 3370b324cSopenharmony_ci 4370b324cSopenharmony_ci#include "Precomp.h" 5370b324cSopenharmony_ci 6370b324cSopenharmony_ci// #define SHOW_DEBUG_INFO 7370b324cSopenharmony_ci 8370b324cSopenharmony_ci// #include <stdio.h> 9370b324cSopenharmony_ci#include <string.h> 10370b324cSopenharmony_ci 11370b324cSopenharmony_ci#ifdef SHOW_DEBUG_INFO 12370b324cSopenharmony_ci#include <stdio.h> 13370b324cSopenharmony_ci#endif 14370b324cSopenharmony_ci 15370b324cSopenharmony_ci#include "MtDec.h" 16370b324cSopenharmony_ci 17370b324cSopenharmony_ci#ifndef Z7_ST 18370b324cSopenharmony_ci 19370b324cSopenharmony_ci#ifdef SHOW_DEBUG_INFO 20370b324cSopenharmony_ci#define PRF(x) x 21370b324cSopenharmony_ci#else 22370b324cSopenharmony_ci#define PRF(x) 23370b324cSopenharmony_ci#endif 24370b324cSopenharmony_ci 25370b324cSopenharmony_ci#define PRF_STR_INT(s, d) PRF(printf("\n" s " %d\n", (unsigned)d)) 26370b324cSopenharmony_ci 27370b324cSopenharmony_civoid MtProgress_Init(CMtProgress *p, ICompressProgressPtr progress) 28370b324cSopenharmony_ci{ 29370b324cSopenharmony_ci p->progress = progress; 30370b324cSopenharmony_ci p->res = SZ_OK; 31370b324cSopenharmony_ci p->totalInSize = 0; 32370b324cSopenharmony_ci p->totalOutSize = 0; 33370b324cSopenharmony_ci} 34370b324cSopenharmony_ci 35370b324cSopenharmony_ci 36370b324cSopenharmony_ciSRes MtProgress_Progress_ST(CMtProgress *p) 37370b324cSopenharmony_ci{ 38370b324cSopenharmony_ci if (p->res == SZ_OK && p->progress) 39370b324cSopenharmony_ci if (ICompressProgress_Progress(p->progress, p->totalInSize, p->totalOutSize) != SZ_OK) 40370b324cSopenharmony_ci p->res = SZ_ERROR_PROGRESS; 41370b324cSopenharmony_ci return p->res; 42370b324cSopenharmony_ci} 43370b324cSopenharmony_ci 44370b324cSopenharmony_ci 45370b324cSopenharmony_ciSRes MtProgress_ProgressAdd(CMtProgress *p, UInt64 inSize, UInt64 outSize) 46370b324cSopenharmony_ci{ 47370b324cSopenharmony_ci SRes res; 48370b324cSopenharmony_ci CriticalSection_Enter(&p->cs); 49370b324cSopenharmony_ci 50370b324cSopenharmony_ci p->totalInSize += inSize; 51370b324cSopenharmony_ci p->totalOutSize += outSize; 52370b324cSopenharmony_ci if (p->res == SZ_OK && p->progress) 53370b324cSopenharmony_ci if (ICompressProgress_Progress(p->progress, p->totalInSize, p->totalOutSize) != SZ_OK) 54370b324cSopenharmony_ci p->res = SZ_ERROR_PROGRESS; 55370b324cSopenharmony_ci res = p->res; 56370b324cSopenharmony_ci 57370b324cSopenharmony_ci CriticalSection_Leave(&p->cs); 58370b324cSopenharmony_ci return res; 59370b324cSopenharmony_ci} 60370b324cSopenharmony_ci 61370b324cSopenharmony_ci 62370b324cSopenharmony_ciSRes MtProgress_GetError(CMtProgress *p) 63370b324cSopenharmony_ci{ 64370b324cSopenharmony_ci SRes res; 65370b324cSopenharmony_ci CriticalSection_Enter(&p->cs); 66370b324cSopenharmony_ci res = p->res; 67370b324cSopenharmony_ci CriticalSection_Leave(&p->cs); 68370b324cSopenharmony_ci return res; 69370b324cSopenharmony_ci} 70370b324cSopenharmony_ci 71370b324cSopenharmony_ci 72370b324cSopenharmony_civoid MtProgress_SetError(CMtProgress *p, SRes res) 73370b324cSopenharmony_ci{ 74370b324cSopenharmony_ci CriticalSection_Enter(&p->cs); 75370b324cSopenharmony_ci if (p->res == SZ_OK) 76370b324cSopenharmony_ci p->res = res; 77370b324cSopenharmony_ci CriticalSection_Leave(&p->cs); 78370b324cSopenharmony_ci} 79370b324cSopenharmony_ci 80370b324cSopenharmony_ci 81370b324cSopenharmony_ci#define RINOK_THREAD(x) RINOK_WRes(x) 82370b324cSopenharmony_ci 83370b324cSopenharmony_ci 84370b324cSopenharmony_cistruct CMtDecBufLink_ 85370b324cSopenharmony_ci{ 86370b324cSopenharmony_ci struct CMtDecBufLink_ *next; 87370b324cSopenharmony_ci void *pad[3]; 88370b324cSopenharmony_ci}; 89370b324cSopenharmony_ci 90370b324cSopenharmony_citypedef struct CMtDecBufLink_ CMtDecBufLink; 91370b324cSopenharmony_ci 92370b324cSopenharmony_ci#define MTDEC__LINK_DATA_OFFSET sizeof(CMtDecBufLink) 93370b324cSopenharmony_ci#define MTDEC__DATA_PTR_FROM_LINK(link) ((Byte *)(link) + MTDEC__LINK_DATA_OFFSET) 94370b324cSopenharmony_ci 95370b324cSopenharmony_ci 96370b324cSopenharmony_ci 97370b324cSopenharmony_cistatic THREAD_FUNC_DECL MtDec_ThreadFunc(void *pp); 98370b324cSopenharmony_ci 99370b324cSopenharmony_ci 100370b324cSopenharmony_cistatic WRes MtDecThread_CreateEvents(CMtDecThread *t) 101370b324cSopenharmony_ci{ 102370b324cSopenharmony_ci WRes wres = AutoResetEvent_OptCreate_And_Reset(&t->canWrite); 103370b324cSopenharmony_ci if (wres == 0) 104370b324cSopenharmony_ci { 105370b324cSopenharmony_ci wres = AutoResetEvent_OptCreate_And_Reset(&t->canRead); 106370b324cSopenharmony_ci if (wres == 0) 107370b324cSopenharmony_ci return SZ_OK; 108370b324cSopenharmony_ci } 109370b324cSopenharmony_ci return wres; 110370b324cSopenharmony_ci} 111370b324cSopenharmony_ci 112370b324cSopenharmony_ci 113370b324cSopenharmony_cistatic SRes MtDecThread_CreateAndStart(CMtDecThread *t) 114370b324cSopenharmony_ci{ 115370b324cSopenharmony_ci WRes wres = MtDecThread_CreateEvents(t); 116370b324cSopenharmony_ci // wres = 17; // for test 117370b324cSopenharmony_ci if (wres == 0) 118370b324cSopenharmony_ci { 119370b324cSopenharmony_ci if (Thread_WasCreated(&t->thread)) 120370b324cSopenharmony_ci return SZ_OK; 121370b324cSopenharmony_ci wres = Thread_Create(&t->thread, MtDec_ThreadFunc, t); 122370b324cSopenharmony_ci if (wres == 0) 123370b324cSopenharmony_ci return SZ_OK; 124370b324cSopenharmony_ci } 125370b324cSopenharmony_ci return MY_SRes_HRESULT_FROM_WRes(wres); 126370b324cSopenharmony_ci} 127370b324cSopenharmony_ci 128370b324cSopenharmony_ci 129370b324cSopenharmony_civoid MtDecThread_FreeInBufs(CMtDecThread *t) 130370b324cSopenharmony_ci{ 131370b324cSopenharmony_ci if (t->inBuf) 132370b324cSopenharmony_ci { 133370b324cSopenharmony_ci void *link = t->inBuf; 134370b324cSopenharmony_ci t->inBuf = NULL; 135370b324cSopenharmony_ci do 136370b324cSopenharmony_ci { 137370b324cSopenharmony_ci void *next = ((CMtDecBufLink *)link)->next; 138370b324cSopenharmony_ci ISzAlloc_Free(t->mtDec->alloc, link); 139370b324cSopenharmony_ci link = next; 140370b324cSopenharmony_ci } 141370b324cSopenharmony_ci while (link); 142370b324cSopenharmony_ci } 143370b324cSopenharmony_ci} 144370b324cSopenharmony_ci 145370b324cSopenharmony_ci 146370b324cSopenharmony_cistatic void MtDecThread_CloseThread(CMtDecThread *t) 147370b324cSopenharmony_ci{ 148370b324cSopenharmony_ci if (Thread_WasCreated(&t->thread)) 149370b324cSopenharmony_ci { 150370b324cSopenharmony_ci Event_Set(&t->canWrite); /* we can disable it. There are no threads waiting canWrite in normal cases */ 151370b324cSopenharmony_ci Event_Set(&t->canRead); 152370b324cSopenharmony_ci Thread_Wait_Close(&t->thread); 153370b324cSopenharmony_ci } 154370b324cSopenharmony_ci 155370b324cSopenharmony_ci Event_Close(&t->canRead); 156370b324cSopenharmony_ci Event_Close(&t->canWrite); 157370b324cSopenharmony_ci} 158370b324cSopenharmony_ci 159370b324cSopenharmony_cistatic void MtDec_CloseThreads(CMtDec *p) 160370b324cSopenharmony_ci{ 161370b324cSopenharmony_ci unsigned i; 162370b324cSopenharmony_ci for (i = 0; i < MTDEC_THREADS_MAX; i++) 163370b324cSopenharmony_ci MtDecThread_CloseThread(&p->threads[i]); 164370b324cSopenharmony_ci} 165370b324cSopenharmony_ci 166370b324cSopenharmony_cistatic void MtDecThread_Destruct(CMtDecThread *t) 167370b324cSopenharmony_ci{ 168370b324cSopenharmony_ci MtDecThread_CloseThread(t); 169370b324cSopenharmony_ci MtDecThread_FreeInBufs(t); 170370b324cSopenharmony_ci} 171370b324cSopenharmony_ci 172370b324cSopenharmony_ci 173370b324cSopenharmony_ci 174370b324cSopenharmony_cistatic SRes MtDec_GetError_Spec(CMtDec *p, UInt64 interruptIndex, BoolInt *wasInterrupted) 175370b324cSopenharmony_ci{ 176370b324cSopenharmony_ci SRes res; 177370b324cSopenharmony_ci CriticalSection_Enter(&p->mtProgress.cs); 178370b324cSopenharmony_ci *wasInterrupted = (p->needInterrupt && interruptIndex > p->interruptIndex); 179370b324cSopenharmony_ci res = p->mtProgress.res; 180370b324cSopenharmony_ci CriticalSection_Leave(&p->mtProgress.cs); 181370b324cSopenharmony_ci return res; 182370b324cSopenharmony_ci} 183370b324cSopenharmony_ci 184370b324cSopenharmony_cistatic SRes MtDec_Progress_GetError_Spec(CMtDec *p, UInt64 inSize, UInt64 outSize, UInt64 interruptIndex, BoolInt *wasInterrupted) 185370b324cSopenharmony_ci{ 186370b324cSopenharmony_ci SRes res; 187370b324cSopenharmony_ci CriticalSection_Enter(&p->mtProgress.cs); 188370b324cSopenharmony_ci 189370b324cSopenharmony_ci p->mtProgress.totalInSize += inSize; 190370b324cSopenharmony_ci p->mtProgress.totalOutSize += outSize; 191370b324cSopenharmony_ci if (p->mtProgress.res == SZ_OK && p->mtProgress.progress) 192370b324cSopenharmony_ci if (ICompressProgress_Progress(p->mtProgress.progress, p->mtProgress.totalInSize, p->mtProgress.totalOutSize) != SZ_OK) 193370b324cSopenharmony_ci p->mtProgress.res = SZ_ERROR_PROGRESS; 194370b324cSopenharmony_ci 195370b324cSopenharmony_ci *wasInterrupted = (p->needInterrupt && interruptIndex > p->interruptIndex); 196370b324cSopenharmony_ci res = p->mtProgress.res; 197370b324cSopenharmony_ci 198370b324cSopenharmony_ci CriticalSection_Leave(&p->mtProgress.cs); 199370b324cSopenharmony_ci 200370b324cSopenharmony_ci return res; 201370b324cSopenharmony_ci} 202370b324cSopenharmony_ci 203370b324cSopenharmony_cistatic void MtDec_Interrupt(CMtDec *p, UInt64 interruptIndex) 204370b324cSopenharmony_ci{ 205370b324cSopenharmony_ci CriticalSection_Enter(&p->mtProgress.cs); 206370b324cSopenharmony_ci if (!p->needInterrupt || interruptIndex < p->interruptIndex) 207370b324cSopenharmony_ci { 208370b324cSopenharmony_ci p->interruptIndex = interruptIndex; 209370b324cSopenharmony_ci p->needInterrupt = True; 210370b324cSopenharmony_ci } 211370b324cSopenharmony_ci CriticalSection_Leave(&p->mtProgress.cs); 212370b324cSopenharmony_ci} 213370b324cSopenharmony_ci 214370b324cSopenharmony_ciByte *MtDec_GetCrossBuff(CMtDec *p) 215370b324cSopenharmony_ci{ 216370b324cSopenharmony_ci Byte *cr = p->crossBlock; 217370b324cSopenharmony_ci if (!cr) 218370b324cSopenharmony_ci { 219370b324cSopenharmony_ci cr = (Byte *)ISzAlloc_Alloc(p->alloc, MTDEC__LINK_DATA_OFFSET + p->inBufSize); 220370b324cSopenharmony_ci if (!cr) 221370b324cSopenharmony_ci return NULL; 222370b324cSopenharmony_ci p->crossBlock = cr; 223370b324cSopenharmony_ci } 224370b324cSopenharmony_ci return MTDEC__DATA_PTR_FROM_LINK(cr); 225370b324cSopenharmony_ci} 226370b324cSopenharmony_ci 227370b324cSopenharmony_ci 228370b324cSopenharmony_ci/* 229370b324cSopenharmony_ci MtDec_ThreadFunc2() returns: 230370b324cSopenharmony_ci 0 - in all normal cases (even for stream error or memory allocation error) 231370b324cSopenharmony_ci (!= 0) - WRes error return by system threading function 232370b324cSopenharmony_ci*/ 233370b324cSopenharmony_ci 234370b324cSopenharmony_ci// #define MTDEC_ProgessStep (1 << 22) 235370b324cSopenharmony_ci#define MTDEC_ProgessStep (1 << 0) 236370b324cSopenharmony_ci 237370b324cSopenharmony_cistatic WRes MtDec_ThreadFunc2(CMtDecThread *t) 238370b324cSopenharmony_ci{ 239370b324cSopenharmony_ci CMtDec *p = t->mtDec; 240370b324cSopenharmony_ci 241370b324cSopenharmony_ci PRF_STR_INT("MtDec_ThreadFunc2", t->index) 242370b324cSopenharmony_ci 243370b324cSopenharmony_ci // SetThreadAffinityMask(GetCurrentThread(), 1 << t->index); 244370b324cSopenharmony_ci 245370b324cSopenharmony_ci for (;;) 246370b324cSopenharmony_ci { 247370b324cSopenharmony_ci SRes res, codeRes; 248370b324cSopenharmony_ci BoolInt wasInterrupted, isAllocError, overflow, finish; 249370b324cSopenharmony_ci SRes threadingErrorSRes; 250370b324cSopenharmony_ci BoolInt needCode, needWrite, needContinue; 251370b324cSopenharmony_ci 252370b324cSopenharmony_ci size_t inDataSize_Start; 253370b324cSopenharmony_ci UInt64 inDataSize; 254370b324cSopenharmony_ci // UInt64 inDataSize_Full; 255370b324cSopenharmony_ci 256370b324cSopenharmony_ci UInt64 blockIndex; 257370b324cSopenharmony_ci 258370b324cSopenharmony_ci UInt64 inPrev = 0; 259370b324cSopenharmony_ci UInt64 outPrev = 0; 260370b324cSopenharmony_ci UInt64 inCodePos; 261370b324cSopenharmony_ci UInt64 outCodePos; 262370b324cSopenharmony_ci 263370b324cSopenharmony_ci Byte *afterEndData = NULL; 264370b324cSopenharmony_ci size_t afterEndData_Size = 0; 265370b324cSopenharmony_ci BoolInt afterEndData_IsCross = False; 266370b324cSopenharmony_ci 267370b324cSopenharmony_ci BoolInt canCreateNewThread = False; 268370b324cSopenharmony_ci // CMtDecCallbackInfo parse; 269370b324cSopenharmony_ci CMtDecThread *nextThread; 270370b324cSopenharmony_ci 271370b324cSopenharmony_ci PRF_STR_INT("=============== Event_Wait(&t->canRead)", t->index) 272370b324cSopenharmony_ci 273370b324cSopenharmony_ci RINOK_THREAD(Event_Wait(&t->canRead)) 274370b324cSopenharmony_ci if (p->exitThread) 275370b324cSopenharmony_ci return 0; 276370b324cSopenharmony_ci 277370b324cSopenharmony_ci PRF_STR_INT("after Event_Wait(&t->canRead)", t->index) 278370b324cSopenharmony_ci 279370b324cSopenharmony_ci // if (t->index == 3) return 19; // for test 280370b324cSopenharmony_ci 281370b324cSopenharmony_ci blockIndex = p->blockIndex++; 282370b324cSopenharmony_ci 283370b324cSopenharmony_ci // PRF(printf("\ncanRead\n")) 284370b324cSopenharmony_ci 285370b324cSopenharmony_ci res = MtDec_Progress_GetError_Spec(p, 0, 0, blockIndex, &wasInterrupted); 286370b324cSopenharmony_ci 287370b324cSopenharmony_ci finish = p->readWasFinished; 288370b324cSopenharmony_ci needCode = False; 289370b324cSopenharmony_ci needWrite = False; 290370b324cSopenharmony_ci isAllocError = False; 291370b324cSopenharmony_ci overflow = False; 292370b324cSopenharmony_ci 293370b324cSopenharmony_ci inDataSize_Start = 0; 294370b324cSopenharmony_ci inDataSize = 0; 295370b324cSopenharmony_ci // inDataSize_Full = 0; 296370b324cSopenharmony_ci 297370b324cSopenharmony_ci if (res == SZ_OK && !wasInterrupted) 298370b324cSopenharmony_ci { 299370b324cSopenharmony_ci // if (p->inStream) 300370b324cSopenharmony_ci { 301370b324cSopenharmony_ci CMtDecBufLink *prev = NULL; 302370b324cSopenharmony_ci CMtDecBufLink *link = (CMtDecBufLink *)t->inBuf; 303370b324cSopenharmony_ci size_t crossSize = p->crossEnd - p->crossStart; 304370b324cSopenharmony_ci 305370b324cSopenharmony_ci PRF(printf("\ncrossSize = %d\n", crossSize)); 306370b324cSopenharmony_ci 307370b324cSopenharmony_ci for (;;) 308370b324cSopenharmony_ci { 309370b324cSopenharmony_ci if (!link) 310370b324cSopenharmony_ci { 311370b324cSopenharmony_ci link = (CMtDecBufLink *)ISzAlloc_Alloc(p->alloc, MTDEC__LINK_DATA_OFFSET + p->inBufSize); 312370b324cSopenharmony_ci if (!link) 313370b324cSopenharmony_ci { 314370b324cSopenharmony_ci finish = True; 315370b324cSopenharmony_ci // p->allocError_for_Read_BlockIndex = blockIndex; 316370b324cSopenharmony_ci isAllocError = True; 317370b324cSopenharmony_ci break; 318370b324cSopenharmony_ci } 319370b324cSopenharmony_ci link->next = NULL; 320370b324cSopenharmony_ci if (prev) 321370b324cSopenharmony_ci { 322370b324cSopenharmony_ci // static unsigned g_num = 0; 323370b324cSopenharmony_ci // printf("\n%6d : %x", ++g_num, (unsigned)(size_t)((Byte *)link - (Byte *)prev)); 324370b324cSopenharmony_ci prev->next = link; 325370b324cSopenharmony_ci } 326370b324cSopenharmony_ci else 327370b324cSopenharmony_ci t->inBuf = (void *)link; 328370b324cSopenharmony_ci } 329370b324cSopenharmony_ci 330370b324cSopenharmony_ci { 331370b324cSopenharmony_ci Byte *data = MTDEC__DATA_PTR_FROM_LINK(link); 332370b324cSopenharmony_ci Byte *parseData = data; 333370b324cSopenharmony_ci size_t size; 334370b324cSopenharmony_ci 335370b324cSopenharmony_ci if (crossSize != 0) 336370b324cSopenharmony_ci { 337370b324cSopenharmony_ci inDataSize = crossSize; 338370b324cSopenharmony_ci // inDataSize_Full = inDataSize; 339370b324cSopenharmony_ci inDataSize_Start = crossSize; 340370b324cSopenharmony_ci size = crossSize; 341370b324cSopenharmony_ci parseData = MTDEC__DATA_PTR_FROM_LINK(p->crossBlock) + p->crossStart; 342370b324cSopenharmony_ci PRF(printf("\ncross : crossStart = %7d crossEnd = %7d finish = %1d", 343370b324cSopenharmony_ci (int)p->crossStart, (int)p->crossEnd, (int)finish)); 344370b324cSopenharmony_ci } 345370b324cSopenharmony_ci else 346370b324cSopenharmony_ci { 347370b324cSopenharmony_ci size = p->inBufSize; 348370b324cSopenharmony_ci 349370b324cSopenharmony_ci res = SeqInStream_ReadMax(p->inStream, data, &size); 350370b324cSopenharmony_ci 351370b324cSopenharmony_ci // size = 10; // test 352370b324cSopenharmony_ci 353370b324cSopenharmony_ci inDataSize += size; 354370b324cSopenharmony_ci // inDataSize_Full = inDataSize; 355370b324cSopenharmony_ci if (!prev) 356370b324cSopenharmony_ci inDataSize_Start = size; 357370b324cSopenharmony_ci 358370b324cSopenharmony_ci p->readProcessed += size; 359370b324cSopenharmony_ci finish = (size != p->inBufSize); 360370b324cSopenharmony_ci if (finish) 361370b324cSopenharmony_ci p->readWasFinished = True; 362370b324cSopenharmony_ci 363370b324cSopenharmony_ci // res = E_INVALIDARG; // test 364370b324cSopenharmony_ci 365370b324cSopenharmony_ci if (res != SZ_OK) 366370b324cSopenharmony_ci { 367370b324cSopenharmony_ci // PRF(printf("\nRead error = %d\n", res)) 368370b324cSopenharmony_ci // we want to decode all data before error 369370b324cSopenharmony_ci p->readRes = res; 370370b324cSopenharmony_ci // p->readError_BlockIndex = blockIndex; 371370b324cSopenharmony_ci p->readWasFinished = True; 372370b324cSopenharmony_ci finish = True; 373370b324cSopenharmony_ci res = SZ_OK; 374370b324cSopenharmony_ci // break; 375370b324cSopenharmony_ci } 376370b324cSopenharmony_ci 377370b324cSopenharmony_ci if (inDataSize - inPrev >= MTDEC_ProgessStep) 378370b324cSopenharmony_ci { 379370b324cSopenharmony_ci res = MtDec_Progress_GetError_Spec(p, 0, 0, blockIndex, &wasInterrupted); 380370b324cSopenharmony_ci if (res != SZ_OK || wasInterrupted) 381370b324cSopenharmony_ci break; 382370b324cSopenharmony_ci inPrev = inDataSize; 383370b324cSopenharmony_ci } 384370b324cSopenharmony_ci } 385370b324cSopenharmony_ci 386370b324cSopenharmony_ci { 387370b324cSopenharmony_ci CMtDecCallbackInfo parse; 388370b324cSopenharmony_ci 389370b324cSopenharmony_ci parse.startCall = (prev == NULL); 390370b324cSopenharmony_ci parse.src = parseData; 391370b324cSopenharmony_ci parse.srcSize = size; 392370b324cSopenharmony_ci parse.srcFinished = finish; 393370b324cSopenharmony_ci parse.canCreateNewThread = True; 394370b324cSopenharmony_ci 395370b324cSopenharmony_ci PRF(printf("\nParse size = %d\n", (unsigned)size)); 396370b324cSopenharmony_ci 397370b324cSopenharmony_ci p->mtCallback->Parse(p->mtCallbackObject, t->index, &parse); 398370b324cSopenharmony_ci 399370b324cSopenharmony_ci PRF(printf(" Parse processed = %d, state = %d \n", (unsigned)parse.srcSize, (unsigned)parse.state)); 400370b324cSopenharmony_ci 401370b324cSopenharmony_ci needWrite = True; 402370b324cSopenharmony_ci canCreateNewThread = parse.canCreateNewThread; 403370b324cSopenharmony_ci 404370b324cSopenharmony_ci // printf("\n\n%12I64u %12I64u", (UInt64)p->mtProgress.totalInSize, (UInt64)p->mtProgress.totalOutSize); 405370b324cSopenharmony_ci 406370b324cSopenharmony_ci if ( 407370b324cSopenharmony_ci // parseRes != SZ_OK || 408370b324cSopenharmony_ci // inDataSize - (size - parse.srcSize) > p->inBlockMax 409370b324cSopenharmony_ci // || 410370b324cSopenharmony_ci parse.state == MTDEC_PARSE_OVERFLOW 411370b324cSopenharmony_ci // || wasInterrupted 412370b324cSopenharmony_ci ) 413370b324cSopenharmony_ci { 414370b324cSopenharmony_ci // Overflow or Parse error - switch from MT decoding to ST decoding 415370b324cSopenharmony_ci finish = True; 416370b324cSopenharmony_ci overflow = True; 417370b324cSopenharmony_ci 418370b324cSopenharmony_ci { 419370b324cSopenharmony_ci PRF(printf("\n Overflow")); 420370b324cSopenharmony_ci // PRF(printf("\nisBlockFinished = %d", (unsigned)parse.blockWasFinished)); 421370b324cSopenharmony_ci PRF(printf("\n inDataSize = %d", (unsigned)inDataSize)); 422370b324cSopenharmony_ci } 423370b324cSopenharmony_ci 424370b324cSopenharmony_ci if (crossSize != 0) 425370b324cSopenharmony_ci memcpy(data, parseData, size); 426370b324cSopenharmony_ci p->crossStart = 0; 427370b324cSopenharmony_ci p->crossEnd = 0; 428370b324cSopenharmony_ci break; 429370b324cSopenharmony_ci } 430370b324cSopenharmony_ci 431370b324cSopenharmony_ci if (crossSize != 0) 432370b324cSopenharmony_ci { 433370b324cSopenharmony_ci memcpy(data, parseData, parse.srcSize); 434370b324cSopenharmony_ci p->crossStart += parse.srcSize; 435370b324cSopenharmony_ci } 436370b324cSopenharmony_ci 437370b324cSopenharmony_ci if (parse.state != MTDEC_PARSE_CONTINUE || finish) 438370b324cSopenharmony_ci { 439370b324cSopenharmony_ci // we don't need to parse in current thread anymore 440370b324cSopenharmony_ci 441370b324cSopenharmony_ci if (parse.state == MTDEC_PARSE_END) 442370b324cSopenharmony_ci finish = True; 443370b324cSopenharmony_ci 444370b324cSopenharmony_ci needCode = True; 445370b324cSopenharmony_ci // p->crossFinished = finish; 446370b324cSopenharmony_ci 447370b324cSopenharmony_ci if (parse.srcSize == size) 448370b324cSopenharmony_ci { 449370b324cSopenharmony_ci // full parsed - no cross transfer 450370b324cSopenharmony_ci p->crossStart = 0; 451370b324cSopenharmony_ci p->crossEnd = 0; 452370b324cSopenharmony_ci break; 453370b324cSopenharmony_ci } 454370b324cSopenharmony_ci 455370b324cSopenharmony_ci if (parse.state == MTDEC_PARSE_END) 456370b324cSopenharmony_ci { 457370b324cSopenharmony_ci afterEndData = parseData + parse.srcSize; 458370b324cSopenharmony_ci afterEndData_Size = size - parse.srcSize; 459370b324cSopenharmony_ci if (crossSize != 0) 460370b324cSopenharmony_ci afterEndData_IsCross = True; 461370b324cSopenharmony_ci // we reduce data size to required bytes (parsed only) 462370b324cSopenharmony_ci inDataSize -= afterEndData_Size; 463370b324cSopenharmony_ci if (!prev) 464370b324cSopenharmony_ci inDataSize_Start = parse.srcSize; 465370b324cSopenharmony_ci break; 466370b324cSopenharmony_ci } 467370b324cSopenharmony_ci 468370b324cSopenharmony_ci { 469370b324cSopenharmony_ci // partial parsed - need cross transfer 470370b324cSopenharmony_ci if (crossSize != 0) 471370b324cSopenharmony_ci inDataSize = parse.srcSize; // it's only parsed now 472370b324cSopenharmony_ci else 473370b324cSopenharmony_ci { 474370b324cSopenharmony_ci // partial parsed - is not in initial cross block - we need to copy new data to cross block 475370b324cSopenharmony_ci Byte *cr = MtDec_GetCrossBuff(p); 476370b324cSopenharmony_ci if (!cr) 477370b324cSopenharmony_ci { 478370b324cSopenharmony_ci { 479370b324cSopenharmony_ci PRF(printf("\ncross alloc error error\n")); 480370b324cSopenharmony_ci // res = SZ_ERROR_MEM; 481370b324cSopenharmony_ci finish = True; 482370b324cSopenharmony_ci // p->allocError_for_Read_BlockIndex = blockIndex; 483370b324cSopenharmony_ci isAllocError = True; 484370b324cSopenharmony_ci break; 485370b324cSopenharmony_ci } 486370b324cSopenharmony_ci } 487370b324cSopenharmony_ci 488370b324cSopenharmony_ci { 489370b324cSopenharmony_ci size_t crSize = size - parse.srcSize; 490370b324cSopenharmony_ci inDataSize -= crSize; 491370b324cSopenharmony_ci p->crossEnd = crSize; 492370b324cSopenharmony_ci p->crossStart = 0; 493370b324cSopenharmony_ci memcpy(cr, parseData + parse.srcSize, crSize); 494370b324cSopenharmony_ci } 495370b324cSopenharmony_ci } 496370b324cSopenharmony_ci 497370b324cSopenharmony_ci // inDataSize_Full = inDataSize; 498370b324cSopenharmony_ci if (!prev) 499370b324cSopenharmony_ci inDataSize_Start = parse.srcSize; // it's partial size (parsed only) 500370b324cSopenharmony_ci 501370b324cSopenharmony_ci finish = False; 502370b324cSopenharmony_ci break; 503370b324cSopenharmony_ci } 504370b324cSopenharmony_ci } 505370b324cSopenharmony_ci 506370b324cSopenharmony_ci if (parse.srcSize != size) 507370b324cSopenharmony_ci { 508370b324cSopenharmony_ci res = SZ_ERROR_FAIL; 509370b324cSopenharmony_ci PRF(printf("\nfinished error SZ_ERROR_FAIL = %d\n", res)); 510370b324cSopenharmony_ci break; 511370b324cSopenharmony_ci } 512370b324cSopenharmony_ci } 513370b324cSopenharmony_ci } 514370b324cSopenharmony_ci 515370b324cSopenharmony_ci prev = link; 516370b324cSopenharmony_ci link = link->next; 517370b324cSopenharmony_ci 518370b324cSopenharmony_ci if (crossSize != 0) 519370b324cSopenharmony_ci { 520370b324cSopenharmony_ci crossSize = 0; 521370b324cSopenharmony_ci p->crossStart = 0; 522370b324cSopenharmony_ci p->crossEnd = 0; 523370b324cSopenharmony_ci } 524370b324cSopenharmony_ci } 525370b324cSopenharmony_ci } 526370b324cSopenharmony_ci 527370b324cSopenharmony_ci if (res == SZ_OK) 528370b324cSopenharmony_ci res = MtDec_GetError_Spec(p, blockIndex, &wasInterrupted); 529370b324cSopenharmony_ci } 530370b324cSopenharmony_ci 531370b324cSopenharmony_ci codeRes = SZ_OK; 532370b324cSopenharmony_ci 533370b324cSopenharmony_ci if (res == SZ_OK && needCode && !wasInterrupted) 534370b324cSopenharmony_ci { 535370b324cSopenharmony_ci codeRes = p->mtCallback->PreCode(p->mtCallbackObject, t->index); 536370b324cSopenharmony_ci if (codeRes != SZ_OK) 537370b324cSopenharmony_ci { 538370b324cSopenharmony_ci needCode = False; 539370b324cSopenharmony_ci finish = True; 540370b324cSopenharmony_ci // SZ_ERROR_MEM is expected error here. 541370b324cSopenharmony_ci // if (codeRes == SZ_ERROR_MEM) - we will try single-thread decoding later. 542370b324cSopenharmony_ci // if (codeRes != SZ_ERROR_MEM) - we can stop decoding or try single-thread decoding. 543370b324cSopenharmony_ci } 544370b324cSopenharmony_ci } 545370b324cSopenharmony_ci 546370b324cSopenharmony_ci if (res != SZ_OK || wasInterrupted) 547370b324cSopenharmony_ci finish = True; 548370b324cSopenharmony_ci 549370b324cSopenharmony_ci nextThread = NULL; 550370b324cSopenharmony_ci threadingErrorSRes = SZ_OK; 551370b324cSopenharmony_ci 552370b324cSopenharmony_ci if (!finish) 553370b324cSopenharmony_ci { 554370b324cSopenharmony_ci if (p->numStartedThreads < p->numStartedThreads_Limit && canCreateNewThread) 555370b324cSopenharmony_ci { 556370b324cSopenharmony_ci SRes res2 = MtDecThread_CreateAndStart(&p->threads[p->numStartedThreads]); 557370b324cSopenharmony_ci if (res2 == SZ_OK) 558370b324cSopenharmony_ci { 559370b324cSopenharmony_ci // if (p->numStartedThreads % 1000 == 0) PRF(printf("\n numStartedThreads=%d\n", p->numStartedThreads)); 560370b324cSopenharmony_ci p->numStartedThreads++; 561370b324cSopenharmony_ci } 562370b324cSopenharmony_ci else 563370b324cSopenharmony_ci { 564370b324cSopenharmony_ci PRF(printf("\nERROR: numStartedThreads=%d\n", p->numStartedThreads)); 565370b324cSopenharmony_ci if (p->numStartedThreads == 1) 566370b324cSopenharmony_ci { 567370b324cSopenharmony_ci // if only one thread is possible, we leave muti-threading code 568370b324cSopenharmony_ci finish = True; 569370b324cSopenharmony_ci needCode = False; 570370b324cSopenharmony_ci threadingErrorSRes = res2; 571370b324cSopenharmony_ci } 572370b324cSopenharmony_ci else 573370b324cSopenharmony_ci p->numStartedThreads_Limit = p->numStartedThreads; 574370b324cSopenharmony_ci } 575370b324cSopenharmony_ci } 576370b324cSopenharmony_ci 577370b324cSopenharmony_ci if (!finish) 578370b324cSopenharmony_ci { 579370b324cSopenharmony_ci unsigned nextIndex = t->index + 1; 580370b324cSopenharmony_ci nextThread = &p->threads[nextIndex >= p->numStartedThreads ? 0 : nextIndex]; 581370b324cSopenharmony_ci RINOK_THREAD(Event_Set(&nextThread->canRead)) 582370b324cSopenharmony_ci // We have started executing for new iteration (with next thread) 583370b324cSopenharmony_ci // And that next thread now is responsible for possible exit from decoding (threading_code) 584370b324cSopenharmony_ci } 585370b324cSopenharmony_ci } 586370b324cSopenharmony_ci 587370b324cSopenharmony_ci // each call of Event_Set(&nextThread->canRead) must be followed by call of Event_Set(&nextThread->canWrite) 588370b324cSopenharmony_ci // if ( !finish ) we must call Event_Set(&nextThread->canWrite) in any case 589370b324cSopenharmony_ci // if ( finish ) we switch to single-thread mode and there are 2 ways at the end of current iteration (current block): 590370b324cSopenharmony_ci // - if (needContinue) after Write(&needContinue), we restore decoding with new iteration 591370b324cSopenharmony_ci // - otherwise we stop decoding and exit from MtDec_ThreadFunc2() 592370b324cSopenharmony_ci 593370b324cSopenharmony_ci // Don't change (finish) variable in the further code 594370b324cSopenharmony_ci 595370b324cSopenharmony_ci 596370b324cSopenharmony_ci // ---------- CODE ---------- 597370b324cSopenharmony_ci 598370b324cSopenharmony_ci inPrev = 0; 599370b324cSopenharmony_ci outPrev = 0; 600370b324cSopenharmony_ci inCodePos = 0; 601370b324cSopenharmony_ci outCodePos = 0; 602370b324cSopenharmony_ci 603370b324cSopenharmony_ci if (res == SZ_OK && needCode && codeRes == SZ_OK) 604370b324cSopenharmony_ci { 605370b324cSopenharmony_ci BoolInt isStartBlock = True; 606370b324cSopenharmony_ci CMtDecBufLink *link = (CMtDecBufLink *)t->inBuf; 607370b324cSopenharmony_ci 608370b324cSopenharmony_ci for (;;) 609370b324cSopenharmony_ci { 610370b324cSopenharmony_ci size_t inSize; 611370b324cSopenharmony_ci int stop; 612370b324cSopenharmony_ci 613370b324cSopenharmony_ci if (isStartBlock) 614370b324cSopenharmony_ci inSize = inDataSize_Start; 615370b324cSopenharmony_ci else 616370b324cSopenharmony_ci { 617370b324cSopenharmony_ci UInt64 rem = inDataSize - inCodePos; 618370b324cSopenharmony_ci inSize = p->inBufSize; 619370b324cSopenharmony_ci if (inSize > rem) 620370b324cSopenharmony_ci inSize = (size_t)rem; 621370b324cSopenharmony_ci } 622370b324cSopenharmony_ci 623370b324cSopenharmony_ci inCodePos += inSize; 624370b324cSopenharmony_ci stop = True; 625370b324cSopenharmony_ci 626370b324cSopenharmony_ci codeRes = p->mtCallback->Code(p->mtCallbackObject, t->index, 627370b324cSopenharmony_ci (const Byte *)MTDEC__DATA_PTR_FROM_LINK(link), inSize, 628370b324cSopenharmony_ci (inCodePos == inDataSize), // srcFinished 629370b324cSopenharmony_ci &inCodePos, &outCodePos, &stop); 630370b324cSopenharmony_ci 631370b324cSopenharmony_ci if (codeRes != SZ_OK) 632370b324cSopenharmony_ci { 633370b324cSopenharmony_ci PRF(printf("\nCode Interrupt error = %x\n", codeRes)); 634370b324cSopenharmony_ci // we interrupt only later blocks 635370b324cSopenharmony_ci MtDec_Interrupt(p, blockIndex); 636370b324cSopenharmony_ci break; 637370b324cSopenharmony_ci } 638370b324cSopenharmony_ci 639370b324cSopenharmony_ci if (stop || inCodePos == inDataSize) 640370b324cSopenharmony_ci break; 641370b324cSopenharmony_ci 642370b324cSopenharmony_ci { 643370b324cSopenharmony_ci const UInt64 inDelta = inCodePos - inPrev; 644370b324cSopenharmony_ci const UInt64 outDelta = outCodePos - outPrev; 645370b324cSopenharmony_ci if (inDelta >= MTDEC_ProgessStep || outDelta >= MTDEC_ProgessStep) 646370b324cSopenharmony_ci { 647370b324cSopenharmony_ci // Sleep(1); 648370b324cSopenharmony_ci res = MtDec_Progress_GetError_Spec(p, inDelta, outDelta, blockIndex, &wasInterrupted); 649370b324cSopenharmony_ci if (res != SZ_OK || wasInterrupted) 650370b324cSopenharmony_ci break; 651370b324cSopenharmony_ci inPrev = inCodePos; 652370b324cSopenharmony_ci outPrev = outCodePos; 653370b324cSopenharmony_ci } 654370b324cSopenharmony_ci } 655370b324cSopenharmony_ci 656370b324cSopenharmony_ci link = link->next; 657370b324cSopenharmony_ci isStartBlock = False; 658370b324cSopenharmony_ci } 659370b324cSopenharmony_ci } 660370b324cSopenharmony_ci 661370b324cSopenharmony_ci 662370b324cSopenharmony_ci // ---------- WRITE ---------- 663370b324cSopenharmony_ci 664370b324cSopenharmony_ci RINOK_THREAD(Event_Wait(&t->canWrite)) 665370b324cSopenharmony_ci 666370b324cSopenharmony_ci { 667370b324cSopenharmony_ci BoolInt isErrorMode = False; 668370b324cSopenharmony_ci BoolInt canRecode = True; 669370b324cSopenharmony_ci BoolInt needWriteToStream = needWrite; 670370b324cSopenharmony_ci 671370b324cSopenharmony_ci if (p->exitThread) return 0; // it's never executed in normal cases 672370b324cSopenharmony_ci 673370b324cSopenharmony_ci if (p->wasInterrupted) 674370b324cSopenharmony_ci wasInterrupted = True; 675370b324cSopenharmony_ci else 676370b324cSopenharmony_ci { 677370b324cSopenharmony_ci if (codeRes != SZ_OK) // || !needCode // check it !!! 678370b324cSopenharmony_ci { 679370b324cSopenharmony_ci p->wasInterrupted = True; 680370b324cSopenharmony_ci p->codeRes = codeRes; 681370b324cSopenharmony_ci if (codeRes == SZ_ERROR_MEM) 682370b324cSopenharmony_ci isAllocError = True; 683370b324cSopenharmony_ci } 684370b324cSopenharmony_ci 685370b324cSopenharmony_ci if (threadingErrorSRes) 686370b324cSopenharmony_ci { 687370b324cSopenharmony_ci p->wasInterrupted = True; 688370b324cSopenharmony_ci p->threadingErrorSRes = threadingErrorSRes; 689370b324cSopenharmony_ci needWriteToStream = False; 690370b324cSopenharmony_ci } 691370b324cSopenharmony_ci if (isAllocError) 692370b324cSopenharmony_ci { 693370b324cSopenharmony_ci p->wasInterrupted = True; 694370b324cSopenharmony_ci p->isAllocError = True; 695370b324cSopenharmony_ci needWriteToStream = False; 696370b324cSopenharmony_ci } 697370b324cSopenharmony_ci if (overflow) 698370b324cSopenharmony_ci { 699370b324cSopenharmony_ci p->wasInterrupted = True; 700370b324cSopenharmony_ci p->overflow = True; 701370b324cSopenharmony_ci needWriteToStream = False; 702370b324cSopenharmony_ci } 703370b324cSopenharmony_ci } 704370b324cSopenharmony_ci 705370b324cSopenharmony_ci if (needCode) 706370b324cSopenharmony_ci { 707370b324cSopenharmony_ci if (wasInterrupted) 708370b324cSopenharmony_ci { 709370b324cSopenharmony_ci inCodePos = 0; 710370b324cSopenharmony_ci outCodePos = 0; 711370b324cSopenharmony_ci } 712370b324cSopenharmony_ci { 713370b324cSopenharmony_ci const UInt64 inDelta = inCodePos - inPrev; 714370b324cSopenharmony_ci const UInt64 outDelta = outCodePos - outPrev; 715370b324cSopenharmony_ci // if (inDelta != 0 || outDelta != 0) 716370b324cSopenharmony_ci res = MtProgress_ProgressAdd(&p->mtProgress, inDelta, outDelta); 717370b324cSopenharmony_ci } 718370b324cSopenharmony_ci } 719370b324cSopenharmony_ci 720370b324cSopenharmony_ci needContinue = (!finish); 721370b324cSopenharmony_ci 722370b324cSopenharmony_ci // if (res == SZ_OK && needWrite && !wasInterrupted) 723370b324cSopenharmony_ci if (needWrite) 724370b324cSopenharmony_ci { 725370b324cSopenharmony_ci // p->inProcessed += inCodePos; 726370b324cSopenharmony_ci 727370b324cSopenharmony_ci PRF(printf("\n--Write afterSize = %d\n", (unsigned)afterEndData_Size)); 728370b324cSopenharmony_ci 729370b324cSopenharmony_ci res = p->mtCallback->Write(p->mtCallbackObject, t->index, 730370b324cSopenharmony_ci res == SZ_OK && needWriteToStream && !wasInterrupted, // needWrite 731370b324cSopenharmony_ci afterEndData, afterEndData_Size, afterEndData_IsCross, 732370b324cSopenharmony_ci &needContinue, 733370b324cSopenharmony_ci &canRecode); 734370b324cSopenharmony_ci 735370b324cSopenharmony_ci // res = SZ_ERROR_FAIL; // for test 736370b324cSopenharmony_ci 737370b324cSopenharmony_ci PRF(printf("\nAfter Write needContinue = %d\n", (unsigned)needContinue)); 738370b324cSopenharmony_ci PRF(printf("\nprocessed = %d\n", (unsigned)p->inProcessed)); 739370b324cSopenharmony_ci 740370b324cSopenharmony_ci if (res != SZ_OK) 741370b324cSopenharmony_ci { 742370b324cSopenharmony_ci PRF(printf("\nWrite error = %d\n", res)); 743370b324cSopenharmony_ci isErrorMode = True; 744370b324cSopenharmony_ci p->wasInterrupted = True; 745370b324cSopenharmony_ci } 746370b324cSopenharmony_ci if (res != SZ_OK 747370b324cSopenharmony_ci || (!needContinue && !finish)) 748370b324cSopenharmony_ci { 749370b324cSopenharmony_ci PRF(printf("\nWrite Interrupt error = %x\n", res)); 750370b324cSopenharmony_ci MtDec_Interrupt(p, blockIndex); 751370b324cSopenharmony_ci } 752370b324cSopenharmony_ci } 753370b324cSopenharmony_ci 754370b324cSopenharmony_ci if (canRecode) 755370b324cSopenharmony_ci if (!needCode 756370b324cSopenharmony_ci || res != SZ_OK 757370b324cSopenharmony_ci || p->wasInterrupted 758370b324cSopenharmony_ci || codeRes != SZ_OK 759370b324cSopenharmony_ci || wasInterrupted 760370b324cSopenharmony_ci || p->numFilledThreads != 0 761370b324cSopenharmony_ci || isErrorMode) 762370b324cSopenharmony_ci { 763370b324cSopenharmony_ci if (p->numFilledThreads == 0) 764370b324cSopenharmony_ci p->filledThreadStart = t->index; 765370b324cSopenharmony_ci if (inDataSize != 0 || !finish) 766370b324cSopenharmony_ci { 767370b324cSopenharmony_ci t->inDataSize_Start = inDataSize_Start; 768370b324cSopenharmony_ci t->inDataSize = inDataSize; 769370b324cSopenharmony_ci p->numFilledThreads++; 770370b324cSopenharmony_ci } 771370b324cSopenharmony_ci PRF(printf("\np->numFilledThreads = %d\n", p->numFilledThreads)); 772370b324cSopenharmony_ci PRF(printf("p->filledThreadStart = %d\n", p->filledThreadStart)); 773370b324cSopenharmony_ci } 774370b324cSopenharmony_ci 775370b324cSopenharmony_ci if (!finish) 776370b324cSopenharmony_ci { 777370b324cSopenharmony_ci RINOK_THREAD(Event_Set(&nextThread->canWrite)) 778370b324cSopenharmony_ci } 779370b324cSopenharmony_ci else 780370b324cSopenharmony_ci { 781370b324cSopenharmony_ci if (needContinue) 782370b324cSopenharmony_ci { 783370b324cSopenharmony_ci // we restore decoding with new iteration 784370b324cSopenharmony_ci RINOK_THREAD(Event_Set(&p->threads[0].canWrite)) 785370b324cSopenharmony_ci } 786370b324cSopenharmony_ci else 787370b324cSopenharmony_ci { 788370b324cSopenharmony_ci // we exit from decoding 789370b324cSopenharmony_ci if (t->index == 0) 790370b324cSopenharmony_ci return SZ_OK; 791370b324cSopenharmony_ci p->exitThread = True; 792370b324cSopenharmony_ci } 793370b324cSopenharmony_ci RINOK_THREAD(Event_Set(&p->threads[0].canRead)) 794370b324cSopenharmony_ci } 795370b324cSopenharmony_ci } 796370b324cSopenharmony_ci } 797370b324cSopenharmony_ci} 798370b324cSopenharmony_ci 799370b324cSopenharmony_ci#ifdef _WIN32 800370b324cSopenharmony_ci#define USE_ALLOCA 801370b324cSopenharmony_ci#endif 802370b324cSopenharmony_ci 803370b324cSopenharmony_ci#ifdef USE_ALLOCA 804370b324cSopenharmony_ci#ifdef _WIN32 805370b324cSopenharmony_ci#include <malloc.h> 806370b324cSopenharmony_ci#else 807370b324cSopenharmony_ci#include <stdlib.h> 808370b324cSopenharmony_ci#endif 809370b324cSopenharmony_ci#endif 810370b324cSopenharmony_ci 811370b324cSopenharmony_ci 812370b324cSopenharmony_cistatic THREAD_FUNC_DECL MtDec_ThreadFunc1(void *pp) 813370b324cSopenharmony_ci{ 814370b324cSopenharmony_ci WRes res; 815370b324cSopenharmony_ci 816370b324cSopenharmony_ci CMtDecThread *t = (CMtDecThread *)pp; 817370b324cSopenharmony_ci CMtDec *p; 818370b324cSopenharmony_ci 819370b324cSopenharmony_ci // fprintf(stdout, "\n%d = %p\n", t->index, &t); 820370b324cSopenharmony_ci 821370b324cSopenharmony_ci res = MtDec_ThreadFunc2(t); 822370b324cSopenharmony_ci p = t->mtDec; 823370b324cSopenharmony_ci if (res == 0) 824370b324cSopenharmony_ci return (THREAD_FUNC_RET_TYPE)(UINT_PTR)p->exitThreadWRes; 825370b324cSopenharmony_ci { 826370b324cSopenharmony_ci // it's unexpected situation for some threading function error 827370b324cSopenharmony_ci if (p->exitThreadWRes == 0) 828370b324cSopenharmony_ci p->exitThreadWRes = res; 829370b324cSopenharmony_ci PRF(printf("\nthread exit error = %d\n", res)); 830370b324cSopenharmony_ci p->exitThread = True; 831370b324cSopenharmony_ci Event_Set(&p->threads[0].canRead); 832370b324cSopenharmony_ci Event_Set(&p->threads[0].canWrite); 833370b324cSopenharmony_ci MtProgress_SetError(&p->mtProgress, MY_SRes_HRESULT_FROM_WRes(res)); 834370b324cSopenharmony_ci } 835370b324cSopenharmony_ci return (THREAD_FUNC_RET_TYPE)(UINT_PTR)res; 836370b324cSopenharmony_ci} 837370b324cSopenharmony_ci 838370b324cSopenharmony_cistatic Z7_NO_INLINE THREAD_FUNC_DECL MtDec_ThreadFunc(void *pp) 839370b324cSopenharmony_ci{ 840370b324cSopenharmony_ci #ifdef USE_ALLOCA 841370b324cSopenharmony_ci CMtDecThread *t = (CMtDecThread *)pp; 842370b324cSopenharmony_ci // fprintf(stderr, "\n%d = %p - before", t->index, &t); 843370b324cSopenharmony_ci t->allocaPtr = alloca(t->index * 128); 844370b324cSopenharmony_ci #endif 845370b324cSopenharmony_ci return MtDec_ThreadFunc1(pp); 846370b324cSopenharmony_ci} 847370b324cSopenharmony_ci 848370b324cSopenharmony_ci 849370b324cSopenharmony_ciint MtDec_PrepareRead(CMtDec *p) 850370b324cSopenharmony_ci{ 851370b324cSopenharmony_ci if (p->crossBlock && p->crossStart == p->crossEnd) 852370b324cSopenharmony_ci { 853370b324cSopenharmony_ci ISzAlloc_Free(p->alloc, p->crossBlock); 854370b324cSopenharmony_ci p->crossBlock = NULL; 855370b324cSopenharmony_ci } 856370b324cSopenharmony_ci 857370b324cSopenharmony_ci { 858370b324cSopenharmony_ci unsigned i; 859370b324cSopenharmony_ci for (i = 0; i < MTDEC_THREADS_MAX; i++) 860370b324cSopenharmony_ci if (i > p->numStartedThreads 861370b324cSopenharmony_ci || p->numFilledThreads <= 862370b324cSopenharmony_ci (i >= p->filledThreadStart ? 863370b324cSopenharmony_ci i - p->filledThreadStart : 864370b324cSopenharmony_ci i + p->numStartedThreads - p->filledThreadStart)) 865370b324cSopenharmony_ci MtDecThread_FreeInBufs(&p->threads[i]); 866370b324cSopenharmony_ci } 867370b324cSopenharmony_ci 868370b324cSopenharmony_ci return (p->numFilledThreads != 0) || (p->crossStart != p->crossEnd); 869370b324cSopenharmony_ci} 870370b324cSopenharmony_ci 871370b324cSopenharmony_ci 872370b324cSopenharmony_ciconst Byte *MtDec_Read(CMtDec *p, size_t *inLim) 873370b324cSopenharmony_ci{ 874370b324cSopenharmony_ci while (p->numFilledThreads != 0) 875370b324cSopenharmony_ci { 876370b324cSopenharmony_ci CMtDecThread *t = &p->threads[p->filledThreadStart]; 877370b324cSopenharmony_ci 878370b324cSopenharmony_ci if (*inLim != 0) 879370b324cSopenharmony_ci { 880370b324cSopenharmony_ci { 881370b324cSopenharmony_ci void *link = t->inBuf; 882370b324cSopenharmony_ci void *next = ((CMtDecBufLink *)link)->next; 883370b324cSopenharmony_ci ISzAlloc_Free(p->alloc, link); 884370b324cSopenharmony_ci t->inBuf = next; 885370b324cSopenharmony_ci } 886370b324cSopenharmony_ci 887370b324cSopenharmony_ci if (t->inDataSize == 0) 888370b324cSopenharmony_ci { 889370b324cSopenharmony_ci MtDecThread_FreeInBufs(t); 890370b324cSopenharmony_ci if (--p->numFilledThreads == 0) 891370b324cSopenharmony_ci break; 892370b324cSopenharmony_ci if (++p->filledThreadStart == p->numStartedThreads) 893370b324cSopenharmony_ci p->filledThreadStart = 0; 894370b324cSopenharmony_ci t = &p->threads[p->filledThreadStart]; 895370b324cSopenharmony_ci } 896370b324cSopenharmony_ci } 897370b324cSopenharmony_ci 898370b324cSopenharmony_ci { 899370b324cSopenharmony_ci size_t lim = t->inDataSize_Start; 900370b324cSopenharmony_ci if (lim != 0) 901370b324cSopenharmony_ci t->inDataSize_Start = 0; 902370b324cSopenharmony_ci else 903370b324cSopenharmony_ci { 904370b324cSopenharmony_ci UInt64 rem = t->inDataSize; 905370b324cSopenharmony_ci lim = p->inBufSize; 906370b324cSopenharmony_ci if (lim > rem) 907370b324cSopenharmony_ci lim = (size_t)rem; 908370b324cSopenharmony_ci } 909370b324cSopenharmony_ci t->inDataSize -= lim; 910370b324cSopenharmony_ci *inLim = lim; 911370b324cSopenharmony_ci return (const Byte *)MTDEC__DATA_PTR_FROM_LINK(t->inBuf); 912370b324cSopenharmony_ci } 913370b324cSopenharmony_ci } 914370b324cSopenharmony_ci 915370b324cSopenharmony_ci { 916370b324cSopenharmony_ci size_t crossSize = p->crossEnd - p->crossStart; 917370b324cSopenharmony_ci if (crossSize != 0) 918370b324cSopenharmony_ci { 919370b324cSopenharmony_ci const Byte *data = MTDEC__DATA_PTR_FROM_LINK(p->crossBlock) + p->crossStart; 920370b324cSopenharmony_ci *inLim = crossSize; 921370b324cSopenharmony_ci p->crossStart = 0; 922370b324cSopenharmony_ci p->crossEnd = 0; 923370b324cSopenharmony_ci return data; 924370b324cSopenharmony_ci } 925370b324cSopenharmony_ci *inLim = 0; 926370b324cSopenharmony_ci if (p->crossBlock) 927370b324cSopenharmony_ci { 928370b324cSopenharmony_ci ISzAlloc_Free(p->alloc, p->crossBlock); 929370b324cSopenharmony_ci p->crossBlock = NULL; 930370b324cSopenharmony_ci } 931370b324cSopenharmony_ci return NULL; 932370b324cSopenharmony_ci } 933370b324cSopenharmony_ci} 934370b324cSopenharmony_ci 935370b324cSopenharmony_ci 936370b324cSopenharmony_civoid MtDec_Construct(CMtDec *p) 937370b324cSopenharmony_ci{ 938370b324cSopenharmony_ci unsigned i; 939370b324cSopenharmony_ci 940370b324cSopenharmony_ci p->inBufSize = (size_t)1 << 18; 941370b324cSopenharmony_ci 942370b324cSopenharmony_ci p->numThreadsMax = 0; 943370b324cSopenharmony_ci 944370b324cSopenharmony_ci p->inStream = NULL; 945370b324cSopenharmony_ci 946370b324cSopenharmony_ci // p->inData = NULL; 947370b324cSopenharmony_ci // p->inDataSize = 0; 948370b324cSopenharmony_ci 949370b324cSopenharmony_ci p->crossBlock = NULL; 950370b324cSopenharmony_ci p->crossStart = 0; 951370b324cSopenharmony_ci p->crossEnd = 0; 952370b324cSopenharmony_ci 953370b324cSopenharmony_ci p->numFilledThreads = 0; 954370b324cSopenharmony_ci 955370b324cSopenharmony_ci p->progress = NULL; 956370b324cSopenharmony_ci p->alloc = NULL; 957370b324cSopenharmony_ci 958370b324cSopenharmony_ci p->mtCallback = NULL; 959370b324cSopenharmony_ci p->mtCallbackObject = NULL; 960370b324cSopenharmony_ci 961370b324cSopenharmony_ci p->allocatedBufsSize = 0; 962370b324cSopenharmony_ci 963370b324cSopenharmony_ci for (i = 0; i < MTDEC_THREADS_MAX; i++) 964370b324cSopenharmony_ci { 965370b324cSopenharmony_ci CMtDecThread *t = &p->threads[i]; 966370b324cSopenharmony_ci t->mtDec = p; 967370b324cSopenharmony_ci t->index = i; 968370b324cSopenharmony_ci t->inBuf = NULL; 969370b324cSopenharmony_ci Event_Construct(&t->canRead); 970370b324cSopenharmony_ci Event_Construct(&t->canWrite); 971370b324cSopenharmony_ci Thread_CONSTRUCT(&t->thread) 972370b324cSopenharmony_ci } 973370b324cSopenharmony_ci 974370b324cSopenharmony_ci // Event_Construct(&p->finishedEvent); 975370b324cSopenharmony_ci 976370b324cSopenharmony_ci CriticalSection_Init(&p->mtProgress.cs); 977370b324cSopenharmony_ci} 978370b324cSopenharmony_ci 979370b324cSopenharmony_ci 980370b324cSopenharmony_cistatic void MtDec_Free(CMtDec *p) 981370b324cSopenharmony_ci{ 982370b324cSopenharmony_ci unsigned i; 983370b324cSopenharmony_ci 984370b324cSopenharmony_ci p->exitThread = True; 985370b324cSopenharmony_ci 986370b324cSopenharmony_ci for (i = 0; i < MTDEC_THREADS_MAX; i++) 987370b324cSopenharmony_ci MtDecThread_Destruct(&p->threads[i]); 988370b324cSopenharmony_ci 989370b324cSopenharmony_ci // Event_Close(&p->finishedEvent); 990370b324cSopenharmony_ci 991370b324cSopenharmony_ci if (p->crossBlock) 992370b324cSopenharmony_ci { 993370b324cSopenharmony_ci ISzAlloc_Free(p->alloc, p->crossBlock); 994370b324cSopenharmony_ci p->crossBlock = NULL; 995370b324cSopenharmony_ci } 996370b324cSopenharmony_ci} 997370b324cSopenharmony_ci 998370b324cSopenharmony_ci 999370b324cSopenharmony_civoid MtDec_Destruct(CMtDec *p) 1000370b324cSopenharmony_ci{ 1001370b324cSopenharmony_ci MtDec_Free(p); 1002370b324cSopenharmony_ci 1003370b324cSopenharmony_ci CriticalSection_Delete(&p->mtProgress.cs); 1004370b324cSopenharmony_ci} 1005370b324cSopenharmony_ci 1006370b324cSopenharmony_ci 1007370b324cSopenharmony_ciSRes MtDec_Code(CMtDec *p) 1008370b324cSopenharmony_ci{ 1009370b324cSopenharmony_ci unsigned i; 1010370b324cSopenharmony_ci 1011370b324cSopenharmony_ci p->inProcessed = 0; 1012370b324cSopenharmony_ci 1013370b324cSopenharmony_ci p->blockIndex = 1; // it must be larger than not_defined index (0) 1014370b324cSopenharmony_ci p->isAllocError = False; 1015370b324cSopenharmony_ci p->overflow = False; 1016370b324cSopenharmony_ci p->threadingErrorSRes = SZ_OK; 1017370b324cSopenharmony_ci 1018370b324cSopenharmony_ci p->needContinue = True; 1019370b324cSopenharmony_ci 1020370b324cSopenharmony_ci p->readWasFinished = False; 1021370b324cSopenharmony_ci p->needInterrupt = False; 1022370b324cSopenharmony_ci p->interruptIndex = (UInt64)(Int64)-1; 1023370b324cSopenharmony_ci 1024370b324cSopenharmony_ci p->readProcessed = 0; 1025370b324cSopenharmony_ci p->readRes = SZ_OK; 1026370b324cSopenharmony_ci p->codeRes = SZ_OK; 1027370b324cSopenharmony_ci p->wasInterrupted = False; 1028370b324cSopenharmony_ci 1029370b324cSopenharmony_ci p->crossStart = 0; 1030370b324cSopenharmony_ci p->crossEnd = 0; 1031370b324cSopenharmony_ci 1032370b324cSopenharmony_ci p->filledThreadStart = 0; 1033370b324cSopenharmony_ci p->numFilledThreads = 0; 1034370b324cSopenharmony_ci 1035370b324cSopenharmony_ci { 1036370b324cSopenharmony_ci unsigned numThreads = p->numThreadsMax; 1037370b324cSopenharmony_ci if (numThreads > MTDEC_THREADS_MAX) 1038370b324cSopenharmony_ci numThreads = MTDEC_THREADS_MAX; 1039370b324cSopenharmony_ci p->numStartedThreads_Limit = numThreads; 1040370b324cSopenharmony_ci p->numStartedThreads = 0; 1041370b324cSopenharmony_ci } 1042370b324cSopenharmony_ci 1043370b324cSopenharmony_ci if (p->inBufSize != p->allocatedBufsSize) 1044370b324cSopenharmony_ci { 1045370b324cSopenharmony_ci for (i = 0; i < MTDEC_THREADS_MAX; i++) 1046370b324cSopenharmony_ci { 1047370b324cSopenharmony_ci CMtDecThread *t = &p->threads[i]; 1048370b324cSopenharmony_ci if (t->inBuf) 1049370b324cSopenharmony_ci MtDecThread_FreeInBufs(t); 1050370b324cSopenharmony_ci } 1051370b324cSopenharmony_ci if (p->crossBlock) 1052370b324cSopenharmony_ci { 1053370b324cSopenharmony_ci ISzAlloc_Free(p->alloc, p->crossBlock); 1054370b324cSopenharmony_ci p->crossBlock = NULL; 1055370b324cSopenharmony_ci } 1056370b324cSopenharmony_ci 1057370b324cSopenharmony_ci p->allocatedBufsSize = p->inBufSize; 1058370b324cSopenharmony_ci } 1059370b324cSopenharmony_ci 1060370b324cSopenharmony_ci MtProgress_Init(&p->mtProgress, p->progress); 1061370b324cSopenharmony_ci 1062370b324cSopenharmony_ci // RINOK_THREAD(AutoResetEvent_OptCreate_And_Reset(&p->finishedEvent)) 1063370b324cSopenharmony_ci p->exitThread = False; 1064370b324cSopenharmony_ci p->exitThreadWRes = 0; 1065370b324cSopenharmony_ci 1066370b324cSopenharmony_ci { 1067370b324cSopenharmony_ci WRes wres; 1068370b324cSopenharmony_ci SRes sres; 1069370b324cSopenharmony_ci CMtDecThread *nextThread = &p->threads[p->numStartedThreads++]; 1070370b324cSopenharmony_ci // wres = MtDecThread_CreateAndStart(nextThread); 1071370b324cSopenharmony_ci wres = MtDecThread_CreateEvents(nextThread); 1072370b324cSopenharmony_ci if (wres == 0) { wres = Event_Set(&nextThread->canWrite); 1073370b324cSopenharmony_ci if (wres == 0) { wres = Event_Set(&nextThread->canRead); 1074370b324cSopenharmony_ci if (wres == 0) { THREAD_FUNC_RET_TYPE res = MtDec_ThreadFunc(nextThread); 1075370b324cSopenharmony_ci wres = (WRes)(UINT_PTR)res; 1076370b324cSopenharmony_ci if (wres != 0) 1077370b324cSopenharmony_ci { 1078370b324cSopenharmony_ci p->needContinue = False; 1079370b324cSopenharmony_ci MtDec_CloseThreads(p); 1080370b324cSopenharmony_ci }}}} 1081370b324cSopenharmony_ci 1082370b324cSopenharmony_ci // wres = 17; // for test 1083370b324cSopenharmony_ci // wres = Event_Wait(&p->finishedEvent); 1084370b324cSopenharmony_ci 1085370b324cSopenharmony_ci sres = MY_SRes_HRESULT_FROM_WRes(wres); 1086370b324cSopenharmony_ci 1087370b324cSopenharmony_ci if (sres != 0) 1088370b324cSopenharmony_ci p->threadingErrorSRes = sres; 1089370b324cSopenharmony_ci 1090370b324cSopenharmony_ci if ( 1091370b324cSopenharmony_ci // wres == 0 1092370b324cSopenharmony_ci // wres != 0 1093370b324cSopenharmony_ci // || p->mtc.codeRes == SZ_ERROR_MEM 1094370b324cSopenharmony_ci p->isAllocError 1095370b324cSopenharmony_ci || p->threadingErrorSRes != SZ_OK 1096370b324cSopenharmony_ci || p->overflow) 1097370b324cSopenharmony_ci { 1098370b324cSopenharmony_ci // p->needContinue = True; 1099370b324cSopenharmony_ci } 1100370b324cSopenharmony_ci else 1101370b324cSopenharmony_ci p->needContinue = False; 1102370b324cSopenharmony_ci 1103370b324cSopenharmony_ci if (p->needContinue) 1104370b324cSopenharmony_ci return SZ_OK; 1105370b324cSopenharmony_ci 1106370b324cSopenharmony_ci // if (sres != SZ_OK) 1107370b324cSopenharmony_ci return sres; 1108370b324cSopenharmony_ci // return SZ_ERROR_FAIL; 1109370b324cSopenharmony_ci } 1110370b324cSopenharmony_ci} 1111370b324cSopenharmony_ci 1112370b324cSopenharmony_ci#endif 1113370b324cSopenharmony_ci 1114370b324cSopenharmony_ci#undef PRF 1115