Skip to content

Commit

Permalink
[GH #830] Implement platform Parrot_get_num_cpus
Browse files Browse the repository at this point in the history
Parrot_get_num_cpus is the new default instead of MAX_THREADS. Initialized at startup
  • Loading branch information
Reini Urban committed Sep 16, 2012
1 parent 5412296 commit fba6c79
Show file tree
Hide file tree
Showing 9 changed files with 228 additions and 10 deletions.
2 changes: 2 additions & 0 deletions MANIFEST
Expand Up @@ -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 []
Expand All @@ -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 []
Expand Down
2 changes: 1 addition & 1 deletion config/auto/headers.pm
Expand Up @@ -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" ) {
Expand Down
1 change: 1 addition & 0 deletions config/auto/platform.pm
Expand Up @@ -47,6 +47,7 @@ sub _set_implementations {
encoding.c
env.c
cpu_type.c
num_cpus.c
dl.c
math.c
itimer.c
Expand Down
4 changes: 4 additions & 0 deletions config/gen/makefiles/root.in
Expand Up @@ -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

Expand Down Expand Up @@ -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)
Expand Down
6 changes: 5 additions & 1 deletion include/parrot/platform_interface.h
Expand Up @@ -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 */

/*
Expand Down
16 changes: 12 additions & 4 deletions include/parrot/thread.h
@@ -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:
Expand All @@ -25,7 +25,7 @@

#include "parrot/atomic.h"

#define MAX_THREADS 9
#define MAX_THREADS 16

#ifndef YIELD
# define YIELD
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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 \
Expand All @@ -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))
Expand Down
99 changes: 99 additions & 0 deletions src/platform/generic/num_cpus.c
@@ -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' :
*/

61 changes: 61 additions & 0 deletions src/platform/win32/num_cpus.c
@@ -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' :
*/

47 changes: 43 additions & 4 deletions src/thread.c
Expand Up @@ -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;

/*
Expand Down Expand Up @@ -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;
}

Expand All @@ -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;
Expand All @@ -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
Expand Down

0 comments on commit fba6c79

Please sign in to comment.