diff --git a/docs/reference/glib/glib-sections.txt b/docs/reference/glib/glib-sections.txt index e4e9df41e..c3f694a1f 100644 --- a/docs/reference/glib/glib-sections.txt +++ b/docs/reference/glib/glib-sections.txt @@ -650,6 +650,9 @@ g_pointer_bit_lock g_pointer_bit_trylock g_pointer_bit_unlock + +g_get_num_processors + G_LOCK_NAME atexit diff --git a/glib/glib.symbols b/glib/glib.symbols index 2ae79d926..d48b39d57 100644 --- a/glib/glib.symbols +++ b/glib/glib.symbols @@ -179,6 +179,7 @@ g_completion_new g_completion_remove_items g_completion_set_compare g_get_filename_charsets +g_get_num_processors g_convert g_convert_error_quark g_convert_with_fallback diff --git a/glib/gthread.c b/glib/gthread.c index d3a924ac0..c27bca688 100644 --- a/glib/gthread.c +++ b/glib/gthread.c @@ -1007,5 +1007,61 @@ g_thread_self (void) return (GThread*) thread; } +/** + * g_get_num_processors: + * + * Determine the approximate number of threads that the system will + * schedule simultaneously for this process. This is intended to be + * used as a parameter to g_thread_pool_new() for CPU bound tasks and + * similar cases. + * + * Returns: Number of schedulable threads, always greater than 0 + * + * Since: 2.36 + */ +guint +g_get_num_processors (void) +{ +#ifdef G_OS_WIN32 + DWORD_PTR process_cpus; + DWORD_PTR system_cpus; + + if (GetProcessAffinityMask (GetCurrentProcess (), + &process_cpus, &system_cpus)) + { + unsigned int count; + + for (count = 0; process_cpus != 0; process_cpus >>= 1) + if (process_cpus & 1) + count++; + + if (count > 0) + return count; + } +#elif defined(HAVE_UNISTD_H) && defined(_SC_NPROCESSORS_ONLN) + { + int count; + + count = sysconf (_SC_NPROCESSORS_ONLN); + if (count > 0) + return count; + } +#elif defined HW_NCPU + { + int mib[2], count = 0; + size_t len; + + mib[0] = CTL_HW; + mib[1] = HW_NCPU; + len = sizeof(count); + + if (sysctl (mib, 2, &count, &len, NULL, 0) == 0 && count > 0) + return count; + } +#endif + + return 1; /* Fallback */ +} + /* Epilogue {{{1 */ /* vim: set foldmethod=marker: */ diff --git a/glib/gthread.h b/glib/gthread.h index 710b64daf..b9c3025a0 100644 --- a/glib/gthread.h +++ b/glib/gthread.h @@ -249,6 +249,9 @@ void g_once_init_leave (volatile void *location, (g_once_init_leave((location), (gsize) (result))) #endif +GLIB_AVAILABLE_IN_2_36 +guint g_get_num_processors (void); + G_END_DECLS #endif /* __G_THREAD_H__ */ diff --git a/glib/tests/spawn-multithreaded.c b/glib/tests/spawn-multithreaded.c index 239bbf647..baccf362b 100644 --- a/glib/tests/spawn-multithreaded.c +++ b/glib/tests/spawn-multithreaded.c @@ -26,8 +26,6 @@ #include #include -#define N_THREADS (20) - static char *echo_prog_path; static void @@ -35,8 +33,12 @@ multithreaded_test_run (GThreadFunc function) { int i; GPtrArray *threads = g_ptr_array_new (); + guint n_threads; - for (i = 0; i < N_THREADS; i++) + /* Limit to 64, otherwise we may hit file descriptor limits and such */ + n_threads = MIN (g_get_num_processors () * 2, 64); + + for (i = 0; i < n_threads; i++) { GThread *thread; @@ -44,7 +46,7 @@ multithreaded_test_run (GThreadFunc function) g_ptr_array_add (threads, thread); } - for (i = 0; i < N_THREADS; i++) + for (i = 0; i < n_threads; i++) { gpointer ret; ret = g_thread_join (g_ptr_array_index (threads, i));