xref: /aosp_15_r20/external/lzma/CPP/7zip/Common/MemBlocks.cpp (revision f6dc9357d832569d4d1f5d24eacdb3935a1ae8e6)
1*f6dc9357SAndroid Build Coastguard Worker // MemBlocks.cpp
2*f6dc9357SAndroid Build Coastguard Worker 
3*f6dc9357SAndroid Build Coastguard Worker #include "StdAfx.h"
4*f6dc9357SAndroid Build Coastguard Worker 
5*f6dc9357SAndroid Build Coastguard Worker #include "../../../C/Alloc.h"
6*f6dc9357SAndroid Build Coastguard Worker 
7*f6dc9357SAndroid Build Coastguard Worker #include "MemBlocks.h"
8*f6dc9357SAndroid Build Coastguard Worker #include "StreamUtils.h"
9*f6dc9357SAndroid Build Coastguard Worker 
AllocateSpace_bool(size_t numBlocks)10*f6dc9357SAndroid Build Coastguard Worker bool CMemBlockManager::AllocateSpace_bool(size_t numBlocks)
11*f6dc9357SAndroid Build Coastguard Worker {
12*f6dc9357SAndroid Build Coastguard Worker   FreeSpace();
13*f6dc9357SAndroid Build Coastguard Worker   if (numBlocks == 0)
14*f6dc9357SAndroid Build Coastguard Worker   {
15*f6dc9357SAndroid Build Coastguard Worker     return true;
16*f6dc9357SAndroid Build Coastguard Worker     // return false;
17*f6dc9357SAndroid Build Coastguard Worker   }
18*f6dc9357SAndroid Build Coastguard Worker   if (_blockSize < sizeof(void *))
19*f6dc9357SAndroid Build Coastguard Worker     return false;
20*f6dc9357SAndroid Build Coastguard Worker   const size_t totalSize = numBlocks * _blockSize;
21*f6dc9357SAndroid Build Coastguard Worker   if (totalSize / _blockSize != numBlocks)
22*f6dc9357SAndroid Build Coastguard Worker     return false;
23*f6dc9357SAndroid Build Coastguard Worker   _data = ::MidAlloc(totalSize);
24*f6dc9357SAndroid Build Coastguard Worker   if (!_data)
25*f6dc9357SAndroid Build Coastguard Worker     return false;
26*f6dc9357SAndroid Build Coastguard Worker   Byte *p = (Byte *)_data;
27*f6dc9357SAndroid Build Coastguard Worker   for (size_t i = 0; i + 1 < numBlocks; i++, p += _blockSize)
28*f6dc9357SAndroid Build Coastguard Worker     *(Byte **)(void *)p = (p + _blockSize);
29*f6dc9357SAndroid Build Coastguard Worker   *(Byte **)(void *)p = NULL;
30*f6dc9357SAndroid Build Coastguard Worker   _headFree = _data;
31*f6dc9357SAndroid Build Coastguard Worker   return true;
32*f6dc9357SAndroid Build Coastguard Worker }
33*f6dc9357SAndroid Build Coastguard Worker 
FreeSpace()34*f6dc9357SAndroid Build Coastguard Worker void CMemBlockManager::FreeSpace()
35*f6dc9357SAndroid Build Coastguard Worker {
36*f6dc9357SAndroid Build Coastguard Worker   ::MidFree(_data);
37*f6dc9357SAndroid Build Coastguard Worker   _data = NULL;
38*f6dc9357SAndroid Build Coastguard Worker   _headFree= NULL;
39*f6dc9357SAndroid Build Coastguard Worker }
40*f6dc9357SAndroid Build Coastguard Worker 
AllocateBlock()41*f6dc9357SAndroid Build Coastguard Worker void *CMemBlockManager::AllocateBlock()
42*f6dc9357SAndroid Build Coastguard Worker {
43*f6dc9357SAndroid Build Coastguard Worker   void *p = _headFree;
44*f6dc9357SAndroid Build Coastguard Worker   if (p)
45*f6dc9357SAndroid Build Coastguard Worker     _headFree = *(void **)p;
46*f6dc9357SAndroid Build Coastguard Worker   return p;
47*f6dc9357SAndroid Build Coastguard Worker }
48*f6dc9357SAndroid Build Coastguard Worker 
FreeBlock(void * p)49*f6dc9357SAndroid Build Coastguard Worker void CMemBlockManager::FreeBlock(void *p)
50*f6dc9357SAndroid Build Coastguard Worker {
51*f6dc9357SAndroid Build Coastguard Worker   if (!p)
52*f6dc9357SAndroid Build Coastguard Worker     return;
53*f6dc9357SAndroid Build Coastguard Worker   *(void **)p = _headFree;
54*f6dc9357SAndroid Build Coastguard Worker   _headFree = p;
55*f6dc9357SAndroid Build Coastguard Worker }
56*f6dc9357SAndroid Build Coastguard Worker 
57*f6dc9357SAndroid Build Coastguard Worker 
58*f6dc9357SAndroid Build Coastguard Worker // #include <stdio.h>
59*f6dc9357SAndroid Build Coastguard Worker 
AllocateSpace(size_t numBlocks,size_t numNoLockBlocks)60*f6dc9357SAndroid Build Coastguard Worker HRESULT CMemBlockManagerMt::AllocateSpace(size_t numBlocks, size_t numNoLockBlocks)
61*f6dc9357SAndroid Build Coastguard Worker {
62*f6dc9357SAndroid Build Coastguard Worker   if (numNoLockBlocks > numBlocks)
63*f6dc9357SAndroid Build Coastguard Worker     return E_INVALIDARG;
64*f6dc9357SAndroid Build Coastguard Worker   const size_t numLockBlocks = numBlocks - numNoLockBlocks;
65*f6dc9357SAndroid Build Coastguard Worker   UInt32 maxCount = (UInt32)numLockBlocks;
66*f6dc9357SAndroid Build Coastguard Worker   if (maxCount != numLockBlocks)
67*f6dc9357SAndroid Build Coastguard Worker     return E_OUTOFMEMORY;
68*f6dc9357SAndroid Build Coastguard Worker   if (!CMemBlockManager::AllocateSpace_bool(numBlocks))
69*f6dc9357SAndroid Build Coastguard Worker     return E_OUTOFMEMORY;
70*f6dc9357SAndroid Build Coastguard Worker   // we need (maxCount = 1), if we want to create non-use empty Semaphore
71*f6dc9357SAndroid Build Coastguard Worker   if (maxCount == 0)
72*f6dc9357SAndroid Build Coastguard Worker     maxCount = 1;
73*f6dc9357SAndroid Build Coastguard Worker 
74*f6dc9357SAndroid Build Coastguard Worker   // printf("\n Synchro.Create() \n");
75*f6dc9357SAndroid Build Coastguard Worker   WRes wres;
76*f6dc9357SAndroid Build Coastguard Worker   #ifndef _WIN32
77*f6dc9357SAndroid Build Coastguard Worker   Semaphore.Close();
78*f6dc9357SAndroid Build Coastguard Worker   wres = Synchro.Create();
79*f6dc9357SAndroid Build Coastguard Worker   if (wres != 0)
80*f6dc9357SAndroid Build Coastguard Worker     return HRESULT_FROM_WIN32(wres);
81*f6dc9357SAndroid Build Coastguard Worker   wres = Semaphore.Create(&Synchro, (UInt32)numLockBlocks, maxCount);
82*f6dc9357SAndroid Build Coastguard Worker   #else
83*f6dc9357SAndroid Build Coastguard Worker   wres = Semaphore.OptCreateInit((UInt32)numLockBlocks, maxCount);
84*f6dc9357SAndroid Build Coastguard Worker   #endif
85*f6dc9357SAndroid Build Coastguard Worker 
86*f6dc9357SAndroid Build Coastguard Worker   return HRESULT_FROM_WIN32(wres);
87*f6dc9357SAndroid Build Coastguard Worker }
88*f6dc9357SAndroid Build Coastguard Worker 
89*f6dc9357SAndroid Build Coastguard Worker 
AllocateSpaceAlways(size_t desiredNumberOfBlocks,size_t numNoLockBlocks)90*f6dc9357SAndroid Build Coastguard Worker HRESULT CMemBlockManagerMt::AllocateSpaceAlways(size_t desiredNumberOfBlocks, size_t numNoLockBlocks)
91*f6dc9357SAndroid Build Coastguard Worker {
92*f6dc9357SAndroid Build Coastguard Worker   // desiredNumberOfBlocks = 0; // for debug
93*f6dc9357SAndroid Build Coastguard Worker   if (numNoLockBlocks > desiredNumberOfBlocks)
94*f6dc9357SAndroid Build Coastguard Worker     return E_INVALIDARG;
95*f6dc9357SAndroid Build Coastguard Worker   for (;;)
96*f6dc9357SAndroid Build Coastguard Worker   {
97*f6dc9357SAndroid Build Coastguard Worker     // if (desiredNumberOfBlocks == 0) return E_OUTOFMEMORY;
98*f6dc9357SAndroid Build Coastguard Worker     const HRESULT hres = AllocateSpace(desiredNumberOfBlocks, numNoLockBlocks);
99*f6dc9357SAndroid Build Coastguard Worker     if (hres != E_OUTOFMEMORY)
100*f6dc9357SAndroid Build Coastguard Worker       return hres;
101*f6dc9357SAndroid Build Coastguard Worker     if (desiredNumberOfBlocks == numNoLockBlocks)
102*f6dc9357SAndroid Build Coastguard Worker       return E_OUTOFMEMORY;
103*f6dc9357SAndroid Build Coastguard Worker     desiredNumberOfBlocks = numNoLockBlocks + ((desiredNumberOfBlocks - numNoLockBlocks) >> 1);
104*f6dc9357SAndroid Build Coastguard Worker   }
105*f6dc9357SAndroid Build Coastguard Worker }
106*f6dc9357SAndroid Build Coastguard Worker 
FreeSpace()107*f6dc9357SAndroid Build Coastguard Worker void CMemBlockManagerMt::FreeSpace()
108*f6dc9357SAndroid Build Coastguard Worker {
109*f6dc9357SAndroid Build Coastguard Worker   Semaphore.Close();
110*f6dc9357SAndroid Build Coastguard Worker   CMemBlockManager::FreeSpace();
111*f6dc9357SAndroid Build Coastguard Worker }
112*f6dc9357SAndroid Build Coastguard Worker 
AllocateBlock()113*f6dc9357SAndroid Build Coastguard Worker void *CMemBlockManagerMt::AllocateBlock()
114*f6dc9357SAndroid Build Coastguard Worker {
115*f6dc9357SAndroid Build Coastguard Worker   // Semaphore.Lock();
116*f6dc9357SAndroid Build Coastguard Worker   NWindows::NSynchronization::CCriticalSectionLock lock(_criticalSection);
117*f6dc9357SAndroid Build Coastguard Worker   return CMemBlockManager::AllocateBlock();
118*f6dc9357SAndroid Build Coastguard Worker }
119*f6dc9357SAndroid Build Coastguard Worker 
FreeBlock(void * p,bool lockMode)120*f6dc9357SAndroid Build Coastguard Worker void CMemBlockManagerMt::FreeBlock(void *p, bool lockMode)
121*f6dc9357SAndroid Build Coastguard Worker {
122*f6dc9357SAndroid Build Coastguard Worker   if (!p)
123*f6dc9357SAndroid Build Coastguard Worker     return;
124*f6dc9357SAndroid Build Coastguard Worker   {
125*f6dc9357SAndroid Build Coastguard Worker     NWindows::NSynchronization::CCriticalSectionLock lock(_criticalSection);
126*f6dc9357SAndroid Build Coastguard Worker     CMemBlockManager::FreeBlock(p);
127*f6dc9357SAndroid Build Coastguard Worker   }
128*f6dc9357SAndroid Build Coastguard Worker   if (lockMode)
129*f6dc9357SAndroid Build Coastguard Worker     Semaphore.Release();
130*f6dc9357SAndroid Build Coastguard Worker }
131*f6dc9357SAndroid Build Coastguard Worker 
132*f6dc9357SAndroid Build Coastguard Worker 
133*f6dc9357SAndroid Build Coastguard Worker 
Free(CMemBlockManagerMt * manager)134*f6dc9357SAndroid Build Coastguard Worker void CMemBlocks::Free(CMemBlockManagerMt *manager)
135*f6dc9357SAndroid Build Coastguard Worker {
136*f6dc9357SAndroid Build Coastguard Worker   while (Blocks.Size() > 0)
137*f6dc9357SAndroid Build Coastguard Worker   {
138*f6dc9357SAndroid Build Coastguard Worker     manager->FreeBlock(Blocks.Back());
139*f6dc9357SAndroid Build Coastguard Worker     Blocks.DeleteBack();
140*f6dc9357SAndroid Build Coastguard Worker   }
141*f6dc9357SAndroid Build Coastguard Worker   TotalSize = 0;
142*f6dc9357SAndroid Build Coastguard Worker }
143*f6dc9357SAndroid Build Coastguard Worker 
FreeOpt(CMemBlockManagerMt * manager)144*f6dc9357SAndroid Build Coastguard Worker void CMemBlocks::FreeOpt(CMemBlockManagerMt *manager)
145*f6dc9357SAndroid Build Coastguard Worker {
146*f6dc9357SAndroid Build Coastguard Worker   Free(manager);
147*f6dc9357SAndroid Build Coastguard Worker   Blocks.ClearAndFree();
148*f6dc9357SAndroid Build Coastguard Worker }
149*f6dc9357SAndroid Build Coastguard Worker 
WriteToStream(size_t blockSize,ISequentialOutStream * outStream) const150*f6dc9357SAndroid Build Coastguard Worker HRESULT CMemBlocks::WriteToStream(size_t blockSize, ISequentialOutStream *outStream) const
151*f6dc9357SAndroid Build Coastguard Worker {
152*f6dc9357SAndroid Build Coastguard Worker   UInt64 totalSize = TotalSize;
153*f6dc9357SAndroid Build Coastguard Worker   for (unsigned blockIndex = 0; totalSize > 0; blockIndex++)
154*f6dc9357SAndroid Build Coastguard Worker   {
155*f6dc9357SAndroid Build Coastguard Worker     size_t curSize = blockSize;
156*f6dc9357SAndroid Build Coastguard Worker     if (curSize > totalSize)
157*f6dc9357SAndroid Build Coastguard Worker       curSize = (size_t)totalSize;
158*f6dc9357SAndroid Build Coastguard Worker     if (blockIndex >= Blocks.Size())
159*f6dc9357SAndroid Build Coastguard Worker       return E_FAIL;
160*f6dc9357SAndroid Build Coastguard Worker     RINOK(WriteStream(outStream, Blocks[blockIndex], curSize))
161*f6dc9357SAndroid Build Coastguard Worker     totalSize -= curSize;
162*f6dc9357SAndroid Build Coastguard Worker   }
163*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
164*f6dc9357SAndroid Build Coastguard Worker }
165*f6dc9357SAndroid Build Coastguard Worker 
166*f6dc9357SAndroid Build Coastguard Worker 
FreeBlock(unsigned index,CMemBlockManagerMt * memManager)167*f6dc9357SAndroid Build Coastguard Worker void CMemLockBlocks::FreeBlock(unsigned index, CMemBlockManagerMt *memManager)
168*f6dc9357SAndroid Build Coastguard Worker {
169*f6dc9357SAndroid Build Coastguard Worker   memManager->FreeBlock(Blocks[index], LockMode);
170*f6dc9357SAndroid Build Coastguard Worker   Blocks[index] = NULL;
171*f6dc9357SAndroid Build Coastguard Worker }
172*f6dc9357SAndroid Build Coastguard Worker 
Free(CMemBlockManagerMt * memManager)173*f6dc9357SAndroid Build Coastguard Worker void CMemLockBlocks::Free(CMemBlockManagerMt *memManager)
174*f6dc9357SAndroid Build Coastguard Worker {
175*f6dc9357SAndroid Build Coastguard Worker   while (Blocks.Size() > 0)
176*f6dc9357SAndroid Build Coastguard Worker   {
177*f6dc9357SAndroid Build Coastguard Worker     FreeBlock(Blocks.Size() - 1, memManager);
178*f6dc9357SAndroid Build Coastguard Worker     Blocks.DeleteBack();
179*f6dc9357SAndroid Build Coastguard Worker   }
180*f6dc9357SAndroid Build Coastguard Worker   TotalSize = 0;
181*f6dc9357SAndroid Build Coastguard Worker }
182*f6dc9357SAndroid Build Coastguard Worker 
183*f6dc9357SAndroid Build Coastguard Worker /*
184*f6dc9357SAndroid Build Coastguard Worker HRes CMemLockBlocks::SwitchToNoLockMode(CMemBlockManagerMt *memManager)
185*f6dc9357SAndroid Build Coastguard Worker {
186*f6dc9357SAndroid Build Coastguard Worker   if (LockMode)
187*f6dc9357SAndroid Build Coastguard Worker   {
188*f6dc9357SAndroid Build Coastguard Worker     if (Blocks.Size() > 0)
189*f6dc9357SAndroid Build Coastguard Worker     {
190*f6dc9357SAndroid Build Coastguard Worker       RINOK(memManager->ReleaseLockedBlocks(Blocks.Size()));
191*f6dc9357SAndroid Build Coastguard Worker     }
192*f6dc9357SAndroid Build Coastguard Worker     LockMode = false;
193*f6dc9357SAndroid Build Coastguard Worker   }
194*f6dc9357SAndroid Build Coastguard Worker   return 0;
195*f6dc9357SAndroid Build Coastguard Worker }
196*f6dc9357SAndroid Build Coastguard Worker */
197*f6dc9357SAndroid Build Coastguard Worker 
Detach(CMemLockBlocks & blocks,CMemBlockManagerMt * memManager)198*f6dc9357SAndroid Build Coastguard Worker void CMemLockBlocks::Detach(CMemLockBlocks &blocks, CMemBlockManagerMt *memManager)
199*f6dc9357SAndroid Build Coastguard Worker {
200*f6dc9357SAndroid Build Coastguard Worker   blocks.Free(memManager);
201*f6dc9357SAndroid Build Coastguard Worker   blocks.LockMode = LockMode;
202*f6dc9357SAndroid Build Coastguard Worker   UInt64 totalSize = 0;
203*f6dc9357SAndroid Build Coastguard Worker   const size_t blockSize = memManager->GetBlockSize();
204*f6dc9357SAndroid Build Coastguard Worker   FOR_VECTOR (i, Blocks)
205*f6dc9357SAndroid Build Coastguard Worker   {
206*f6dc9357SAndroid Build Coastguard Worker     if (totalSize < TotalSize)
207*f6dc9357SAndroid Build Coastguard Worker       blocks.Blocks.Add(Blocks[i]);
208*f6dc9357SAndroid Build Coastguard Worker     else
209*f6dc9357SAndroid Build Coastguard Worker       FreeBlock(i, memManager);
210*f6dc9357SAndroid Build Coastguard Worker     Blocks[i] = NULL;
211*f6dc9357SAndroid Build Coastguard Worker     totalSize += blockSize;
212*f6dc9357SAndroid Build Coastguard Worker   }
213*f6dc9357SAndroid Build Coastguard Worker   blocks.TotalSize = TotalSize;
214*f6dc9357SAndroid Build Coastguard Worker   Free(memManager);
215*f6dc9357SAndroid Build Coastguard Worker }
216