Report fatal error and abort if any cpuinfo_get_* function is called before initialization
diff --git a/src/api.c b/src/api.c
index 1ffdb8c..0504a63 100644
--- a/src/api.c
+++ b/src/api.c
@@ -2,8 +2,11 @@
 
 #include <cpuinfo.h>
 #include <api.h>
+#include <log.h>
 
 
+bool cpuinfo_is_initialized = false;
+
 struct cpuinfo_processor* cpuinfo_processors = NULL;
 struct cpuinfo_core* cpuinfo_cores = NULL;
 struct cpuinfo_cluster* cpuinfo_clusters = NULL;
@@ -18,22 +21,37 @@
 
 
 const struct cpuinfo_processor* cpuinfo_get_processors(void) {
+	if (!cpuinfo_is_initialized) {
+		cpuinfo_log_fatal("cpuinfo_get_%s called before cpuinfo is initialized", "processors");
+	}
 	return cpuinfo_processors;
 }
 
 const struct cpuinfo_core* cpuinfo_get_cores(void) {
+	if (!cpuinfo_is_initialized) {
+		cpuinfo_log_fatal("cpuinfo_get_%s called before cpuinfo is initialized", "core");
+	}
 	return cpuinfo_cores;
 }
 
 const struct cpuinfo_cluster* cpuinfo_get_clusters(void) {
+	if (!cpuinfo_is_initialized) {
+		cpuinfo_log_fatal("cpuinfo_get_%s called before cpuinfo is initialized", "clusters");
+	}
 	return cpuinfo_clusters;
 }
 
 const struct cpuinfo_package* cpuinfo_get_packages(void) {
+	if (!cpuinfo_is_initialized) {
+		cpuinfo_log_fatal("cpuinfo_get_%s called before cpuinfo is initialized", "packages");
+	}
 	return cpuinfo_packages;
 }
 
 const struct cpuinfo_processor* cpuinfo_get_processor(uint32_t index) {
+	if (!cpuinfo_is_initialized) {
+		cpuinfo_log_fatal("cpuinfo_get_%s called before cpuinfo is initialized", "processor");
+	}
 	if (index < cpuinfo_processors_count) {
 		return cpuinfo_processors + index;
 	} else {
@@ -42,6 +60,9 @@
 }
 
 const struct cpuinfo_core* cpuinfo_get_core(uint32_t index) {
+	if (!cpuinfo_is_initialized) {
+		cpuinfo_log_fatal("cpuinfo_get_%s called before cpuinfo is initialized", "core");
+	}
 	if (index < cpuinfo_cores_count) {
 		return cpuinfo_cores + index;
 	} else {
@@ -50,6 +71,9 @@
 }
 
 const struct cpuinfo_cluster* cpuinfo_get_cluster(uint32_t index) {
+	if (!cpuinfo_is_initialized) {
+		cpuinfo_log_fatal("cpuinfo_get_%s called before cpuinfo is initialized", "cluster");
+	}
 	if (index < cpuinfo_clusters_count) {
 		return cpuinfo_clusters + index;
 	} else {
@@ -58,6 +82,9 @@
 }
 
 const struct cpuinfo_package* cpuinfo_get_package(uint32_t index) {
+	if (!cpuinfo_is_initialized) {
+		cpuinfo_log_fatal("cpuinfo_get_%s called before cpuinfo is initialized", "package");
+	}
 	if (index < cpuinfo_packages_count) {
 		return cpuinfo_packages + index;
 	} else {
@@ -66,42 +93,72 @@
 }
 
 uint32_t cpuinfo_get_processors_count(void) {
+	if (!cpuinfo_is_initialized) {
+		cpuinfo_log_fatal("cpuinfo_get_%s called before cpuinfo is initialized", "processors_count");
+	}
 	return cpuinfo_processors_count;
 }
 
 uint32_t cpuinfo_get_cores_count(void) {
+	if (!cpuinfo_is_initialized) {
+		cpuinfo_log_fatal("cpuinfo_get_%s called before cpuinfo is initialized", "cores_count");
+	}
 	return cpuinfo_cores_count;
 }
 
 uint32_t cpuinfo_get_clusters_count(void) {
+	if (!cpuinfo_is_initialized) {
+		cpuinfo_log_fatal("cpuinfo_get_%s called before cpuinfo is initialized", "clusters_count");
+	}
 	return cpuinfo_clusters_count;
 }
 
 uint32_t cpuinfo_get_packages_count(void) {
+	if (!cpuinfo_is_initialized) {
+		cpuinfo_log_fatal("cpuinfo_get_%s called before cpuinfo is initialized", "packages_count");
+	}
 	return cpuinfo_packages_count;
 }
 
 const struct cpuinfo_cache* CPUINFO_ABI cpuinfo_get_l1i_caches(void) {
+	if (!cpuinfo_is_initialized) {
+		cpuinfo_log_fatal("cpuinfo_get_%s called before cpuinfo is initialized", "l1i_caches");
+	}
 	return cpuinfo_cache[cpuinfo_cache_level_1i];
 }
 
 const struct cpuinfo_cache* CPUINFO_ABI cpuinfo_get_l1d_caches(void) {
+	if (!cpuinfo_is_initialized) {
+		cpuinfo_log_fatal("cpuinfo_get_%s called before cpuinfo is initialized", "l1d_caches");
+	}
 	return cpuinfo_cache[cpuinfo_cache_level_1d];
 }
 
 const struct cpuinfo_cache* CPUINFO_ABI cpuinfo_get_l2_caches(void) {
+	if (!cpuinfo_is_initialized) {
+		cpuinfo_log_fatal("cpuinfo_get_%s called before cpuinfo is initialized", "l2_caches");
+	}
 	return cpuinfo_cache[cpuinfo_cache_level_2];
 }
 
 const struct cpuinfo_cache* CPUINFO_ABI cpuinfo_get_l3_caches(void) {
+	if (!cpuinfo_is_initialized) {
+		cpuinfo_log_fatal("cpuinfo_get_%s called before cpuinfo is initialized", "l3_caches");
+	}
 	return cpuinfo_cache[cpuinfo_cache_level_3];
 }
 
 const struct cpuinfo_cache* CPUINFO_ABI cpuinfo_get_l4_caches(void) {
+	if (!cpuinfo_is_initialized) {
+		cpuinfo_log_fatal("cpuinfo_get_%s called before cpuinfo is initialized", "l4_caches");
+	}
 	return cpuinfo_cache[cpuinfo_cache_level_4];
 }
 
 const struct cpuinfo_cache* CPUINFO_ABI cpuinfo_get_l1i_cache(uint32_t index) {
+	if (!cpuinfo_is_initialized) {
+		cpuinfo_log_fatal("cpuinfo_get_%s called before cpuinfo is initialized", "l1i_cache");
+	}
 	if (index < cpuinfo_cache_count[cpuinfo_cache_level_1i]) {
 		return cpuinfo_cache[cpuinfo_cache_level_1i] + index;
 	} else {
@@ -110,6 +167,9 @@
 }
 
 const struct cpuinfo_cache* CPUINFO_ABI cpuinfo_get_l1d_cache(uint32_t index) {
+	if (!cpuinfo_is_initialized) {
+		cpuinfo_log_fatal("cpuinfo_get_%s called before cpuinfo is initialized", "l1d_cache");
+	}
 	if (index < cpuinfo_cache_count[cpuinfo_cache_level_1d]) {
 		return cpuinfo_cache[cpuinfo_cache_level_1d] + index;
 	} else {
@@ -118,6 +178,9 @@
 }
 
 const struct cpuinfo_cache* CPUINFO_ABI cpuinfo_get_l2_cache(uint32_t index) {
+	if (!cpuinfo_is_initialized) {
+		cpuinfo_log_fatal("cpuinfo_get_%s called before cpuinfo is initialized", "l2_cache");
+	}
 	if (index < cpuinfo_cache_count[cpuinfo_cache_level_2]) {
 		return cpuinfo_cache[cpuinfo_cache_level_2] + index;
 	} else {
@@ -126,6 +189,9 @@
 }
 
 const struct cpuinfo_cache* CPUINFO_ABI cpuinfo_get_l3_cache(uint32_t index) {
+	if (!cpuinfo_is_initialized) {
+		cpuinfo_log_fatal("cpuinfo_get_%s called before cpuinfo is initialized", "l3_cache");
+	}
 	if (index < cpuinfo_cache_count[cpuinfo_cache_level_3]) {
 		return cpuinfo_cache[cpuinfo_cache_level_3] + index;
 	} else {
@@ -134,6 +200,9 @@
 }
 
 const struct cpuinfo_cache* CPUINFO_ABI cpuinfo_get_l4_cache(uint32_t index) {
+	if (!cpuinfo_is_initialized) {
+		cpuinfo_log_fatal("cpuinfo_get_%s called before cpuinfo is initialized", "l4_cache");
+	}
 	if (index < cpuinfo_cache_count[cpuinfo_cache_level_4]) {
 		return cpuinfo_cache[cpuinfo_cache_level_4] + index;
 	} else {
@@ -142,21 +211,36 @@
 }
 
 uint32_t CPUINFO_ABI cpuinfo_get_l1i_caches_count(void) {
+	if (!cpuinfo_is_initialized) {
+		cpuinfo_log_fatal("cpuinfo_get_%s called before cpuinfo is initialized", "l1i_caches_count");
+	}
 	return cpuinfo_cache_count[cpuinfo_cache_level_1i];
 }
 
 uint32_t CPUINFO_ABI cpuinfo_get_l1d_caches_count(void) {
+	if (!cpuinfo_is_initialized) {
+		cpuinfo_log_fatal("cpuinfo_get_%s called before cpuinfo is initialized", "l1d_caches_count");
+	}
 	return cpuinfo_cache_count[cpuinfo_cache_level_1d];
 }
 
 uint32_t CPUINFO_ABI cpuinfo_get_l2_caches_count(void) {
+	if (!cpuinfo_is_initialized) {
+		cpuinfo_log_fatal("cpuinfo_get_%s called before cpuinfo is initialized", "l2_caches_count");
+	}
 	return cpuinfo_cache_count[cpuinfo_cache_level_2];
 }
 
 uint32_t CPUINFO_ABI cpuinfo_get_l3_caches_count(void) {
+	if (!cpuinfo_is_initialized) {
+		cpuinfo_log_fatal("cpuinfo_get_%s called before cpuinfo is initialized", "l3_caches_count");
+	}
 	return cpuinfo_cache_count[cpuinfo_cache_level_3];
 }
 
 uint32_t CPUINFO_ABI cpuinfo_get_l4_caches_count(void) {
+	if (!cpuinfo_is_initialized) {
+		cpuinfo_log_fatal("cpuinfo_get_%s called before cpuinfo is initialized", "l4_caches_count");
+	}
 	return cpuinfo_cache_count[cpuinfo_cache_level_4];
 }
diff --git a/src/api.h b/src/api.h
index 9ba406f..14463e0 100644
--- a/src/api.h
+++ b/src/api.h
@@ -18,6 +18,7 @@
 	cpuinfo_cache_level_max = 5,
 };
 
+extern bool cpuinfo_is_initialized;
 extern struct cpuinfo_processor* cpuinfo_processors;
 extern struct cpuinfo_core* cpuinfo_cores;
 extern struct cpuinfo_cluster* cpuinfo_clusters;
diff --git a/src/arm/linux/init.c b/src/arm/linux/init.c
index 197b48f..dd54668 100644
--- a/src/arm/linux/init.c
+++ b/src/arm/linux/init.c
@@ -557,6 +557,10 @@
 	cpuinfo_cache_count[cpuinfo_cache_level_1d] = usable_processors;
 	cpuinfo_cache_count[cpuinfo_cache_level_2]  = l2_count;
 
+	__sync_synchronize();
+
+	cpuinfo_is_initialized = true;
+
 	linux_cpu_to_processor_map = NULL;
 	linux_cpu_to_core_map = NULL;
 	processors = NULL;
diff --git a/src/arm/mach/init.c b/src/arm/mach/init.c
index 2d8feeb..d8e0ab6 100644
--- a/src/arm/mach/init.c
+++ b/src/arm/mach/init.c
@@ -483,6 +483,10 @@
 	cpuinfo_cores_count = mach_topology.cores;
 	cpuinfo_packages_count = mach_topology.packages;
 
+	__sync_synchronize();
+
+	cpuinfo_is_initialized = true;
+
 	processors = NULL;
 	cores = NULL;
 	packages = NULL;
diff --git a/src/init.c b/src/init.c
index 45cffdc..2a30fcf 100644
--- a/src/init.c
+++ b/src/init.c
@@ -41,7 +41,7 @@
 #else
 	cpuinfo_log_error("processor architecture is not supported in cpuinfo");
 #endif
-	return (cpuinfo_processors != NULL) && (cpuinfo_cores != NULL) && (cpuinfo_packages != NULL);
+	return cpuinfo_is_initialized;
 }
 
 void CPUINFO_ABI cpuinfo_deinitialize(void) {
diff --git a/src/linux/current.c b/src/linux/current.c
index d4a7f69..9d48b92 100644
--- a/src/linux/current.c
+++ b/src/linux/current.c
@@ -9,14 +9,18 @@
 
 #include <cpuinfo.h>
 #include <api.h>
+#include <log.h>
 #include <linux/api.h>
 
 
-const struct cpuinfo_processor** cpuinfo_linux_cpu_to_processor_map;
-const struct cpuinfo_core** cpuinfo_linux_cpu_to_core_map;
+const struct cpuinfo_processor** cpuinfo_linux_cpu_to_processor_map = NULL;
+const struct cpuinfo_core** cpuinfo_linux_cpu_to_core_map = NULL;
 
 
 const struct cpuinfo_processor* CPUINFO_ABI cpuinfo_get_current_processor(void) {
+	if (!cpuinfo_is_initialized) {
+		cpuinfo_log_fatal("cpuinfo_get_%s called before cpuinfo is initialized", "current_processor");
+	}
 	const int cpu = sched_getcpu();
 	if (cpu >= 0) {
 		return cpuinfo_linux_cpu_to_processor_map[cpu];
@@ -26,6 +30,9 @@
 }
 
 const struct cpuinfo_core* CPUINFO_ABI cpuinfo_get_current_core(void) {
+	if (!cpuinfo_is_initialized) {
+		cpuinfo_log_fatal("cpuinfo_get_%s called before cpuinfo is initialized", "current_core");
+	}
 	const int cpu = sched_getcpu();
 	if (cpu >= 0) {
 		return cpuinfo_linux_cpu_to_core_map[cpu];
diff --git a/src/log.c b/src/log.c
index 65fac8c..396d58c 100644
--- a/src/log.c
+++ b/src/log.c
@@ -1,17 +1,53 @@
 #include <stdarg.h>
+#include <stdlib.h>
 #include <stdio.h>
 #ifndef _WIN32
 	#include <unistd.h>
 #endif
+#ifdef __ANDROID__
+	#include <android/log.h>
+	#define CPUINFO_LOG_TAG "cpuinfo"
+#endif
 
 #include <log.h>
 
+#ifndef CPUINFO_LOG_TO_STDIO
+	#ifdef __ANDROID__
+		#define CPUINFO_LOG_TO_STDIO 0
+	#else
+		#define CPUINFO_LOG_TO_STDIO 1
+	#endif
+#endif
+
+void cpuinfo_log_fatal(const char* format, ...) {
+	va_list args;
+	va_start(args, format);
+
+	#if defined(__ANDROID__) && !CPUINFO_LOG_TO_STDIO
+		__android_log_vprint(ANDROID_LOG_FATAL, CPUINFO_LOG_TAG, format, args);
+	#elif defined(__ANDROID__) || defined(_WIN32)
+		fprintf(stderr, "Fatal error: ");
+		vfprintf(stderr, format, args);
+		fprintf(stderr, "\n");
+		fflush(stderr);
+	#else
+		dprintf(STDERR_FILENO, "Error: ");
+		vdprintf(STDERR_FILENO, format, args);
+		dprintf(STDERR_FILENO, "\n");
+	#endif
+
+	va_end(args);
+	abort();
+}
+
 #if CPUINFO_LOG_LEVEL >= CPUINFO_LOG_ERROR
 	void cpuinfo_log_error(const char* format, ...) {
 		va_list args;
 		va_start(args, format);
 
-		#if defined(__ANDROID__) || defined(_WIN32)
+		#if defined(__ANDROID__) && !CPUINFO_LOG_TO_STDIO
+			__android_log_vprint(ANDROID_LOG_ERROR, CPUINFO_LOG_TAG, format, args);
+		#elif defined(__ANDROID__) || defined(_WIN32)
 			fprintf(stderr, "Error: ");
 			vfprintf(stderr, format, args);
 			fprintf(stderr, "\n");
@@ -31,7 +67,9 @@
 		va_list args;
 		va_start(args, format);
 
-		#if defined(__ANDROID__) || defined(_WIN32)
+		#if defined(__ANDROID__) && !CPUINFO_LOG_TO_STDIO
+			__android_log_vprint(ANDROID_LOG_WARN, CPUINFO_LOG_TAG, format, args);
+		#elif defined(__ANDROID__) || defined(_WIN32)
 			fprintf(stderr, "Warning: ");
 			vfprintf(stderr, format, args);
 			fprintf(stderr, "\n");
@@ -51,7 +89,9 @@
 		va_list args;
 		va_start(args, format);
 
-		#if defined(__ANDROID__) || defined(_WIN32)
+		#if defined(__ANDROID__) && !CPUINFO_LOG_TO_STDIO
+			__android_log_vprint(ANDROID_LOG_INFO, CPUINFO_LOG_TAG, format, args);
+		#elif defined(__ANDROID__) || defined(_WIN32)
 			printf("Note: ");
 			vprintf(format, args);
 			printf("\n");
@@ -70,7 +110,9 @@
 		va_list args;
 		va_start(args, format);
 
-		#if defined(__ANDROID__) || defined(_WIN32)
+		#if defined(__ANDROID__) && !CPUINFO_LOG_TO_STDIO
+			__android_log_vprint(ANDROID_LOG_DEBUG, CPUINFO_LOG_TAG, format, args);
+		#elif defined(__ANDROID__) || defined(_WIN32)
 			printf("Debug: ");
 			vprintf(format, args);
 			printf("\n");
diff --git a/src/log.h b/src/log.h
index ccfbd03..69e4b8f 100644
--- a/src/log.h
+++ b/src/log.h
@@ -48,3 +48,10 @@
 #else
 	static inline void cpuinfo_log_error(const char* format, ...) { }
 #endif
+
+#if defined(__GNUC__)
+__attribute__((__format__(__printf__, 1, 2), __noreturn__))
+#elif defined(_MSC_VER)
+__declspec(noreturn)
+#endif
+void cpuinfo_log_fatal(const char* format, ...);
diff --git a/src/x86/linux/init.c b/src/x86/linux/init.c
index 400fb9c..fadd99c 100644
--- a/src/x86/linux/init.c
+++ b/src/x86/linux/init.c
@@ -534,6 +534,10 @@
 	cpuinfo_cache_count[cpuinfo_cache_level_3]  = l3_count;
 	cpuinfo_cache_count[cpuinfo_cache_level_4]  = l4_count;
 
+	__sync_synchronize();
+
+	cpuinfo_is_initialized = true;
+
 	linux_cpu_to_processor_map = NULL;
 	linux_cpu_to_core_map = NULL;
 	processors = NULL;
diff --git a/src/x86/mach/init.c b/src/x86/mach/init.c
index dc04663..a5371a5 100644
--- a/src/x86/mach/init.c
+++ b/src/x86/mach/init.c
@@ -327,6 +327,10 @@
 	cpuinfo_clusters_count = mach_topology.packages;
 	cpuinfo_packages_count = mach_topology.packages;
 
+	__sync_synchronize();
+
+	cpuinfo_is_initialized = true;
+
 	processors = NULL;
 	cores = NULL;
 	clusters = NULL;
diff --git a/src/x86/windows/init.c b/src/x86/windows/init.c
index 8866eee..d65aa6c 100644
--- a/src/x86/windows/init.c
+++ b/src/x86/windows/init.c
@@ -571,6 +571,10 @@
 	cpuinfo_clusters_count = packages_count;
 	cpuinfo_packages_count = packages_count;
 
+	MemoryBarrier();
+
+	cpuinfo_is_initialized = true;
+
 	processors = NULL;
 	cores = NULL;
 	clusters = NULL;