3131namespace NEO {
3232int filterFunction (const struct dirent *file) {
3333 std::string_view fileName = file->d_name ;
34- if (fileName.find (" .cl_cache" ) != fileName.npos || fileName.find (" .l0_cache" ) != fileName.npos ) {
34+ if (fileName.find (" .cl_cache" ) != fileName.npos ||
35+ fileName.find (" .l0_cache" ) != fileName.npos ) {
3536 return 1 ;
3637 }
3738
@@ -50,38 +51,39 @@ bool compareByLastAccessTime(const ElementsStruct &a, ElementsStruct &b) {
5051bool CompilerCache::evictCache (uint64_t &bytesEvicted) {
5152 struct dirent **files = 0 ;
5253
53- int filesCount = NEO::SysCalls::scandir (config.cacheDir .c_str (), &files, filterFunction, NULL );
54+ const int filesCount = NEO::SysCalls::scandir (config.cacheDir .c_str (), &files, filterFunction, NULL );
5455
5556 if (filesCount == -1 ) {
5657 NEO::printDebugString (NEO::DebugManager.flags .PrintDebugMessages .get (), stderr, " PID %d [Cache failure]: Scandir failed! errno: %d\n " , NEO::SysCalls::getProcessId (), errno);
5758 return false ;
5859 }
5960
60- std::vector<ElementsStruct> vec ;
61- vec .reserve (static_cast <size_t >(filesCount));
61+ std::vector<ElementsStruct> cacheFiles ;
62+ cacheFiles .reserve (static_cast <size_t >(filesCount));
6263 for (int i = 0 ; i < filesCount; ++i) {
6364 ElementsStruct fileElement = {};
6465 fileElement.path = joinPath (config.cacheDir , files[i]->d_name );
6566 if (NEO::SysCalls::stat (fileElement.path .c_str (), &fileElement.statEl ) == 0 ) {
66- vec .push_back (std::move (fileElement));
67+ cacheFiles .push_back (std::move (fileElement));
6768 }
68- }
69-
70- for (int i = 0 ; i < filesCount; ++i) {
7169 free (files[i]);
7270 }
71+
7372 free (files);
7473
75- std::sort (vec .begin (), vec .end (), compareByLastAccessTime);
74+ std::sort (cacheFiles .begin (), cacheFiles .end (), compareByLastAccessTime);
7675
77- size_t evictionLimit = config.cacheSize / 3 ;
76+ bytesEvicted = 0 ;
77+ const auto evictionLimit = config.cacheSize / 3 ;
7878
79- size_t evictionSizeCount = 0 ;
80- for (size_t i = 0 ; i < vec.size (); ++i) {
81- NEO::SysCalls::unlink (vec[i].path );
82- evictionSizeCount += vec[i].statEl .st_size ;
79+ for (const auto &file : cacheFiles) {
80+ auto res = NEO::SysCalls::unlink (file.path );
81+ if (res == -1 ) {
82+ continue ;
83+ }
8384
84- if (evictionSizeCount > evictionLimit) {
85+ bytesEvicted += file.statEl .st_size ;
86+ if (bytesEvicted > evictionLimit) {
8587 return true ;
8688 }
8789 }
@@ -146,7 +148,7 @@ void CompilerCache::lockConfigFileAndReadSize(const std::string &configFilePath,
146148 }
147149 }
148150
149- int lockErr = NEO::SysCalls::flock (std::get<int >(fd), LOCK_EX);
151+ const int lockErr = NEO::SysCalls::flock (std::get<int >(fd), LOCK_EX);
150152
151153 if (lockErr < 0 ) {
152154 NEO::printDebugString (NEO::DebugManager.flags .PrintDebugMessages .get (), stderr, " PID %d [Cache failure]: Lock config file failed! errno: %d\n " , NEO::SysCalls::getProcessId (), errno);
@@ -159,7 +161,7 @@ void CompilerCache::lockConfigFileAndReadSize(const std::string &configFilePath,
159161 if (countDirectorySize) {
160162 struct dirent **files = {};
161163
162- int filesCount = NEO::SysCalls::scandir (config.cacheDir .c_str (), &files, filterFunction, NULL );
164+ const int filesCount = NEO::SysCalls::scandir (config.cacheDir .c_str (), &files, filterFunction, NULL );
163165
164166 if (filesCount == -1 ) {
165167 unlockFileAndClose (std::get<int >(fd));
@@ -168,30 +170,28 @@ void CompilerCache::lockConfigFileAndReadSize(const std::string &configFilePath,
168170 return ;
169171 }
170172
171- std::vector<ElementsStruct> vec ;
172- vec .reserve (static_cast <size_t >(filesCount));
173+ std::vector<ElementsStruct> cacheFiles ;
174+ cacheFiles .reserve (static_cast <size_t >(filesCount));
173175 for (int i = 0 ; i < filesCount; ++i) {
174176 std::string_view fileName = files[i]->d_name ;
175177 if (fileName.find (config.cacheFileExtension ) != fileName.npos ) {
176178 ElementsStruct fileElement = {};
177179 fileElement.path = joinPath (config.cacheDir , files[i]->d_name );
178180 if (NEO::SysCalls::stat (fileElement.path .c_str (), &fileElement.statEl ) == 0 ) {
179- vec .push_back (std::move (fileElement));
181+ cacheFiles .push_back (std::move (fileElement));
180182 }
181183 }
182- }
183-
184- for (int i = 0 ; i < filesCount; ++i) {
185184 free (files[i]);
186185 }
186+
187187 free (files);
188188
189- for (auto &element : vec ) {
189+ for (const auto &element : cacheFiles ) {
190190 directorySize += element.statEl .st_size ;
191191 }
192192
193193 } else {
194- ssize_t readErr = NEO::SysCalls::pread (std::get<int >(fd), &directorySize, sizeof (directorySize), 0 );
194+ const ssize_t readErr = NEO::SysCalls::pread (std::get<int >(fd), &directorySize, sizeof (directorySize), 0 );
195195
196196 if (readErr < 0 ) {
197197 directorySize = 0 ;
@@ -202,16 +202,30 @@ void CompilerCache::lockConfigFileAndReadSize(const std::string &configFilePath,
202202 }
203203}
204204
205+ class HandleGuard {
206+ public:
207+ HandleGuard () = delete ;
208+ explicit HandleGuard (int &fileDescriptor) : fd(fileDescriptor) {}
209+ ~HandleGuard () {
210+ if (fd != -1 ) {
211+ unlockFileAndClose (fd);
212+ }
213+ }
214+
215+ private:
216+ int fd = -1 ;
217+ };
218+
205219bool CompilerCache::cacheBinary (const std::string &kernelFileHash, const char *pBinary, size_t binarySize) {
206- if (pBinary == nullptr || binarySize == 0 ) {
220+ if (pBinary == nullptr || binarySize == 0 || binarySize > config. cacheSize ) {
207221 return false ;
208222 }
209223
210224 std::unique_lock<std::mutex> lock (cacheAccessMtx);
211225 constexpr std::string_view configFileName = " config.file" ;
212226
213227 std::string configFilePath = joinPath (config.cacheDir , configFileName.data ());
214- std::string filePath = joinPath (config.cacheDir , kernelFileHash + config.cacheFileExtension );
228+ std::string cacheFilePath = joinPath (config.cacheDir , kernelFileHash + config.cacheFileExtension );
215229
216230 UnifiedHandle fd{-1 };
217231 size_t directorySize = 0u ;
@@ -222,42 +236,44 @@ bool CompilerCache::cacheBinary(const std::string &kernelFileHash, const char *p
222236 return false ;
223237 }
224238
239+ HandleGuard configGuard (std::get<int >(fd));
240+
225241 struct stat statbuf = {};
226- if (NEO::SysCalls::stat (filePath, &statbuf) == 0 ) {
227- unlockFileAndClose (std::get<int >(fd));
242+ if (NEO::SysCalls::stat (cacheFilePath, &statbuf) == 0 ) {
228243 return true ;
229244 }
230245
231- size_t maxSize = config.cacheSize ;
232-
233- if (maxSize < directorySize + binarySize) {
246+ const size_t maxSize = config.cacheSize ;
247+ if (maxSize < (directorySize + binarySize)) {
234248 uint64_t bytesEvicted{0u };
235- if (!evictCache (bytesEvicted)) {
236- unlockFileAndClose (std::get<int >(fd));
249+ const auto evictSuccess = evictCache (bytesEvicted);
250+ const auto availableSpace = maxSize - directorySize + bytesEvicted;
251+
252+ directorySize = std::max<size_t >(0 , directorySize - bytesEvicted);
253+
254+ if (!evictSuccess || binarySize > availableSpace) {
255+ if (bytesEvicted > 0 ) {
256+ NEO::SysCalls::pwrite (std::get<int >(fd), &directorySize, sizeof (directorySize), 0 );
257+ }
237258 return false ;
238259 }
239260 }
240261
241262 std::string tmpFileName = " cl_cache.XXXXXX" ;
242-
243263 std::string tmpFilePath = joinPath (config.cacheDir , tmpFileName);
244264
245265 if (!createUniqueTempFileAndWriteData (tmpFilePath.data (), pBinary, binarySize)) {
246- unlockFileAndClose (std::get<int >(fd));
247266 return false ;
248267 }
249268
250- if (!renameTempFileBinaryToProperName (tmpFilePath, filePath)) {
251- unlockFileAndClose (std::get<int >(fd));
269+ if (!renameTempFileBinaryToProperName (tmpFilePath, cacheFilePath)) {
252270 return false ;
253271 }
254272
255273 directorySize += binarySize;
256274
257275 NEO::SysCalls::pwrite (std::get<int >(fd), &directorySize, sizeof (directorySize), 0 );
258276
259- unlockFileAndClose (std::get<int >(fd));
260-
261277 return true ;
262278}
263279
0 commit comments