1// [Blend2D]
2// 2D Vector Graphics Powered by a JIT Compiler.
3//
4// [License]
5// Zlib - See LICENSE.md file in the package.
6
7#include "./blapi-build_p.h"
8#include "./blruntime_p.h"
9#include "./blsupport_p.h"
10
11#ifndef BL_BUILD_NO_JIT
12 #include <asmjit/asmjit.h>
13#endif
14
15// ============================================================================
16// [Global Variables]
17// ============================================================================
18
19BLRuntimeContext blRuntimeContext;
20
21// ============================================================================
22// [BLRuntime - Build Information]
23// ============================================================================
24
25#define BL_STRINGIFY_WRAP(N) #N
26#define BL_STRINGIFY(N) BL_STRINGIFY_WRAP(N)
27
28static const BLRuntimeBuildInfo blRuntimeBuildInfo = {
29 // Library Version.
30 { BL_VERSION },
31
32 // Build Type.
33#ifdef BL_BUILD_DEBUG
34 BL_RUNTIME_BUILD_TYPE_DEBUG,
35#else
36 BL_RUNTIME_BUILD_TYPE_RELEASE,
37#endif
38
39 // Baseline CPU features.
40 0
41#ifdef BL_TARGET_OPT_SSE2
42 | BL_RUNTIME_CPU_FEATURE_X86_SSE2
43#endif
44#ifdef BL_TARGET_OPT_SSE3
45 | BL_RUNTIME_CPU_FEATURE_X86_SSE3
46#endif
47#ifdef BL_TARGET_OPT_SSSE3
48 | BL_RUNTIME_CPU_FEATURE_X86_SSSE3
49#endif
50#ifdef BL_TARGET_OPT_SSE4_1
51 | BL_RUNTIME_CPU_FEATURE_X86_SSE4_1
52#endif
53#ifdef BL_TARGET_OPT_SSE4_2
54 | BL_RUNTIME_CPU_FEATURE_X86_SSE4_2
55#endif
56#ifdef BL_TARGET_OPT_AVX
57 | BL_RUNTIME_CPU_FEATURE_X86_AVX
58#endif
59#ifdef BL_TARGET_OPT_AVX2
60 | BL_RUNTIME_CPU_FEATURE_X86_AVX2
61#endif
62 ,
63
64 // Supported CPU features.
65 0
66#ifdef BL_BUILD_OPT_SSE2
67 | BL_RUNTIME_CPU_FEATURE_X86_SSE2
68#endif
69#ifdef BL_BUILD_OPT_SSE3
70 | BL_RUNTIME_CPU_FEATURE_X86_SSE3
71#endif
72#ifdef BL_BUILD_OPT_SSSE3
73 | BL_RUNTIME_CPU_FEATURE_X86_SSSE3
74#endif
75#ifdef BL_BUILD_OPT_SSE4_1
76 | BL_RUNTIME_CPU_FEATURE_X86_SSE4_1
77#endif
78#ifdef BL_BUILD_OPT_SSE4_2
79 | BL_RUNTIME_CPU_FEATURE_X86_SSE4_2
80#endif
81#ifdef BL_BUILD_OPT_AVX
82 | BL_RUNTIME_CPU_FEATURE_X86_AVX
83#endif
84#ifdef BL_BUILD_OPT_AVX2
85 | BL_RUNTIME_CPU_FEATURE_X86_AVX2
86#endif
87 ,
88
89 // Maximum image size.
90 BL_RUNTIME_MAX_IMAGE_SIZE,
91
92 // Maximum thread count.
93 BL_RUNTIME_MAX_THREAD_COUNT,
94
95 // Reserved
96 { 0 },
97
98 // Compiler Info.
99#if defined(__INTEL_COMPILER)
100 "ICC"
101#elif defined(__clang_minor__)
102 "Clang " BL_STRINGIFY(__clang_major__) "." BL_STRINGIFY(__clang_minor__)
103#elif defined(__GNUC_MINOR__)
104 "GCC " BL_STRINGIFY(__GNUC__) "." BL_STRINGIFY(__GNUC_MINOR__)
105#elif defined(_MSC_VER)
106 "MSC"
107#else
108 "Unknown"
109#endif
110};
111
112// ============================================================================
113// [BLRuntime - System Information]
114// ============================================================================
115
116#ifndef BL_BUILD_NO_JIT
117static BL_INLINE uint32_t blRuntimeDetectCpuFeatures(const asmjit::CpuInfo& asmCpuInfo) noexcept {
118 uint32_t features = 0;
119
120#if BL_TARGET_ARCH_X86
121 if (asmCpuInfo.hasFeature(asmjit::x86::Features::kSSE2 )) features |= BL_RUNTIME_CPU_FEATURE_X86_SSE2;
122 if (asmCpuInfo.hasFeature(asmjit::x86::Features::kSSE3 )) features |= BL_RUNTIME_CPU_FEATURE_X86_SSE3;
123 if (asmCpuInfo.hasFeature(asmjit::x86::Features::kSSSE3 )) features |= BL_RUNTIME_CPU_FEATURE_X86_SSSE3;
124 if (asmCpuInfo.hasFeature(asmjit::x86::Features::kSSE4_1)) features |= BL_RUNTIME_CPU_FEATURE_X86_SSE4_1;
125 if (asmCpuInfo.hasFeature(asmjit::x86::Features::kSSE4_2)) features |= BL_RUNTIME_CPU_FEATURE_X86_SSE4_2;
126 if (asmCpuInfo.hasFeature(asmjit::x86::Features::kAVX )) features |= BL_RUNTIME_CPU_FEATURE_X86_AVX;
127 if (asmCpuInfo.hasFeature(asmjit::x86::Features::kAVX2 )) features |= BL_RUNTIME_CPU_FEATURE_X86_AVX2;
128#endif
129
130 return features;
131}
132#endif
133
134static BL_INLINE void blRuntimeInitSystemInfo(BLRuntimeSystemInfo& info) noexcept {
135 info.cpuArch = BL_TARGET_ARCH_X86 ? BL_RUNTIME_CPU_ARCH_X86 :
136 BL_TARGET_ARCH_ARM ? BL_RUNTIME_CPU_ARCH_ARM :
137 BL_TARGET_ARCH_MIPS ? BL_RUNTIME_CPU_ARCH_MIPS : BL_RUNTIME_CPU_ARCH_UNKNOWN;
138
139#ifndef BL_BUILD_NO_JIT
140 const asmjit::CpuInfo& asmCpuInfo = asmjit::CpuInfo::host();
141 info.cpuFeatures = blRuntimeDetectCpuFeatures(asmCpuInfo);
142 info.coreCount = asmCpuInfo.hwThreadCount();
143 info.threadCount = asmCpuInfo.hwThreadCount();
144#endif
145
146#ifdef _WIN32
147 SYSTEM_INFO si;
148 GetSystemInfo(&si);
149 info.minThreadStackSize = si.dwAllocationGranularity;
150 info.allocationGranularity = si.dwAllocationGranularity;
151#else
152 #if defined(_SC_PAGESIZE)
153 info.allocationGranularity = uint32_t(sysconf(_SC_PAGESIZE));
154 #else
155 info.allocationGranularity = uint32_t(getpagesize());
156 #endif
157
158 #if defined(PTHREAD_STACK_MIN)
159 info.minThreadStackSize = uint32_t(PTHREAD_STACK_MIN);
160 #elif defined(_SC_THREAD_STACK_MIN)
161 info.minThreadStackSize = uint32_t(sysconf(_SC_THREAD_STACK_MIN));
162 #else
163 #pragma message("Missing 'BLRuntimeSystemInfo::minStackSize' implementation")
164 info.minThreadStackSize = blMax<uint32_t>(info.allocationGranularity, 65536u);
165 #endif
166#endif
167
168 info.minWorkerStackSize = blAlignUp(blMax<uint32_t>(info.minThreadStackSize, 4096u), info.allocationGranularity);
169}
170
171// ============================================================================
172// [BLRuntime - Initialization & Shutdown]
173// ============================================================================
174
175BLResult blRuntimeInit() noexcept {
176 BLRuntimeContext* rt = &blRuntimeContext;
177 if (blAtomicFetchAdd(&rt->refCount) != 0)
178 return BL_SUCCESS;
179
180 // Initialize system information - we need this first so we can properly
181 // initialize everything that relies on system info (thread-pool, optimized
182 // functions, etc...).
183 blRuntimeInitSystemInfo(rt->systemInfo);
184
185 // Call "Runtime Initialization" handlers.
186 // - These would automatically install shutdown handlers when necessary.
187 blThreadingRtInit(rt);
188 blThreadPoolRtInit(rt);
189 blZeroAllocatorRtInit(rt);
190 blMatrix2DRtInit(rt);
191 blArrayRtInit(rt);
192 blStringRtInit(rt);
193 blPathRtInit(rt);
194 blRegionRtInit(rt);
195 blImageRtInit(rt);
196 blImageScalerRtInit(rt);
197 blPatternRtInit(rt);
198 blGradientRtInit(rt);
199 blFontRtInit(rt);
200
201#if !defined(BL_BUILD_NO_FIXED_PIPE)
202 blFixedPipeRtInit(rt);
203#endif
204
205#if !defined(BL_BUILD_NO_JIT)
206 blPipeGenRtInit(rt);
207#endif
208
209 blContextRtInit(rt);
210
211 return BL_SUCCESS;
212}
213
214BLResult blRuntimeShutdown() noexcept {
215 BLRuntimeContext* rt = &blRuntimeContext;
216 if (blAtomicFetchSub(&rt->refCount) != 1)
217 return BL_SUCCESS;
218
219 rt->shutdownHandlers.callInReverseOrder(rt);
220 rt->shutdownHandlers.reset();
221
222 return BL_SUCCESS;
223}
224
225// Static instance that calls `blRuntimeInit()` and `blRuntimeShutdown()`.
226class BLRuntimeAutoInit {
227public:
228 inline BLRuntimeAutoInit() noexcept { blRuntimeInit(); }
229 inline ~BLRuntimeAutoInit() noexcept { blRuntimeShutdown(); }
230};
231static BLRuntimeAutoInit blRuntimeAutoInit;
232
233// ============================================================================
234// [BLRuntime - Cleanup]
235// ============================================================================
236
237BLResult blRuntimeCleanup(uint32_t cleanupFlags) noexcept {
238 BLRuntimeContext* rt = &blRuntimeContext;
239 rt->cleanupHandlers.call(rt, cleanupFlags);
240 return BL_SUCCESS;
241}
242
243// ============================================================================
244// [BLRuntime - Query Info]
245// ============================================================================
246
247BLResult blRuntimeQueryInfo(uint32_t infoType, void* infoOut) noexcept {
248 BLRuntimeContext* rt = &blRuntimeContext;
249
250 switch (infoType) {
251 case BL_RUNTIME_INFO_TYPE_BUILD: {
252 BLRuntimeBuildInfo* buildInfo = static_cast<BLRuntimeBuildInfo*>(infoOut);
253 memcpy(buildInfo, &blRuntimeBuildInfo, sizeof(BLRuntimeBuildInfo));
254 return BL_SUCCESS;
255 }
256
257 case BL_RUNTIME_INFO_TYPE_SYSTEM: {
258 BLRuntimeSystemInfo* systemInfo = static_cast<BLRuntimeSystemInfo*>(infoOut);
259 memcpy(systemInfo, &rt->systemInfo, sizeof(BLRuntimeSystemInfo));
260 return BL_SUCCESS;
261 }
262
263 case BL_RUNTIME_INFO_TYPE_MEMORY: {
264 BLRuntimeMemoryInfo* memoryInfo = static_cast<BLRuntimeMemoryInfo*>(infoOut);
265 memoryInfo->reset();
266 rt->memoryInfoHandlers.call(rt, memoryInfo);
267 return BL_SUCCESS;
268 }
269
270 default:
271 return blTraceError(BL_ERROR_INVALID_VALUE);
272 }
273}
274
275// ============================================================================
276// [BLRuntime - Message]
277// ============================================================================
278
279BLResult blRuntimeMessageOut(const char* msg) noexcept {
280#if defined(_WIN32)
281 // Support both Console and GUI applications on Windows.
282 OutputDebugStringA(msg);
283#endif
284
285 fputs(msg, stderr);
286 return BL_SUCCESS;
287}
288
289BLResult blRuntimeMessageFmt(const char* fmt, ...) noexcept {
290 va_list ap;
291 va_start(ap, fmt);
292 BLResult result = blRuntimeMessageVFmt(fmt, ap);
293 va_end(ap);
294
295 return result;
296}
297
298BLResult blRuntimeMessageVFmt(const char* fmt, va_list ap) noexcept {
299 char buf[1024];
300 vsnprintf(buf, BL_ARRAY_SIZE(buf), fmt, ap);
301 return blRuntimeMessageOut(buf);
302}
303
304// ============================================================================
305// [BLRuntime - GetCpuTicks]
306// ============================================================================
307
308uint32_t blRuntimeGetTickCount(void) noexcept {
309#ifndef BL_BUILD_NO_JIT
310 return asmjit::OSUtils::getTickCount();
311#else
312 return 0;
313#endif
314}
315
316// ============================================================================
317// [BLRuntime - Failure]
318// ============================================================================
319
320void blRuntimeFailure(const char* fmt, ...) noexcept {
321 va_list ap;
322 va_start(ap, fmt);
323 blRuntimeMessageVFmt(fmt, ap);
324 va_end(ap);
325
326 abort();
327}
328
329void blRuntimeAssertionFailure(const char* file, int line, const char* msg) noexcept {
330 blRuntimeMessageFmt("[Blend2D] ASSERTION FAILURE: '%s' at '%s' [line %d]\n", msg, file, line);
331 abort();
332}
333
334// ============================================================================
335// [BLRuntime - Alloc / Free]
336// ============================================================================
337
338// We use 'malloc/free' implementation at the moment.
339
340void* blRuntimeAllocImpl(size_t implSize, uint16_t* memPoolDataOut) noexcept {
341 *memPoolDataOut = 0;
342 return malloc(implSize);
343}
344
345BLResult blRuntimeFreeImpl(void* impl_, size_t implSize, uint32_t memPoolData) noexcept {
346 BL_UNUSED(implSize);
347 BL_UNUSED(memPoolData);
348
349 free(impl_);
350 return BL_SUCCESS;
351}
352
353void BL_CDECL blRuntimeDummyDestroyImplFunc(void* impl, void* destroyData) noexcept {
354 BL_UNUSED(impl);
355 BL_UNUSED(destroyData);
356}
357
358// ============================================================================
359// [BLRuntime - ResultFrom{Win|Posix}Error]
360// ============================================================================
361
362#ifdef _WIN32
363
364// Fix possible problems with MinGW not defining these.
365#ifndef ERROR_DISK_QUOTA_EXCEEDED
366 #define ERROR_DISK_QUOTA_EXCEEDED 0x0000050F
367#endif
368
369BLResult blResultFromWinError(uint32_t e) noexcept {
370 switch (e) {
371 case ERROR_SUCCESS : return BL_SUCCESS; // 0x00000000
372 case ERROR_INVALID_FUNCTION : return BL_ERROR_NOT_PERMITTED; // 0x00000001
373 case ERROR_FILE_NOT_FOUND : return BL_ERROR_NO_ENTRY; // 0x00000002
374 case ERROR_PATH_NOT_FOUND : return BL_ERROR_NO_ENTRY; // 0x00000003
375 case ERROR_TOO_MANY_OPEN_FILES : return BL_ERROR_TOO_MANY_OPEN_FILES; // 0x00000004
376 case ERROR_ACCESS_DENIED : return BL_ERROR_ACCESS_DENIED; // 0x00000005
377 case ERROR_INVALID_HANDLE : return BL_ERROR_INVALID_HANDLE; // 0x00000006
378 case ERROR_NOT_ENOUGH_MEMORY : return BL_ERROR_OUT_OF_MEMORY; // 0x00000008
379 case ERROR_OUTOFMEMORY : return BL_ERROR_OUT_OF_MEMORY; // 0x0000000E
380 case ERROR_INVALID_DRIVE : return BL_ERROR_NO_ENTRY; // 0x0000000F
381 case ERROR_CURRENT_DIRECTORY : return BL_ERROR_NOT_PERMITTED; // 0x00000010
382 case ERROR_NOT_SAME_DEVICE : return BL_ERROR_NOT_SAME_DEVICE; // 0x00000011
383 case ERROR_NO_MORE_FILES : return BL_ERROR_NO_MORE_FILES; // 0x00000012
384 case ERROR_WRITE_PROTECT : return BL_ERROR_READ_ONLY_FS; // 0x00000013
385 case ERROR_NOT_READY : return BL_ERROR_NO_MEDIA; // 0x00000015
386 case ERROR_CRC : return BL_ERROR_IO; // 0x00000017
387 case ERROR_SEEK : return BL_ERROR_INVALID_SEEK; // 0x00000019
388 case ERROR_WRITE_FAULT : return BL_ERROR_IO; // 0x0000001D
389 case ERROR_READ_FAULT : return BL_ERROR_IO; // 0x0000001E
390 case ERROR_GEN_FAILURE : return BL_ERROR_IO; // 0x0000001F
391 case ERROR_SHARING_BUFFER_EXCEEDED: return BL_ERROR_TOO_MANY_OPEN_FILES; // 0x00000024
392 case ERROR_HANDLE_EOF : return BL_ERROR_NO_MORE_DATA; // 0x00000026
393 case ERROR_HANDLE_DISK_FULL : return BL_ERROR_NO_SPACE_LEFT; // 0x00000027
394 case ERROR_NOT_SUPPORTED : return BL_ERROR_NOT_IMPLEMENTED; // 0x00000032
395 case ERROR_FILE_EXISTS : return BL_ERROR_ALREADY_EXISTS; // 0x00000050
396 case ERROR_CANNOT_MAKE : return BL_ERROR_NOT_PERMITTED; // 0x00000052
397 case ERROR_INVALID_PARAMETER : return BL_ERROR_INVALID_VALUE; // 0x00000057
398 case ERROR_NET_WRITE_FAULT : return BL_ERROR_IO; // 0x00000058
399 case ERROR_DRIVE_LOCKED : return BL_ERROR_BUSY; // 0x0000006C
400 case ERROR_BROKEN_PIPE : return BL_ERROR_BROKEN_PIPE; // 0x0000006D
401 case ERROR_OPEN_FAILED : return BL_ERROR_OPEN_FAILED; // 0x0000006E
402 case ERROR_BUFFER_OVERFLOW : return BL_ERROR_FILE_NAME_TOO_LONG; // 0x0000006F
403 case ERROR_DISK_FULL : return BL_ERROR_NO_SPACE_LEFT; // 0x00000070
404 case ERROR_CALL_NOT_IMPLEMENTED : return BL_ERROR_NOT_IMPLEMENTED; // 0x00000078
405 case ERROR_INVALID_NAME : return BL_ERROR_INVALID_FILE_NAME; // 0x0000007B
406 case ERROR_NEGATIVE_SEEK : return BL_ERROR_INVALID_SEEK; // 0x00000083
407 case ERROR_SEEK_ON_DEVICE : return BL_ERROR_INVALID_SEEK; // 0x00000084
408 case ERROR_BUSY_DRIVE : return BL_ERROR_BUSY; // 0x0000008E
409 case ERROR_DIR_NOT_ROOT : return BL_ERROR_NOT_ROOT_DEVICE; // 0x00000090
410 case ERROR_DIR_NOT_EMPTY : return BL_ERROR_NOT_EMPTY; // 0x00000091
411 case ERROR_PATH_BUSY : return BL_ERROR_BUSY; // 0x00000094
412 case ERROR_TOO_MANY_TCBS : return BL_ERROR_TOO_MANY_THREADS; // 0x0000009B
413 case ERROR_BAD_ARGUMENTS : return BL_ERROR_INVALID_VALUE; // 0x000000A0
414 case ERROR_BAD_PATHNAME : return BL_ERROR_INVALID_FILE_NAME; // 0x000000A1
415 case ERROR_SIGNAL_PENDING : return BL_ERROR_BUSY; // 0x000000A2
416 case ERROR_MAX_THRDS_REACHED : return BL_ERROR_TOO_MANY_THREADS; // 0x000000A4
417 case ERROR_BUSY : return BL_ERROR_BUSY; // 0x000000AA
418 case ERROR_ALREADY_EXISTS : return BL_ERROR_ALREADY_EXISTS; // 0x000000B7
419 case ERROR_BAD_PIPE : return BL_ERROR_BROKEN_PIPE; // 0x000000E6
420 case ERROR_PIPE_BUSY : return BL_ERROR_BUSY; // 0x000000E7
421 case ERROR_NO_MORE_ITEMS : return BL_ERROR_NO_MORE_FILES; // 0x00000103
422 case ERROR_FILE_INVALID : return BL_ERROR_NO_ENTRY; // 0x000003EE
423 case ERROR_NO_DATA_DETECTED : return BL_ERROR_IO; // 0x00000450
424 case ERROR_MEDIA_CHANGED : return BL_ERROR_MEDIA_CHANGED; // 0x00000456
425 case ERROR_IO_DEVICE : return BL_ERROR_NO_DEVICE; // 0x0000045D
426 case ERROR_NO_MEDIA_IN_DRIVE : return BL_ERROR_NO_MEDIA; // 0x00000458
427 case ERROR_DISK_OPERATION_FAILED : return BL_ERROR_IO; // 0x00000467
428 case ERROR_TOO_MANY_LINKS : return BL_ERROR_TOO_MANY_LINKS; // 0x00000476
429 case ERROR_DISK_QUOTA_EXCEEDED : return BL_ERROR_NO_SPACE_LEFT; // 0x0000050F
430 case ERROR_INVALID_USER_BUFFER : return BL_ERROR_BUSY; // 0x000006F8
431 case ERROR_UNRECOGNIZED_MEDIA : return BL_ERROR_IO; // 0x000006F9
432 case ERROR_NOT_ENOUGH_QUOTA : return BL_ERROR_OUT_OF_MEMORY; // 0x00000718
433 case ERROR_CANT_ACCESS_FILE : return BL_ERROR_NOT_PERMITTED; // 0x00000780
434 case ERROR_CANT_RESOLVE_FILENAME : return BL_ERROR_NO_ENTRY; // 0x00000781
435 case ERROR_OPEN_FILES : return BL_ERROR_TRY_AGAIN; // 0x00000961
436 }
437
438 // Pass the system error if it's below our error indexing.
439 if (e < BL_ERROR_START_INDEX)
440 return e;
441
442 // Otherwise this is an unmapped system error code.
443 return BL_ERROR_UNKNOWN_SYSTEM_ERROR;
444}
445
446#else
447
448BLResult blResultFromPosixError(int e) noexcept {
449 #define MAP(C_ERROR, BL_ERROR) case C_ERROR: return BL_ERROR
450
451 switch (e) {
452 #ifdef EACCES
453 MAP(EACCES, BL_ERROR_ACCESS_DENIED);
454 #endif
455 #ifdef EAGAIN
456 MAP(EAGAIN, BL_ERROR_TRY_AGAIN);
457 #endif
458 #ifdef EBADF
459 MAP(EBADF, BL_ERROR_INVALID_HANDLE);
460 #endif
461 #ifdef EBUSY
462 MAP(EBUSY, BL_ERROR_BUSY);
463 #endif
464 #ifdef EDQUOT
465 MAP(EDQUOT, BL_ERROR_NO_SPACE_LEFT);
466 #endif
467 #ifdef EEXIST
468 MAP(EEXIST, BL_ERROR_ALREADY_EXISTS);
469 #endif
470 #ifdef EFAULT
471 MAP(EFAULT, BL_ERROR_INVALID_STATE);
472 #endif
473 #ifdef EFBIG
474 MAP(EFBIG, BL_ERROR_FILE_TOO_LARGE);
475 #endif
476 #ifdef EINTR
477 MAP(EINTR, BL_ERROR_INTERRUPTED);
478 #endif
479 #ifdef EINVAL
480 MAP(EINVAL, BL_ERROR_INVALID_VALUE);
481 #endif
482 #ifdef EIO
483 MAP(EIO, BL_ERROR_IO);
484 #endif
485 #ifdef EISDIR
486 MAP(EISDIR, BL_ERROR_NOT_FILE);
487 #endif
488 #ifdef ELOOP
489 MAP(ELOOP, BL_ERROR_SYMLINK_LOOP);
490 #endif
491 #ifdef EMFILE
492 MAP(EMFILE, BL_ERROR_TOO_MANY_OPEN_FILES);
493 #endif
494 #ifdef ENAMETOOLONG
495 MAP(ENAMETOOLONG, BL_ERROR_FILE_NAME_TOO_LONG);
496 #endif
497 #ifdef ENFILE
498 MAP(ENFILE, BL_ERROR_TOO_MANY_OPEN_FILES_BY_OS);
499 #endif
500 #ifdef ENMFILE
501 MAP(ENMFILE, BL_ERROR_NO_MORE_FILES);
502 #endif
503 #ifdef ENODATA
504 MAP(ENODATA, BL_ERROR_NO_MORE_DATA);
505 #endif
506 #ifdef ENODEV
507 MAP(ENODEV, BL_ERROR_NO_DEVICE);
508 #endif
509 #ifdef ENOENT
510 MAP(ENOENT, BL_ERROR_NO_ENTRY);
511 #endif
512 #ifdef ENOMEDIUM
513 MAP(ENOMEDIUM, BL_ERROR_NO_MEDIA);
514 #endif
515 #ifdef ENOMEM
516 MAP(ENOMEM, BL_ERROR_OUT_OF_MEMORY);
517 #endif
518 #ifdef ENOSPC
519 MAP(ENOSPC, BL_ERROR_NO_SPACE_LEFT);
520 #endif
521 #ifdef ENOSYS
522 MAP(ENOSYS, BL_ERROR_NOT_IMPLEMENTED);
523 #endif
524 #ifdef ENOTBLK
525 MAP(ENOTBLK, BL_ERROR_NOT_BLOCK_DEVICE);
526 #endif
527 #ifdef ENOTDIR
528 MAP(ENOTDIR, BL_ERROR_NOT_DIRECTORY);
529 #endif
530 #ifdef ENOTEMPTY
531 MAP(ENOTEMPTY, BL_ERROR_NOT_EMPTY);
532 #endif
533 #ifdef ENXIO
534 MAP(ENXIO, BL_ERROR_NO_DEVICE);
535 #endif
536 #ifdef EOVERFLOW
537 MAP(EOVERFLOW, BL_ERROR_VALUE_TOO_LARGE);
538 #endif
539 #ifdef EPERM
540 MAP(EPERM, BL_ERROR_NOT_PERMITTED);
541 #endif
542 #ifdef EROFS
543 MAP(EROFS, BL_ERROR_READ_ONLY_FS);
544 #endif
545 #ifdef ESPIPE
546 MAP(ESPIPE, BL_ERROR_INVALID_SEEK);
547 #endif
548 #ifdef ETIMEDOUT
549 MAP(ETIMEDOUT, BL_ERROR_TIMED_OUT);
550 #endif
551 #ifdef EXDEV
552 MAP(EXDEV, BL_ERROR_NOT_SAME_DEVICE);
553 #endif
554 }
555
556 #undef MAP
557
558 // Pass the system error if it's below our error indexing.
559 if (e != 0 && unsigned(e) < BL_ERROR_START_INDEX)
560 return uint32_t(unsigned(e));
561 else
562 return BL_ERROR_UNKNOWN_SYSTEM_ERROR;
563}
564#endif
565