/// <summary> /// Sets the thread exit callback. /// </summary> private static unsafe int SetThreadExitCallbackLibcoreclr(IntPtr callbackPtr) { int tlsIndex; CheckResult(NativeMethodsLinuxLibcoreclr.pthread_key_create(new IntPtr(&tlsIndex), callbackPtr)); return(tlsIndex); }
static UnmanagedThread() { NativeLibraryUtils.SetDllImportResolvers(); if (Os.IsWindows) { SetThreadExitCallbackDelegate = SetThreadExitCallbackWindows; RemoveThreadExitCallbackDelegate = RemoveThreadExitCallbackWindows; EnableCurrentThreadExitEventDelegate = EnableCurrentThreadExitEventWindows; } else if (Os.IsMacOs) { SetThreadExitCallbackDelegate = SetThreadExitCallbackMacOs; RemoveThreadExitCallbackDelegate = RemoveThreadExitCallbackMacOs; EnableCurrentThreadExitEventDelegate = EnableCurrentThreadExitEventMacOs; } else if (Os.IsLinux) { if (Os.IsMono) { SetThreadExitCallbackDelegate = SetThreadExitCallbackMono; RemoveThreadExitCallbackDelegate = RemoveThreadExitCallbackMono; EnableCurrentThreadExitEventDelegate = EnableCurrentThreadExitEventMono; } else { unsafe { // Depending on the Linux distro, use either libcoreclr or libpthread. try { int tlsIndex; CheckResult(NativeMethodsLinuxLibcoreclr.pthread_key_create(new IntPtr(&tlsIndex), IntPtr.Zero)); CheckResult(NativeMethodsLinuxLibcoreclr.pthread_key_delete(tlsIndex)); SetThreadExitCallbackDelegate = SetThreadExitCallbackLibcoreclr; RemoveThreadExitCallbackDelegate = RemoveThreadExitCallbackLibcoreclr; EnableCurrentThreadExitEventDelegate = EnableCurrentThreadExitEventLibcoreclr; } catch (EntryPointNotFoundException) { SetThreadExitCallbackDelegate = SetThreadExitCallbackLibpthread; RemoveThreadExitCallbackDelegate = RemoveThreadExitCallbackLibpthread; EnableCurrentThreadExitEventDelegate = EnableCurrentThreadExitEventLibpthread; } } } } else { throw new InvalidOperationException("Unsupported OS: " + Environment.OSVersion); } }
/// <summary> /// Loads specified DLL. /// </summary> /// <returns>Library handle and error message.</returns> public static KeyValuePair <IntPtr, string> Load(string dllPath) { if (Os.IsWindows) { var ptr = NativeMethodsWindows.LoadLibrary(dllPath); return(new KeyValuePair <IntPtr, string>(ptr, ptr == IntPtr.Zero ? FormatWin32Error(Marshal.GetLastWin32Error()) ?? "Unknown error" : null)); } if (Os.IsMacOs) { var ptr = NativeMethodsMacOs.dlopen(dllPath, RtldGlobal | RtldLazy); return(new KeyValuePair <IntPtr, string>(ptr, ptr == IntPtr.Zero ? GetErrorText(NativeMethodsMacOs.dlerror()) : null)); } if (Os.IsLinux) { if (Os.IsMono) { var ptr = NativeMethodsMono.dlopen(dllPath, RtldGlobal | RtldLazy); return(new KeyValuePair <IntPtr, string>(ptr, ptr == IntPtr.Zero ? GetErrorText(NativeMethodsMono.dlerror()) : null)); } // Depending on the Linux distro, dlopen is either present in libdl or in libcoreclr. try { var ptr = NativeMethodsLinuxLibcoreclr.dlopen(dllPath, RtldGlobal | RtldLazy); return(new KeyValuePair <IntPtr, string>(ptr, ptr == IntPtr.Zero ? GetErrorText(NativeMethodsLinuxLibcoreclr.dlerror()) : null)); } catch (EntryPointNotFoundException) { var ptr = NativeMethodsLinuxLibdl.dlopen(dllPath, RtldGlobal | RtldLazy); return(new KeyValuePair <IntPtr, string>(ptr, ptr == IntPtr.Zero ? GetErrorText(NativeMethodsLinuxLibdl.dlerror()) : null)); } } throw new InvalidOperationException("Unsupported OS: " + Environment.OSVersion); }
/// <summary> /// Enables thread exit event for current thread. /// </summary> private static void EnableCurrentThreadExitEventLibcoreclr(int callbackId, IntPtr threadLocalValue) { CheckResult(NativeMethodsLinuxLibcoreclr.pthread_setspecific(callbackId, threadLocalValue)); }
/// <summary> /// Removes thread exit callback that has been set with <see cref="SetThreadExitCallback"/>. /// </summary> private static void RemoveThreadExitCallbackLibcoreclr(int callbackId) { CheckResult(NativeMethodsLinuxLibcoreclr.pthread_key_delete(callbackId)); }