is now provided via a thread-mutex.
global.scm:36: get-interrupt-enables set-interrupt-enables! with-interrupt-mask
+ Definitions.
global.scm:129: (set-interrupt-enables! (fix:and limit-mask (get-interrupt-enables))))
+ Caller: limit-interrupts!
+ No callers, but exported to ().
global.scm:234: (with-absolutely-no-interrupts (ucode-primitive halt))
+ Caller: %quit
global.scm:346: (without-interrupts
+ Caller: clean-obarray
+
+ OK. Callers of limit-interrupts! should be warned in the
+ Release Notes? Why does %quit use with-absolutely-no-
+ interrupts?
+
+ The big problem was clean-obarray. It runs as a
+ secondary-gc-daemon (running in parallel with other
+ processors), and was using without-interrupts to ensure sole
+ access to the obarray.
+
+ A number of primitives and compiler utilities modify the
+ obarray so a pthread mutex was introduced to serialize access
+ to it (conservatively, without much study of its modifier
+ procedures). Clean-obarray serializes with these C functions
+ using the new smp-lock-obarray primitive.
hash.scm:168: (with-absolutely-no-interrupts
hash.scm:213: (with-absolutely-no-interrupts
/* String hash functions and interning of symbols. */
-#include "scheme.h"
#include "prims.h"
+#include "ossmp.h"
#include "trap.h"
+
+#ifdef ENABLE_SMP
+static pthread_mutex_t mutex = MUTEX_INITIALIZER;
+# ifdef ENABLE_DEBUGGING_TOOLS
+static bool locked_p = false;
+# endif
+#endif
\f
/* The FNV hash, short for Fowler/Noll/Vo in honor of its creators. */
void
strengthen_symbol (SCHEME_OBJECT symbol)
{
+ LOCK();
replace_symbol_bucket_type (symbol, TC_LIST);
+ UNLOCK();
}
void
weaken_symbol (SCHEME_OBJECT symbol)
{
+ LOCK();
replace_symbol_bucket_type (symbol, TC_WEAK_CONS);
+ UNLOCK();
}
static SCHEME_OBJECT
-make_symbol (SCHEME_OBJECT string, SCHEME_OBJECT * cell)
+make_symbol_entry (SCHEME_OBJECT string)
{
Primitive_GC_If_Needed (4);
{
Free += 2;
MEMORY_SET (symbol, SYMBOL_NAME, string);
MEMORY_SET (symbol, SYMBOL_GLOBAL_VALUE, UNBOUND_OBJECT);
- (*cell) = (system_pair_cons (TC_WEAK_CONS, symbol, EMPTY_LIST));
- return (symbol);
+ return (system_pair_cons (TC_WEAK_CONS, symbol, EMPTY_LIST));
}
}
SCHEME_OBJECT
find_symbol (unsigned long length, const char * string)
{
- SCHEME_OBJECT * cell = (find_symbol_internal (length, string));
- return ((INTERNED_SYMBOL_P (*cell)) ? (*cell) : SHARP_F);
+ SCHEME_OBJECT * cell, result;
+ LOCK();
+ cell = (find_symbol_internal (length, string));
+ result = ((INTERNED_SYMBOL_P (*cell)) ? (*cell) : SHARP_F);
+ UNLOCK();
+ return (result);
}
\f
SCHEME_OBJECT
memory_to_symbol (unsigned long length, const void * string)
{
- SCHEME_OBJECT * cell = (find_symbol_internal (length, string));
- return
- ((INTERNED_SYMBOL_P (*cell))
- ? (*cell)
- : (make_symbol ((memory_to_string (length, string)), cell)));
+ SCHEME_OBJECT * cell, result;
+ LOCK();
+ cell = (find_symbol_internal (length, string));
+ if (INTERNED_SYMBOL_P (*cell))
+ result = (*cell);
+ else
+ {
+ SCHEME_OBJECT entry;
+ UNLOCK();
+ /* May abort for GC. */
+ entry = (make_symbol_entry (memory_to_string (length, string)));
+ LOCK();
+ cell = (find_symbol_internal (length, string));
+ if (INTERNED_SYMBOL_P (*cell))
+ result = (*cell);
+ else
+ {
+ (*cell) = entry;
+ result = PAIR_CAR (entry);
+ }
+ }
+ UNLOCK();
+ return (result);
}
SCHEME_OBJECT
SCHEME_OBJECT
string_to_symbol (SCHEME_OBJECT string)
{
- SCHEME_OBJECT * cell
- = (find_symbol_internal ((STRING_LENGTH (string)),
- (STRING_POINTER (string))));
- return ((INTERNED_SYMBOL_P (*cell))
- ? (*cell)
- : (make_symbol (string, cell)));
+ unsigned long length = (STRING_LENGTH (string));
+ const char * chars = (STRING_POINTER (string));
+ SCHEME_OBJECT * cell, result;
+ LOCK();
+ cell = (find_symbol_internal (length, chars));
+ if (INTERNED_SYMBOL_P (*cell))
+ result = (*cell);
+ else
+ {
+ SCHEME_OBJECT entry;
+ UNLOCK();
+ /* May abort for GC. */
+ entry = (make_symbol_entry (string));
+ LOCK();
+ cell = (find_symbol_internal (length, chars));
+ if (INTERNED_SYMBOL_P (*cell))
+ result = (*cell);
+ else
+ {
+ (*cell) = entry;
+ result = PAIR_CAR (entry);
+ }
+ }
+ UNLOCK();
+ return (result);
}
SCHEME_OBJECT
intern_symbol (SCHEME_OBJECT symbol)
{
- SCHEME_OBJECT name = (MEMORY_REF (symbol, SYMBOL_NAME));
- SCHEME_OBJECT * cell
- = (find_symbol_internal ((STRING_LENGTH (name)),
- (STRING_POINTER (name))));
+ SCHEME_OBJECT string = (MEMORY_REF (symbol, SYMBOL_NAME));
+ unsigned long length = (STRING_LENGTH (string));
+ const char * chars = (STRING_POINTER (string));
+ SCHEME_OBJECT * cell, result;
+ LOCK();
+ cell = (find_symbol_internal (length, chars));
if (INTERNED_SYMBOL_P (*cell))
- return (*cell);
+ result = (*cell);
else
{
- SCHEME_OBJECT result = (OBJECT_NEW_TYPE (TC_INTERNED_SYMBOL, symbol));
- (*cell) = (system_pair_cons (TC_WEAK_CONS, result, EMPTY_LIST));
- return (result);
+ SCHEME_OBJECT entry;
+ UNLOCK();
+ /* May abort for GC. */
+ result = (OBJECT_NEW_TYPE (TC_INTERNED_SYMBOL, symbol));
+ entry = (system_pair_cons (TC_WEAK_CONS, result, EMPTY_LIST));
+ LOCK();
+ cell = (find_symbol_internal (length, chars));
+ if (INTERNED_SYMBOL_P (*cell))
+ result = (*cell);
+ else
+ (*cell) = entry;
}
+ UNLOCK();
+ return (result);
}
const char *
% (arg_ulong_integer (2))));
}
}
+
+DEFINE_PRIMITIVE ("SMP-LOCK-OBARRAY", Prim_smp_lock_obarray, 1, 1,
+ "(SMP-LOCK-OBARRAY LOCK?)\n\
+When LOCK? is #F/non-#F, unlock/lock the pthread mutex serializing\n\
+accesses to the obarray.")
+{
+ PRIMITIVE_HEADER (1);
+ {
+#ifdef ENABLE_SMP
+ if (ARG_REF (1) != SHARP_F)
+ LOCK();
+ else
+ UNLOCK();
+#endif
+ }
+ PRIMITIVE_RETURN (UNSPECIFIC);
+}