Added few more stubs so that control reaches to DestroyDevice().
[mesa.git] / src / util / u_thread.h
index e484d8aa74f3362a0fcfc88a2b084e320e292d71..af44bcfc1bd6c0ab97b9ca27e146e49a8c4966f8 100644 (file)
 #include <stdbool.h>
 
 #include "c11/threads.h"
+#include "detect_os.h"
 
 #ifdef HAVE_PTHREAD
 #include <signal.h>
+#ifdef HAVE_PTHREAD_NP_H
+#include <pthread_np.h>
+#endif
 #endif
 
+#ifdef __HAIKU__
+#include <OS.h>
+#endif
+
+#ifdef __FreeBSD__
+/* pthread_np.h -> sys/param.h -> machine/param.h
+ * - defines ALIGN which clashes with our ALIGN
+ */
+#undef ALIGN
+#define cpu_set_t cpuset_t
+#endif
 
 static inline thrd_t u_thread_create(int (*routine)(void *), void *param)
 {
@@ -45,7 +60,8 @@ static inline thrd_t u_thread_create(int (*routine)(void *), void *param)
    int ret;
 
    sigfillset(&new_set);
-   pthread_sigmask(SIG_SETMASK, &new_set, &saved_set);
+   sigdelset(&new_set, SIGSYS);
+   pthread_sigmask(SIG_BLOCK, &new_set, &saved_set);
    ret = thrd_create( &thread, routine, param );
    pthread_sigmask(SIG_SETMASK, &saved_set, NULL);
 #else
@@ -61,14 +77,80 @@ static inline thrd_t u_thread_create(int (*routine)(void *), void *param)
 static inline void u_thread_setname( const char *name )
 {
 #if defined(HAVE_PTHREAD)
-#  if defined(__GNU_LIBRARY__) && defined(__GLIBC__) && defined(__GLIBC_MINOR__) && \
-      (__GLIBC__ >= 3 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 12))
+#if DETECT_OS_LINUX || DETECT_OS_CYGWIN || DETECT_OS_SOLARIS
    pthread_setname_np(pthread_self(), name);
-#  endif
+#elif DETECT_OS_FREEBSD || DETECT_OS_OPENBSD
+   pthread_set_name_np(pthread_self(), name);
+#elif DETECT_OS_NETBSD
+   pthread_setname_np(pthread_self(), "%s", (void *)name);
+#elif DETECT_OS_APPLE
+   pthread_setname_np(name);
+#elif DETECT_OS_HAIKU
+   rename_thread(find_thread(NULL), name);
+#else
+#warning Not sure how to call pthread_setname_np
+#endif
 #endif
    (void)name;
 }
 
+/**
+ * An AMD Zen CPU consists of multiple modules where each module has its own L3
+ * cache. Inter-thread communication such as locks and atomics between modules
+ * is very expensive. It's desirable to pin a group of closely cooperating
+ * threads to one group of cores sharing L3.
+ *
+ * \param thread        thread
+ * \param L3_index      index of the L3 cache
+ * \param cores_per_L3  number of CPU cores shared by one L3
+ */
+static inline void
+util_pin_thread_to_L3(thrd_t thread, unsigned L3_index, unsigned cores_per_L3)
+{
+#if defined(HAVE_PTHREAD_SETAFFINITY)
+   cpu_set_t cpuset;
+
+   CPU_ZERO(&cpuset);
+   for (unsigned i = 0; i < cores_per_L3; i++)
+      CPU_SET(L3_index * cores_per_L3 + i, &cpuset);
+   pthread_setaffinity_np(thread, sizeof(cpuset), &cpuset);
+#endif
+}
+
+/**
+ * Return the index of L3 that the thread is pinned to. If the thread is
+ * pinned to multiple L3 caches, return -1.
+ *
+ * \param thread        thread
+ * \param cores_per_L3  number of CPU cores shared by one L3
+ */
+static inline int
+util_get_L3_for_pinned_thread(thrd_t thread, unsigned cores_per_L3)
+{
+#if defined(HAVE_PTHREAD_SETAFFINITY)
+   cpu_set_t cpuset;
+
+   if (pthread_getaffinity_np(thread, sizeof(cpuset), &cpuset) == 0) {
+      int L3_index = -1;
+
+      for (unsigned i = 0; i < CPU_SETSIZE; i++) {
+         if (CPU_ISSET(i, &cpuset)) {
+            int x = i / cores_per_L3;
+
+            if (L3_index != x) {
+               if (L3_index == -1)
+                  L3_index = x;
+               else
+                  return -1; /* multiple L3s are set */
+            }
+         }
+      }
+      return L3_index;
+   }
+#endif
+   return -1;
+}
+
 /*
  * Thread statistics.
  */
@@ -77,7 +159,7 @@ static inline void u_thread_setname( const char *name )
 static inline int64_t
 u_thread_get_time_nano(thrd_t thread)
 {
-#if defined(__linux__) && defined(HAVE_PTHREAD)
+#if defined(HAVE_PTHREAD) && !defined(__APPLE__) && !defined(__HAIKU__)
    struct timespec ts;
    clockid_t cid;
 
@@ -92,10 +174,7 @@ u_thread_get_time_nano(thrd_t thread)
 static inline bool u_thread_is_self(thrd_t thread)
 {
 #if defined(HAVE_PTHREAD)
-#  if defined(__GNU_LIBRARY__) && defined(__GLIBC__) && defined(__GLIBC_MINOR__) && \
-      (__GLIBC__ >= 3 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 12))
    return pthread_equal(pthread_self(), thread);
-#  endif
 #endif
    return false;
 }
@@ -104,7 +183,7 @@ static inline bool u_thread_is_self(thrd_t thread)
  * util_barrier
  */
 
-#if defined(HAVE_PTHREAD)
+#if defined(HAVE_PTHREAD) && !defined(__APPLE__)
 
 typedef pthread_barrier_t util_barrier;