#endif
#include <assert.h>
+#include <fcntl.h>
+#include <nproc.h>
#include "libguile/validate.h"
#include "libguile/root.h"
#include "libguile/strings.h"
#include "libguile/weaks.h"
-#ifdef __MINGW32__
-#ifndef ETIMEDOUT
-# define ETIMEDOUT WSAETIMEDOUT
-#endif
-# include <fcntl.h>
-# include <process.h>
-# define pipe(fd) _pipe (fd, 256, O_BINARY)
-#endif /* __MINGW32__ */
-
#include <full-read.h>
};
static int
-GC_register_my_thread (struct GC_stack_base *)
+GC_register_my_thread (struct GC_stack_base *stack_base)
{
return GC_UNIMPLEMENTED;
}
#endif
static int
-GC_get_stack_base (struct GC_stack_base *)
+GC_get_stack_base (struct GC_stack_base *stack_base)
{
stack_base->mem_base = get_thread_stack_base ();
#ifdef __ia64__
static SCM scm_i_default_dynamic_state;
+/* Run when a fluid is collected. */
+void
+scm_i_reset_fluid (size_t n, SCM val)
+{
+ scm_i_thread *t;
+
+ scm_i_pthread_mutex_lock (&thread_admin_mutex);
+ for (t = all_threads; t; t = t->next_thread)
+ if (SCM_I_DYNAMIC_STATE_P (t->dynamic_state))
+ {
+ SCM v = SCM_I_DYNAMIC_STATE_FLUIDS (t->dynamic_state);
+
+ if (n < SCM_SIMPLE_VECTOR_LENGTH (v))
+ SCM_SIMPLE_VECTOR_SET (v, n, val);
+ }
+ scm_i_pthread_mutex_unlock (&thread_admin_mutex);
+}
+
/* Perform first stage of thread initialisation, in non-guile mode.
*/
static void
t.sleep_object = SCM_BOOL_F;
t.sleep_fd = -1;
- if (pipe (t.sleep_pipe) != 0)
+ if (pipe2 (t.sleep_pipe, O_CLOEXEC) != 0)
/* FIXME: Error conditions during the initialization phase are handled
gracelessly since public functions such as `scm_init_guile ()'
currently have type `void'. */
#define SCM_MUTEXP(x) SCM_SMOB_PREDICATE (scm_tc16_mutex, x)
#define SCM_MUTEX_DATA(x) ((fat_mutex *) SCM_SMOB_DATA (x))
+static SCM
+call_cleanup (void *data)
+{
+ SCM *proc_p = data;
+ return scm_call_0 (*proc_p);
+}
+
/* Perform thread tear-down, in guile mode.
*/
static void *
{
scm_i_thread *t = (scm_i_thread *) v;
+ /* Ensure the signal handling thread has been launched, because we might be
+ shutting it down. This needs to be done in Guile mode. */
+ scm_i_ensure_signal_delivery_thread ();
+
if (!scm_is_false (t->cleanup_handler))
{
SCM ptr = t->cleanup_handler;
t->cleanup_handler = SCM_BOOL_F;
t->result = scm_internal_catch (SCM_BOOL_T,
- (scm_t_catch_body) scm_call_0, ptr,
+ call_cleanup, &ptr,
scm_handle_by_message_noexit, NULL);
}
do_thread_exit_trampoline (struct GC_stack_base *sb, void *v)
{
/* Won't hurt if we are already registered. */
+#if SCM_USE_PTHREAD_THREADS
GC_register_my_thread (sb);
+#endif
return scm_with_guile (do_thread_exit, v);
}
case but it doesn't hurt to be consistent. */
scm_i_pthread_setspecific (scm_i_thread_key, t);
- /* Ensure the signal handling thread has been launched, because we might be
- shutting it down. */
- scm_i_ensure_signal_delivery_thread ();
-
/* Scheme-level thread finalizers and other cleanup needs to happen in
guile mode. */
GC_call_with_stack_base (do_thread_exit_trampoline, t);
scm_i_pthread_setspecific (scm_i_thread_key, NULL);
+#if SCM_USE_PTHREAD_THREADS
GC_unregister_my_thread ();
+#endif
}
static scm_i_pthread_once_t init_thread_key_once = SCM_I_PTHREAD_ONCE_INIT;
*/
scm_i_init_guile (base);
+#if defined (HAVE_GC_ALLOW_REGISTER_THREADS) && SCM_USE_PTHREAD_THREADS
/* Allow other threads to come in later. */
GC_allow_register_threads ();
+#endif
scm_i_pthread_mutex_unlock (&scm_i_init_mutex);
}
scm_i_pthread_mutex_unlock (&scm_i_init_mutex);
/* Register this thread with libgc. */
+#if SCM_USE_PTHREAD_THREADS
GC_register_my_thread (base);
+#endif
guilify_self_1 (base);
guilify_self_2 (parent);
else
{
fprintf (stderr, "Failed to get stack base for current thread.\n");
- exit (1);
+ exit (EXIT_FAILURE);
}
}
}
#undef FUNC_NAME
+static void
+lock_mutex_return_void (SCM mx)
+{
+ (void) scm_lock_mutex (mx);
+}
+
+static void
+unlock_mutex_return_void (SCM mx)
+{
+ (void) scm_unlock_mutex (mx);
+}
+
void
scm_dynwind_lock_mutex (SCM mutex)
{
- scm_dynwind_unwind_handler_with_scm ((void(*)(SCM))scm_unlock_mutex, mutex,
+ scm_dynwind_unwind_handler_with_scm (unlock_mutex_return_void, mutex,
SCM_F_WIND_EXPLICITLY);
- scm_dynwind_rewind_handler_with_scm ((void(*)(SCM))scm_lock_mutex, mutex,
+ scm_dynwind_rewind_handler_with_scm (lock_mutex_return_void, mutex,
SCM_F_WIND_EXPLICITLY);
}
}
t->block_asyncs--;
- scm_async_click ();
+ scm_async_tick ();
scm_remember_upto_here_2 (cond, mutex);
}
#undef FUNC_NAME
+SCM_DEFINE (scm_total_processor_count, "total-processor-count", 0, 0, 0,
+ (void),
+ "Return the total number of processors of the machine, which\n"
+ "is guaranteed to be at least 1. A ``processor'' here is a\n"
+ "thread execution unit, which can be either:\n\n"
+ "@itemize\n"
+ "@item an execution core in a (possibly multi-core) chip, in a\n"
+ " (possibly multi- chip) module, in a single computer, or\n"
+ "@item a thread execution unit inside a core in the case of\n"
+ " @dfn{hyper-threaded} CPUs.\n"
+ "@end itemize\n\n"
+ "Which of the two definitions is used, is unspecified.\n")
+#define FUNC_NAME s_scm_total_processor_count
+{
+ return scm_from_ulong (num_processors (NPROC_ALL));
+}
+#undef FUNC_NAME
+
+SCM_DEFINE (scm_current_processor_count, "current-processor-count", 0, 0, 0,
+ (void),
+ "Like @code{total-processor-count}, but return the number of\n"
+ "processors available to the current process. See\n"
+ "@code{setaffinity} and @code{getaffinity} for more\n"
+ "information.\n")
+#define FUNC_NAME s_scm_current_processor_count
+{
+ return scm_from_ulong (num_processors (NPROC_CURRENT));
+}
+#undef FUNC_NAME
+
+
+\f
+
static scm_i_pthread_cond_t wake_up_cond;
static int threads_initialized_p = 0;