From 79cd5b8edac67485e9b88b3b0abf8068f54cf900 Mon Sep 17 00:00:00 2001 From: Marius Vollmer Date: Sun, 27 Oct 2002 20:12:07 +0000 Subject: [PATCH] * coop-defs.h (coop_m): Added 'level' field. (scm_t_mutex, scm_mutex_init, scm_mutex_lock, scm_mutex_trylock, scm_mutex_unlock, scm_mutex_destroy, scm_t_cond, scm_cond_init, scm_cond_wait, scm_cond_timedwait, scm_cond_signal, scm_cond_broadcast, scm_cond_destroy, struct timespec): Do not define. (coop_condition_variable_broadcast): New. * coop-threads.c (scm_threads_init): Create smobs here, using the appropriate sizes. (scm_c_thread_exited_p, scm_try_mutex, scm_timed_wait_condition_variable, scm_broadcast_condition_variable): New. (scm_wait_condition_variable): Removed. * coop.c (coop_new_mutex_init): Initialize level. (coop_mutex_trylock, coop_mutex_lock, coop_mutex_unlock): maintain level. (coop_condition_variable_signal): Renamed to coop_condition_variable_broadcast and reimplemented in terms of that. Thus... (coop_condition_variable_broadcast): New. --- libguile/coop-defs.h | 29 ++--------------- libguile/coop-threads.c | 71 ++++++++++++++++++++++++++++++++++++++--- libguile/coop.c | 59 ++++++++++++++++++++++++---------- 3 files changed, 111 insertions(+), 48 deletions(-) diff --git a/libguile/coop-defs.h b/libguile/coop-defs.h index e84a352d3..424a0134e 100644 --- a/libguile/coop-defs.h +++ b/libguile/coop-defs.h @@ -3,7 +3,7 @@ #ifndef SCM_COOP_DEFS_H #define SCM_COOP_DEFS_H -/* Copyright (C) 1996,1997,1998,1999,2000,2001 Free Software Foundation, Inc. +/* Copyright (C) 1996,1997,1998,1999,2000,2001, 2002 Free Software Foundation, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -142,24 +142,18 @@ typedef struct coop_q_t { typedef struct coop_m { coop_t *owner; /* Mutex owner */ + int level; /* for recursive locks. */ coop_q_t waiting; /* Queue of waiting threads */ } coop_m; typedef int coop_mattr; -typedef coop_m scm_t_mutex; - SCM_API int coop_mutex_init (coop_m*); SCM_API int coop_new_mutex_init (coop_m*, coop_mattr*); SCM_API int coop_mutex_lock (coop_m*); SCM_API int coop_mutex_trylock (coop_m*); SCM_API int coop_mutex_unlock (coop_m*); SCM_API int coop_mutex_destroy (coop_m*); -#define scm_mutex_init coop_mutex_init -#define scm_mutex_lock coop_mutex_lock -#define scm_mutex_trylock coop_mutex_lock -#define scm_mutex_unlock coop_mutex_unlock -#define scm_mutex_destroy coop_mutex_destroy /* A Condition variable is made up of a list of threads waiting on the condition. */ @@ -170,18 +164,6 @@ typedef struct coop_c { typedef int coop_cattr; -typedef coop_c scm_t_cond; - -#ifndef HAVE_STRUCT_TIMESPEC -/* POSIX.4 structure for a time value. This is like a `struct timeval' but - has nanoseconds instead of microseconds. */ -struct timespec -{ - long int tv_sec; /* Seconds. */ - long int tv_nsec; /* Nanoseconds. */ -}; -#endif - SCM_API int coop_condition_variable_init (coop_c*); SCM_API int coop_new_condition_variable_init (coop_c*, coop_cattr*); SCM_API int coop_condition_variable_wait_mutex (coop_c*, coop_m*); @@ -189,13 +171,8 @@ SCM_API int coop_condition_variable_timed_wait_mutex (coop_c*, coop_m*, const struct timespec *abstime); SCM_API int coop_condition_variable_signal (coop_c*); +SCM_API int coop_condition_variable_broadcast (coop_c*); SCM_API int coop_condition_variable_destroy (coop_c*); -#define scm_cond_init coop_new_condition_variable_init -#define scm_cond_wait coop_condition_variable_wait_mutex -#define scm_cond_timedwait coop_condition_variable_timed_wait_mutex -#define scm_cond_signal coop_condition_variable_signal -#define scm_cond_broadcast coop_condition_variable_signal /* yes */ -#define scm_cond_destroy coop_condition_variable_destroy typedef int coop_k; diff --git a/libguile/coop-threads.c b/libguile/coop-threads.c index ae00d3428..a7e0047cc 100644 --- a/libguile/coop-threads.c +++ b/libguile/coop-threads.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1995,1996,1997,1998,2000,2001 Free Software Foundation, Inc. +/* Copyright (C) 1995,1996,1997,1998,2000,2001, 2002 Free Software Foundation, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -66,6 +66,11 @@ scm_threads_init (SCM_STACKITEM *i) { coop_init(); + scm_tc16_thread = scm_make_smob_type ("thread", 0); + scm_tc16_mutex = scm_make_smob_type ("mutex", sizeof (coop_m)); + scm_tc16_condvar = scm_make_smob_type ("condition-variable", + sizeof (coop_c)); + scm_thread_count = 1; #ifndef GUILE_PTHREAD_COMPAT @@ -418,10 +423,20 @@ scm_join_thread (SCM thread) if (thread_data) /* The thread is still alive */ coop_join (thread_data); + /* XXX - return real result. */ return SCM_BOOL_T; } #undef FUNC_NAME +int +scm_c_thread_exited_p (SCM thread) +#define FUNC_NAME s_scm_thread_exited_p +{ + SCM_VALIDATE_THREAD (1, thread); + return SCM_THREAD_DATA (thread) != NULL; +} +#undef FUNC_NAME + SCM scm_yield (void) { @@ -456,6 +471,13 @@ scm_lock_mutex (SCM m) return SCM_BOOL_T; } +SCM +scm_try_mutex (SCM m) +{ + SCM_ASSERT (SCM_MUTEXP (m), m, SCM_ARG1, s_lock_mutex); + return SCM_BOOL (coop_mutex_trylock (SCM_MUTEX_DATA (m))); +} + SCM scm_unlock_mutex (SCM m) { @@ -478,8 +500,13 @@ scm_make_condition_variable (void) } SCM -scm_wait_condition_variable (SCM c, SCM m) +scm_timed_wait_condition_variable (SCM c, SCM m, SCM t) +#define FUNC_NAME s_wait_condition_variable { + coop_c *cv; + coop_m *mx; + struct timespec waittime; + SCM_ASSERT (SCM_CONDVARP (c), c, SCM_ARG1, @@ -488,10 +515,33 @@ scm_wait_condition_variable (SCM c, SCM m) m, SCM_ARG2, s_wait_condition_variable); - coop_condition_variable_wait_mutex (SCM_CONDVAR_DATA (c), - SCM_MUTEX_DATA (m)); - return SCM_BOOL_T; + + cv = SCM_CONDVAR_DATA (c); + mx = SCM_MUTEX_DATA (m); + + if (!SCM_UNBNDP (t)) + { + if (SCM_CONSP (t)) + { + SCM_VALIDATE_UINT_COPY (3, SCM_CAR(t), waittime.tv_sec); + SCM_VALIDATE_UINT_COPY (3, SCM_CDR(t), waittime.tv_nsec); + waittime.tv_nsec *= 1000; + } + else + { + SCM_VALIDATE_UINT_COPY (3, t, waittime.tv_sec); + waittime.tv_nsec = 0; + } + return SCM_BOOL( + coop_condition_variable_timed_wait_mutex (cv, mx, &waittime)); + } + else + { + coop_condition_variable_wait_mutex (cv, mx); + return SCM_BOOL_T; + } } +#undef FUNC_NAME SCM scm_signal_condition_variable (SCM c) @@ -504,6 +554,17 @@ scm_signal_condition_variable (SCM c) return SCM_BOOL_T; } +SCM +scm_broadcast_condition_variable (SCM c) +{ + SCM_ASSERT (SCM_CONDVARP (c), + c, + SCM_ARG1, + s_broadcast_condition_variable); + coop_condition_variable_broadcast (SCM_CONDVAR_DATA (c)); + return SCM_BOOL_T; +} + /* Local Variables: c-file-style: "gnu" diff --git a/libguile/coop.c b/libguile/coop.c index 889276e23..3b46e65ea 100644 --- a/libguile/coop.c +++ b/libguile/coop.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc. +/* Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -40,7 +40,7 @@ * If you do not wish that, delete this exception notice. */ -/* $Id: coop.c,v 1.31 2002-08-17 20:39:35 ghouston Exp $ */ +/* $Id: coop.c,v 1.32 2002-10-27 20:12:07 mvo Exp $ */ /* Cooperative thread library, based on QuickThreads */ @@ -293,6 +293,7 @@ int coop_new_mutex_init (coop_m *m, coop_mattr *attr) { m->owner = NULL; + m->level = 0; coop_qinit(&(m->waiting)); return 0; } @@ -305,6 +306,11 @@ coop_mutex_trylock (coop_m *m) m->owner = coop_global_curr; return 0; } + else if (m->owner == coop_global_curr) + { + m->level++; + return 0; + } else return EBUSY; } @@ -316,6 +322,10 @@ coop_mutex_lock (coop_m *m) { m->owner = coop_global_curr; } + else if (m->owner == coop_global_curr) + { + m->level++; + } else { coop_t *old, *newthread; @@ -343,23 +353,31 @@ coop_mutex_unlock (coop_m *m) { coop_t *old, *newthread; - newthread = coop_qget (&(m->waiting)); - if (newthread != NULL) + if (m->level == 0) { - /* Record the current top-of-stack before going to sleep */ - coop_global_curr->top = &old; - - old = coop_global_curr; - coop_global_curr = newthread; - /* The new thread came into m->waiting through a lock operation. - It now owns this mutex. */ - m->owner = coop_global_curr; - QT_BLOCK (coop_yieldhelp, old, &coop_global_runq, newthread->sp); + newthread = coop_qget (&(m->waiting)); + if (newthread != NULL) + { + /* Record the current top-of-stack before going to sleep */ + coop_global_curr->top = &old; + + old = coop_global_curr; + coop_global_curr = newthread; + /* The new thread came into m->waiting through a lock operation. + It now owns this mutex. */ + m->owner = coop_global_curr; + QT_BLOCK (coop_yieldhelp, old, &coop_global_runq, newthread->sp); + } + else + { + m->owner = NULL; + } } + else if (m->level > 0) + m->level--; else - { - m->owner = NULL; - } + abort (); /* XXX */ + return 0; } @@ -472,7 +490,7 @@ coop_condition_variable_timed_wait_mutex (coop_c *c, } int -coop_condition_variable_signal (coop_c *c) +coop_condition_variable_broadcast (coop_c *c) { coop_t *newthread; @@ -483,6 +501,13 @@ coop_condition_variable_signal (coop_c *c) return 0; } +int +coop_condition_variable_signal (coop_c *c) +{ + return coop_condition_variable_broadcast (c); +} + + /* {Keys} */ -- 2.20.1