Преглед на файлове

Switch to better initializer strategy

Nikias Bassen преди 4 месеца
родител
ревизия
1a0c83ccd1
променени са 2 файла, в които са добавени 42 реда и са изтрити 68 реда
  1. 0 2
      include/libirecovery.h
  2. 42 66
      src/libirecovery.c

+ 0 - 2
include/libirecovery.h

@@ -132,8 +132,6 @@ enum {
 /* library */
 IRECV_API void irecv_set_debug_level(int level);
 IRECV_API const char* irecv_strerror(irecv_error_t error);
-IRECV_API void irecv_init(void); /* deprecated: libirecovery has constructor now */
-IRECV_API void irecv_exit(void); /* deprecated: libirecovery has destructor now */
 
 IRECV_API const char* irecv_version();
 

+ 42 - 66
src/libirecovery.c

@@ -71,6 +71,33 @@
 
 #include "libirecovery.h"
 
+// Reference: https://stackoverflow.com/a/2390626/1806760
+// Initializer/finalizer sample for MSVC and GCC/Clang.
+// 2010-2016 Joe Lowe. Released into the public domain.
+
+#ifdef __cplusplus
+    #define INITIALIZER(f) \
+        static void f(void); \
+        struct f##_t_ { f##_t_(void) { f(); } }; static f##_t_ f##_; \
+        static void f(void)
+#elif defined(_MSC_VER)
+    #pragma section(".CRT$XCU",read)
+    #define INITIALIZER2_(f,p) \
+        static void f(void); \
+        __declspec(allocate(".CRT$XCU")) void (*f##_)(void) = f; \
+        __pragma(comment(linker,"/include:" p #f "_")) \
+        static void f(void)
+    #ifdef _WIN64
+        #define INITIALIZER(f) INITIALIZER2_(f,"")
+    #else
+        #define INITIALIZER(f) INITIALIZER2_(f,"_")
+    #endif
+#else
+    #define INITIALIZER(f) \
+        static void f(void) __attribute__((__constructor__)); \
+        static void f(void)
+#endif
+
 struct irecv_client_private {
 	int debug;
 	int usb_config;
@@ -603,24 +630,6 @@ static libusb_context* irecv_hotplug_ctx = NULL;
 #endif
 #endif
 
-static void _irecv_init(void)
-{
-	char* dbglvl = getenv("LIBIRECOVERY_DEBUG_LEVEL");
-	if (dbglvl) {
-		libirecovery_debug = strtol(dbglvl, NULL, 0);
-		irecv_set_debug_level(libirecovery_debug);
-	}
-#ifndef USE_DUMMY
-#ifndef _WIN32
-#ifndef HAVE_IOKIT
-	libusb_init(&libirecovery_context);
-#endif
-#endif
-	collection_init(&listeners);
-	mutex_init(&listener_mutex);
-#endif
-}
-
 static void _irecv_deinit(void)
 {
 #ifndef USE_DUMMY
@@ -637,43 +646,24 @@ static void _irecv_deinit(void)
 #endif
 }
 
-static thread_once_t init_once = THREAD_ONCE_INIT;
-static thread_once_t deinit_once = THREAD_ONCE_INIT;
-
-#ifndef HAVE_ATTRIBUTE_CONSTRUCTOR
-  #if defined(__llvm__) || defined(__GNUC__)
-    #define HAVE_ATTRIBUTE_CONSTRUCTOR
-  #endif
-#endif
-
-#ifdef HAVE_ATTRIBUTE_CONSTRUCTOR
-static void __attribute__((constructor)) libirecovery_initialize(void)
+INITIALIZER(_irecv_init)
 {
-	thread_once(&init_once, _irecv_init);
-}
-
-static void __attribute__((destructor)) libirecovery_deinitialize(void)
-{
-	thread_once(&deinit_once, _irecv_deinit);
-}
-#elif defined(_WIN32)
-BOOL WINAPI DllMain(HINSTANCE hModule, DWORD dwReason, LPVOID lpReserved)
-{
-	switch (dwReason) {
-	case DLL_PROCESS_ATTACH:
-		thread_once(&init_once, _irecv_init);
-		break;
-	case DLL_PROCESS_DETACH:
-		thread_once(&deinit_once, _irecv_deinit);
-		break;
-	default:
-		break;
+	char* dbglvl = getenv("LIBIRECOVERY_DEBUG_LEVEL");
+	if (dbglvl) {
+		libirecovery_debug = strtol(dbglvl, NULL, 0);
+		irecv_set_debug_level(libirecovery_debug);
 	}
-	return 1;
-}
-#else
-#warning No compiler support for constructor/destructor attributes, some features might not be available.
+#ifndef USE_DUMMY
+#ifndef _WIN32
+#ifndef HAVE_IOKIT
+	libusb_init(&libirecovery_context);
+#endif
 #endif
+	collection_init(&listeners);
+	mutex_init(&listener_mutex);
+#endif
+	atexit(_irecv_deinit);
+}
 
 #ifdef HAVE_IOKIT
 static int iokit_get_string_descriptor_ascii(irecv_client_t client, uint8_t desc_index, unsigned char * buffer, int size)
@@ -1334,20 +1324,6 @@ static int check_context(irecv_client_t client)
 }
 #endif
 
-void irecv_init(void)
-{
-#ifndef USE_DUMMY
-	thread_once(&init_once, _irecv_init);
-#endif
-}
-
-void irecv_exit(void)
-{
-#ifndef USE_DUMMY
-	thread_once(&deinit_once, _irecv_deinit);
-#endif
-}
-
 #ifndef USE_DUMMY
 #ifdef HAVE_IOKIT
 static int iokit_usb_control_transfer(irecv_client_t client, uint8_t bm_request_type, uint8_t b_request, uint16_t w_value, uint16_t w_index, unsigned char *data, uint16_t w_length, unsigned int timeout)