Permalink
Browse files

[GH #830] Implement platform Parrot_get_num_cpus

Parrot_get_num_cpus is the new default instead of MAX_THREADS. Initialized at startup
  • Loading branch information...
1 parent 5412296 commit fba6c79491d1077023c05a925374b485147a2d1a Reini Urban committed Sep 16, 2012
View
@@ -1327,6 +1327,7 @@ src/platform/generic/io.c []
src/platform/generic/itimer.c []
src/platform/generic/math.c []
src/platform/generic/misc.c []
+src/platform/generic/num_cpus.c []
src/platform/generic/socket.c []
src/platform/generic/sysmem.c []
src/platform/generic/time.c []
@@ -1347,6 +1348,7 @@ src/platform/win32/file.c []
src/platform/win32/hires_timer.c []
src/platform/win32/io.c []
src/platform/win32/misc.c []
+src/platform/win32/num_cpus.c []
src/platform/win32/sysmem.c []
src/platform/win32/time.c []
src/platform/win32/uid.c []
View
@@ -97,7 +97,7 @@ sub _list_extra_headers {
# the header.
my @extra_headers = qw(malloc.h fcntl.h setjmp.h pthread.h signal.h
sys/types.h sys/socket.h netinet/in.h arpa/inet.h
- sys/stat.h sysexit.h limits.h sys/sysctl.h);
+ sys/stat.h sysexit.h limits.h sys/sysctl.h libcpuid.h);
# more extra_headers needed on mingw/msys; *BSD fails if they are present
if ( $conf->data->get('OSNAME_provisional') eq "msys" ) {
View
@@ -47,6 +47,7 @@ sub _set_implementations {
encoding.c
env.c
cpu_type.c
+ num_cpus.c
dl.c
math.c
itimer.c
@@ -1810,6 +1810,8 @@ src/platform/generic/math$(O) : src/platform/generic/math.c $(PARROT_H_HEADERS)
src/platform/generic/misc$(O) : src/platform/generic/misc.c $(PARROT_H_HEADERS)
+src/platform/generic/num_cpus$(O) : src/platform/generic/num_cpus.c $(PARROT_H_HEADERS)
+
src/platform/generic/socket$(O) : $(PARROT_H_HEADERS) $(INC_PMC_DIR)/pmc_socket.h \
src/io/io_private.h $(INC_PMC_DIR)/pmc_sockaddr.h src/platform/generic/socket.c
@@ -1852,6 +1854,8 @@ src/platform/win32/io$(O) : $(PARROT_H_HEADERS) src/io/io_private.h \
src/platform/win32/misc$(O) : src/platform/win32/misc.c $(PARROT_H_HEADERS)
+src/platform/win32/num_cpus$(O) : src/platform/win32/num_cpus.c $(PARROT_H_HEADERS)
+
src/platform/win32/sysmem$(O) : src/platform/win32/sysmem.c $(PARROT_H_HEADERS)
src/platform/win32/time$(O) : src/platform/win32/time.c $(PARROT_H_HEADERS)
@@ -413,11 +413,15 @@ PARROT_EXPORT
INTVAL Parrot_get_entropy(PARROT_INTERP);
/*
- * CPU Type
+ * CPU
*/
PARROT_EXPORT
STRING *Parrot_get_cpu_type(PARROT_INTERP);
+PARROT_EXPORT
+INTVAL Parrot_get_num_cpus(PARROT_INTERP);
+
+
#endif /* PARROT_PLATFORM_INTERFACE_H_GUARD */
/*
View
@@ -1,5 +1,5 @@
/* thread.h
- * Copyright (C) 2001-2011, Parrot Foundation.
+ * Copyright (C) 2001-2012, Parrot Foundation.
* Overview:
* This is the api header for the thread primitives
* Data Structure and Algorithms:
@@ -25,7 +25,7 @@
#include "parrot/atomic.h"
-#define MAX_THREADS 9
+#define MAX_THREADS 16
#ifndef YIELD
# define YIELD
@@ -115,6 +115,9 @@ VAR_SCOPE Shared_gc_info *shared_gc_info;
/* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */
void Parrot_clone_code(Parrot_Interp d, Parrot_Interp s);
+void Parrot_set_num_threads(PARROT_INTERP, INTVAL numthreads)
+ __attribute__nonnull__(1);
+
PARROT_CANNOT_RETURN_NULL
PMC * Parrot_thread_create(PARROT_INTERP, INTVAL type, INTVAL clone_flags)
__attribute__nonnull__(1);
@@ -147,7 +150,9 @@ int Parrot_thread_get_free_threads_array_index(PARROT_INTERP);
PARROT_CANNOT_RETURN_NULL
Interp** Parrot_thread_get_threads_array(PARROT_INTERP);
-void Parrot_thread_init_threads_array(PARROT_INTERP);
+void Parrot_thread_init_threads_array(PARROT_INTERP)
+ __attribute__nonnull__(1);
+
void Parrot_thread_insert_thread(PARROT_INTERP,
ARGIN(Interp* thread),
int index)
@@ -196,6 +201,8 @@ void Parrot_thread_wait_for_notification(PARROT_INTERP)
__attribute__nonnull__(1);
#define ASSERT_ARGS_Parrot_clone_code __attribute__unused__ int _ASSERT_ARGS_CHECK = (0)
+#define ASSERT_ARGS_Parrot_set_num_threads __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
+ PARROT_ASSERT_ARG(interp))
#define ASSERT_ARGS_Parrot_thread_create __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
PARROT_ASSERT_ARG(interp))
#define ASSERT_ARGS_Parrot_thread_create_local_sub \
@@ -217,7 +224,8 @@ void Parrot_thread_wait_for_notification(PARROT_INTERP)
#define ASSERT_ARGS_Parrot_thread_get_threads_array \
__attribute__unused__ int _ASSERT_ARGS_CHECK = (0)
#define ASSERT_ARGS_Parrot_thread_init_threads_array \
- __attribute__unused__ int _ASSERT_ARGS_CHECK = (0)
+ __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
+ PARROT_ASSERT_ARG(interp))
#define ASSERT_ARGS_Parrot_thread_insert_thread __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
PARROT_ASSERT_ARG(interp) \
, PARROT_ASSERT_ARG(thread))
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2012, Parrot Foundation.
+ */
+
+/*
+
+=head1 NAME
+
+src/platform/generic/num_cpus.c
+
+=head1 DESCRIPTION
+
+Returns the number of CPUs for non-win32 systems
+For win32, look in platform/win32/num_cpus.c
+
+=head2 Functions
+
+=cut
+
+*/
+
+#include "parrot/parrot.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef PARROT_HAS_HEADER_UNISTD
+# include <unistd.h>
+#endif
+
+/* HEADERIZER HFILE: none */
+
+/*
+
+=over 4
+
+=item C<INTVAL Parrot_get_num_cpus(Parrot_Interp)>
+
+Returns the number of CPUs
+
+=back
+
+=cut
+
+*/
+
+INTVAL
+Parrot_get_num_cpus(Parrot_Interp interp) {
+ INTVAL nprocs = -1;
+
+#ifdef _SC_NPROCESSORS_ONLN
+ nprocs = sysconf(_SC_NPROCESSORS_ONLN);
+#elif defined (PARROT_HAS_HEADER_LIBCPUID)
+ struct cpu_raw_data_t raw;
+ struct cpu_id_t data;
+
+ if (!cpuid_present()) {
+ printf("cpuid_present failed\n");
+ exit(EXIT_FAILURE);
+ }
+ if (cpuid_get_raw_data(&raw) < 0) {
+ printf("cpuid_get_raw_data failed\n");
+ printf("Error: %s\n", cpuid_error());
+ exit(EXIT_FAILURE);
+ }
+ if (cpu_identify(&raw, &data) < 0) {
+ printf("cpu_identify failed\n");
+ printf("Error: %s\n", cpuid_error());
+ exit(EXIT_FAILURE);
+ }
+ nprocs = data.num_cores;
+#else
+ FILE *f;
+ char line[128];
+
+ if (!fopen("/proc/cpuinfo", "rb"))
+ exit(EXIT_FAILURE);
+
+ while (!feof(f)) {
+ fgets(line, 128, f);
+ if (strlen(line) == 1) continue;
+ if (strncmp(line, "cpu cores", 8) == 0) {
+ sscanf(line, "cpu cores\t: %d", &nprocs);
+ fclose (f);
+ return nprocs;
+ }
+ }
+ fclose (f);
+#endif
+ return nprocs;
+}
+
+/*
+ * Local variables:
+ * c-file-style: "parrot"
+ * End:
+ * vim: expandtab shiftwidth=4 cinoptions='\:2=2' :
+ */
+
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2012, Parrot Foundation.
+ */
+
+/*
+
+=head1 NAME
+
+src/platform/win32/num_cpus.c
+
+=head1 DESCRIPTION
+
+Returns the number of CPUs for win32 systems
+
+=head2 Functions
+
+=cut
+
+*/
+
+#include "parrot/parrot.h"
+
+#ifdef _WIN32
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#endif
+
+/* HEADERIZER HFILE: none */
+
+/*
+
+=over 4
+
+=item C<INTVAL Parrot_get_num_cpus(Parrot_Interp)>
+
+Returns the number of CPUs
+
+=back
+
+=cut
+
+*/
+
+INTVAL
+Parrot_get_num_cpus(Parrot_Interp interp)
+{
+ INTVAL nprocs = -1;
+ SYSTEM_INFO info;
+
+ GetSystemInfo(&info);
+ nprocs = (INTVAL)info.dwNumberOfProcessors;
+ return nprocs;
+}
+
+/*
+ * Local variables:
+ * c-file-style: "parrot"
+ * End:
+ * vim: expandtab shiftwidth=4 cinoptions='\:2=2' :
+ */
+
View
@@ -53,6 +53,7 @@ static void* Parrot_thread_outer_runloop(ARGIN_NULLOK(void *arg));
/* HEADERIZER END: static */
static Interp * threads_array[MAX_THREADS];
+static size_t num_threads = -1;
/*
@@ -591,11 +592,24 @@ Initialize the threads array.
*/
void
-Parrot_thread_init_threads_array(SHIM_INTERP)
+Parrot_thread_init_threads_array(PARROT_INTERP)
{
ASSERT_ARGS(Parrot_thread_init_threads_array)
- int i = 0;
- for (; i < MAX_THREADS; i++)
+
+ int i;
+ int nprocs;
+
+ if (num_threads > 0) { /* cmdline or API override */
+ nprocs = num_threads;
+ }
+ else { /* or a useful default */
+ nprocs = Parrot_get_num_cpus(interp);
+ if (nprocs < 0 || nprocs > MAX_THREADS)
+ nprocs = MAX_THREADS;
+ num_threads = nprocs;
+ }
+
+ for (i = 0; i < nprocs; i++)
threads_array[i] = NULL;
}
@@ -614,8 +628,9 @@ int
Parrot_thread_get_free_threads_array_index(SHIM_INTERP)
{
ASSERT_ARGS(Parrot_thread_get_free_threads_array_index)
+
int i = 0;
- for (; i < MAX_THREADS; i++)
+ for (; i < num_threads; i++)
if (threads_array[i] == NULL)
return i;
return -1;
@@ -640,6 +655,30 @@ Parrot_thread_insert_thread(PARROT_INTERP, ARGIN(Interp* thread), int index)
threads_array[index] = thread;
}
+
+/*
+
+=item C<void Parrot_set_num_threads(PARROT_INTERP, INTVAL numthreads)>
+
+Overrides the default number of allocated threads, which defaults to
+the number of online CPUs.
+
+This function must be called before C<Parrot_thread_init_threads_array()>;
+
+=cut
+
+*/
+
+void
+Parrot_set_num_threads(PARROT_INTERP, INTVAL numthreads)
+{
+ ASSERT_ARGS(Parrot_set_num_threads)
+
+ /* Ensure that threads are not already initialized */
+ if (num_threads < 0)
+ num_threads = numthreads;
+}
+
/*
=back

0 comments on commit fba6c79

Please sign in to comment.