1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-05-09 07:00:23 +02:00
Commit graph

9315 commits

Author SHA1 Message Date
Ludovic Courtès
c6054feaf0 Add support for static allocation of cells, strings and stringbufs.
* libguile/__scm.h (SCM_ALIGNED): New macro.

* libguile/_scm.h: Include "libguile/strings.h", to make the
  string/stringbuf-related constants visible to snarffed code.

* libguile/snarf.h (SCM_SUPPORT_STATIC_ALLOCATION): New macro.
  (SCM_SYMBOL, SCM_GLOBAL_SYMBOL)[SCM_SUPPORT_STATIC_ALLOCATION]: New
  alternative versions of these macros with support for (almost) static
  allocation via the use of `string->symbol'.
  (SCM_IMMUTABLE_DOUBLE_CELL, SCM_IMMUTABLE_STRINGBUF,
  SCM_IMMUTABLE_STRING): New macros.

* libguile/tags.h (SCM)[SCM_DEBUG_TYPING_STRICTNESS==1]: Use a pointer
  type that is compatible with other pointer types, to avoid potential
  violation of strict aliasing rules.
2009-01-14 00:05:23 +01:00
Ludovic Courtès
35920c00a8 Expose some of the string/stringbuf internal flags and tags.
* libguile/strings.h (scm_tc7_ro_string, SCM_I_STRINGBUF_F_SHARED,
  SCM_I_STRINGBUF_F_INLINE): New macros.

* libguile/strings.c (STRINGBUF_F_SHARED): Alias for
  `SCM_I_STRINGBUF_F_SHARED'.
  (STRINGBUF_F_INLINE): Alias for `SCM_I_STRINGBUF_F_INLINE'.
  (RO_STRING_TAG): Alias for `scm_tc7_ro_string'.
2009-01-13 23:59:17 +01:00
Andy Wingo
7aa6f86b77 fix marking empty VM continuations
* libguile/vm.h (struct scm_vm_cont):
* libguile/vm.c (capture_vm_cont, reinstate_vm_cont): Change so we just
  store the registers as they are, with the reloc.
  (vm_cont_mark): Only mark the stack if it has elements on it, otherwise
  we get a bogus fp.

* libguile/stacks.c (scm_make_stack): Update for change to vm
  continuations.
2009-01-13 22:33:21 +01:00
Andy Wingo
d5968e7f4e Merge branch 'master' into vm 2009-01-12 23:34:42 +01:00
Neil Jerram
4a462e3544 Make sure that we have a real on-the-stack alloca()
Because of how Guile saves and restores continuations (by copying the
stack), and how it uses alloca to create space for debug information
on the stack, we must have an alloca() that really does use the stack,
and not one that uses the heap.

To do this, we use the Gnulib "alloca-opt" module instead of "alloca".

This commit also updates the Gnulib sources from the current Gnulib
Git repository.
2009-01-12 22:08:56 +00:00
Andy Wingo
616167fc12 remove a paranoid define; fix bitrot in measure.scm.
* benchmark/measure.scm (measure): Fix bitrot.

* libguile/vm.c (VM_ENABLE_STACK_NULLING): Undefine this, as it hasn't
  caught any errors in quite a while.
2009-01-12 22:37:29 +01:00
Andy Wingo
c32929d14d Merge commit 'origin/master' into vm
Conflicts:

	.gitignore
	guile-tools.in
	srfi/srfi-19.scm
2009-01-12 21:36:39 +01:00
Andy Wingo
ff73ae34c3 finish compiler.texi, woo
* libguile/objcodes.c (do-pair): Removed unused debuging hack.

* module/language/glil/spec.scm (glil): Simplify a bit.

* module/system/repl/repl.scm (default-catch-handler): Don't catch
  vm-error, as vm-backtrace doesn't exist any more.

* doc/ref/compiler.texi: Finish documenting GLIL and object code.
2009-01-11 14:23:48 +01:00
Neil Jerram
a9931e4e1a Fix implementation of %fast-slot-ref and %fast-slot-set!
* libguile/goops.c (scm_sys_fast_slot_ref, scm_sys_fast_slot_set_x):
  Correct incantation for getting the number of slots of the specified
  instance.

* libguile/goops.h (SCM_NUMBER_OF_SLOTS): Removed (because wrong).

* test-suite/standalone/test-fast-slot-ref.in: New standalone test.

* configure.in: Generate test-suite/standalone/test-fast-slot-ref.

* test-suite/standalone/Makefile.am (check_SCRIPTS): Add
  test-fast-slot-ref.
2009-01-04 22:46:47 +00:00
Andy Wingo
fb10a0084e allow `apply' on %nil-terminated lists
* libguile/vm-engine.h (PUSH_LIST): Add a parameter to check that the
  list was proper.

* libguile/vm-i-system.c: Adapt PUSH_LIST callsites to pass SCM_NULLP or
  SCM_NULL_OR_NIL_P, as appropriate. Add a check to return/values*.

* libguile/vm.c: Add lang.h header for SCM_NULL_OR_NIL_P.

* test-suite/tests/elisp.test: Fix XFAIL for elisp + apply.
2009-01-04 14:06:52 +01:00
Andy Wingo
b1b942b74c remove heap links in VM frames, incorporate vm frames into normal backtraces
* doc/ref/vm.texi (Stack Layout): Update to remove references to the
  "heap link".

* gdbinit: Update for "heap link" removal.

* libguile/frames.c:
* libguile/frames.h: Update macros and diagram for removal of "heap
  link". As part of this, we also remove "heap frames", replacing them
  with "vm frames", which are much like the interpreter's debug objects,
  but for VM stacks. That is to say, they don't actually hold the stack
  themselves, just the pointers into stack that's held by a continuation
  (either captured or current).

* libguile/stacks.c (stack_depth, read_frames): Since a "stack" object is
  really a copy of information that comes from somewhere else, it makes
  sense to copy over info from the VM, just as `make-stack' does from the
  evaluator. The tricky bit is to figure out how to interleave VM and
  interpreter frames. We do that by starting in the interpreter, and
  whenever the current frame's procedure is actually a program, we switch
  to the VM stack, switching back when we reach a "bootstrap frame". The
  last bit is hacky, but it does work...
  (is_vm_bootstrap_frame): Hacky predicate to see if a VM frame is a
  bootstrap frame.
  (scm_make_stack): Accept a VM frame in addition to debug frames.
  Probably has some bugs in this case. But in the case that the arg is
  #t (a common case), do the right thing, capturing the top VM frame as
  well, and interleaving those frames appropriately on the stack.

  As an accident, we lost the ability to limit the number of frames in
  the backtrace. We could add that back, but personally I always want
  *all* frames in the trace... Narrowing still works fine, though there
  are some hiccups sometimes -- e.g. an outer cut to a procedure that
  does a tail-call in VM code will never find the cut, as it no longer
  exists in the continuation.

* libguile/vm.h (struct scm_vm): So! Now that we have switched to save
  stacks in the normal make-stack, there's no more need for `this_frame'
  or `last_frame'. On the other hand, we can take this opportunity to fix
  tracing: when we're in a trace hook, we set `trace_frame' on the VM,
  so we know not to fire hooks when we're already in a hook.
  (struct scm_vm_cont): Expose this, as make-stack needs it to make VM
  frames from VM continuations.

* libguile/vm.c (scm_vm_trace_frame): New function, gets the current
  trace frame.
  (vm_mark, make_vm): Hook up the trace frame.
  (vm_dispatch_hook): New hook dispatcher, with a dynwind so it does the
  right thing if the hook exits nonlocally.

* libguile/vm-engine.c (vm_run): No more this_frame in the wind data.

* libguile/vm-engine.h (RUN_HOOK): Run hooks through the dispatcher.
  (ALIGN_AS_NON_IMMEDIATE, POP_LIST_ON_STACK): Remove unused code.
  (NEW_FRAME): Adapt for no HL in the frame.

* libguile/vm-i-system.c (goto/args, mv-call, return, return/values):
  Adapt for no HL in the frame.

* module/system/vm/frame.scm:
* module/system/vm/vm.scm: Beginnings of some reworkings, needs more
  thought.
2008-12-26 18:07:20 +01:00
Andy Wingo
9a9f64874a add scm_c_program_source
* libguile/programs.h:
* libguile/programs.c (scm_c_program_source): New helper for getting
  source information from C.
2008-12-26 16:37:20 +01:00
Andy Wingo
e052d29640 backtrace.c: allow vectors for SCM_FRAME_SOURCE (frame)
* libguile/backtrace.c (display_backtrace_get_file_line): If the source
  is a vector, treat it as a #(line column file) vector, as emitted by
  the VM. Needs subsequent patches to make sense.
2008-12-26 16:35:43 +01:00
Andy Wingo
d22fc3e4af remove the `late-bind' instruction
* doc/ref/vm.texi: Minor fixes.

* libguile/vm-i-loader.c: Remove the unused `late-bind' instruction.
2008-12-19 11:50:43 +01:00
Ludovic Courtès
36c66a07e5 Don't use deprecated functions in `debug-malloc.c'.
* libguile/debug-malloc.c (scm_malloc_stats): Use
  `scm_from_locale_string ()'.  Patch by Linas Vepstas
  <linasvepstas@gmail.com>.
2008-12-18 22:49:17 +01:00
Ludovic Courtès
46e17bd233 Fix typo in makefile.
* libguile/Makefile.am (DOT_X_FILES): Substitute `gettext.x' to
  `gettext.c'.
2008-12-14 20:54:18 +01:00
Ludovic Courtès
083f810fe9 Merge branch 'master' into boehm-demers-weiser-gc
Conflicts:
	lib/Makefile.am
	libguile/struct.c
	libguile/threads.c
	m4/gnulib-cache.m4
	m4/gnulib-comp.m4
2008-12-14 20:48:15 +01:00
Neil Jerram
55aae98356 Revert "(scm_shell_usage): Note need for subscription to bug-guile@gnu.org."
This reverts commit f3e3f530c2, which is
appropriate because subscription is not now required for someone to
send a message to bug-guile@gnu.org.

Conflicts:
2008-12-10 19:11:28 +00:00
Ludovic Courtès
83fda4707c i18n: Add comment about standardization of the `locale_t' API.
* libguile/i18n.c: Add pointer to the POSIX 2008 standardization of the
  API.
2008-12-10 11:05:50 +01:00
Ludovic Courtès
de7d32d064 Remove useless references to Libtool's `dlpreopen' mechanism.
* libguile/Makefile.am (guile_LDFLAGS): Remove `@DLPREOPEN@' since it
  has no effect.

* libguile/guile.c (main): Don't invoke `LTDL_SET_PRELOADED_SYMBOLS ()'
  since it had no effect given how we invoke `libtool'.  It also fixes
  compatibility issues when using libltdl 1.5 with a Libtool 2.2
  package.
2008-12-07 22:35:23 +01:00
Ludovic Courtès
3ae3166b23 Fix sloppy bound checking in `string-{ref,set!}' with the empty string.
* libguile/strings.c (scm_string_ref): Add proper range checking for the
  empty string.
  (scm_string_set_x): Likewise.
  Reported by Bill Schottstaedt <bil@ccrma.Stanford.EDU>.

* test-suite/tests/strings.test ("string-ref"): New test prefix.
  ("string-set!")["empty string", "empty string and non-zero index",
  "out of range", "negative index", "regular string"]: New tests.

* NEWS: Update.
2008-12-02 19:52:13 +01:00
Ludovic Courtès
cb823e630d Fix potential deadlock in `make-struct'.
* libguile/struct.c (scm_make_struct): Remove critical section, as
  suggested by Linas Vepstas <linasvepstas@gmail.com>.  See
  http://lists.gnu.org/archive/html/bug-guile/2008-11/msg00036.html for
  a discussion.
2008-11-30 20:26:56 +01:00
Ludovic Courtès
634aa8de8f Check the return value of libc's functions to make `_FORTIFY_SOURCE=2' work.
This fixes bug #24009 reported by Martin Pitt.

* libguile/threads.c (guilify_self_1): Check the return value of
  pipe(2).
  (scm_std_select): Use `full_read ()' instead of `read ()' when reading
  from WAKEUP_FD.

* libguile/async.c (scm_i_queue_async_cell): Use `full_write ()' instead
  of write(2) when writing to SLEEP_FD.

* libguile/fports.c (fport_flush): Likewise.

* libguile/posix.c (getgroups): Use the return value of getgroups(2) as
  NGROUPS.
  (scm_nice): Get the return value of nice(2) to make glibc happy.

* libguile/scmsigs.c (take_signal): Use `full_write ()' instead of
  write(2).
2008-11-30 18:43:41 +01:00
Ludovic Courtès
1da93484fb Use orthodox libtoology in `guile'.
* libguile/guile.c (main): Use `LTDL_SET_PRELOADED_SYMBOLS ()' instead
  of our own trick.
2008-11-24 22:04:44 +01:00
Neil Jerram
6d2275560d Make scm_c_read use caller buffer only for unbuffered ports.
We recently modified scm_c_read so that it temporarily swaps the
caller's buffer with the port's normal read buffer, in order to
improve performance in the case where the port is unbuffered (which
actually means having a single-byte buffer) - but we implemented the
swap in the buffered case too.  The latter turns out to be a bad idea
- because it means that the C code of a custom port implementation
cannot rely on a port's buffer always being the same as when it was
first set up - and so this commit reverts that.  The buffer swapping
trick now applies to unbuffered ports only.

* libguile/ports.c (scm_c_read): Only do swapping of port and caller
  buffer for unbuffered ports.
2008-11-23 22:48:26 +00:00
Andy Wingo
f7e5296e04 late-variable-{ref,set} -> toplevel-{ref,set}
* benchmark/lib.scm:
* libguile/vm-i-system.c (toplevel-ref, toplevel-set):
* module/system/vm/assemble.scm (codegen):
* module/system/vm/disasm.scm (code-annotation):
  s/late-variable/toplevel/. It's just a better name.
2008-11-20 13:45:27 +01:00
Ludovic Courtès
ccf1ca4adf Update the thread stack base when `scm_with_guile' is invoked multiple times.
* NEWS: Update.

* libguile/threads.c (scm_i_init_thread_for_guile): When the thread is
  already guilified, update `t->base' so that it corresponds to the new
  stack base.  Bug report and patch by Linas Vepstas <linasvepstas@gmail.com>.

* test-suite/standalone/Makefile.am (test_scm_with_guile_CFLAGS,
  test_scm_with_guile_LDADD): New.
  (check_PROGRAMS, TESTS): Add `test-scm-with-guile'.
2008-11-14 00:36:58 +01:00
Andy Wingo
32c8ae2009 rashly bump stack limit to 40k words
* libguile/eval.c (scm_debug_opts): Whereas, today's machines are larger
  than yesterday's; GCC consumes more words per stack frame than it used
  to; and you can get quite some recursion in a halfway-compiled system,
  be it resolved: let's bump up the C stack limit to 40k words (160 kB /
  320 kB, depending on word size).
2008-11-11 23:11:27 +01:00
Ludovic Courtès
857a263e4f Have version' return PACKAGE_VERSION'.
* libguile/version.c (scm_version): Return `PACKAGE_VERSION' instead of
  "MAJOR.MINOR.MICRO".
2008-11-10 23:46:29 +01:00
Ludovic Courtès
490cf75094 Work around unintentional retention of modules by the GC.
This reverts par of "Document the failure of `gc.test' wrt. unused modules."
(commit 328efeb9a6.)

* ice-9/boot-9.scm (set-module-eval-closure!): Don't set the `module' property
  on CLOSURE.

* libguile/modules.c (scm_lookup_closure_module): Call `abort ()' to make it
  clear that code that uses the `module' property no longer works.  That code
  is unused anyway.
2008-11-05 22:39:31 +01:00
Ludovic Courtès
00b8057d1f Merge branch 'master' into boehm-demers-weiser-gc
Conflicts:
	libguile/threads.c
2008-11-04 19:07:07 +01:00
Ludovic Courtès
f8e7dfdc53 Remove the SMOB mark procedure for source properties.
* libguile/srcprop.c (srcprops_mark): Remove.
  (scm_init_srcprop): Remove call to `scm_set_smob_mark ()'.
2008-11-02 23:24:10 +01:00
Andy Wingo
9b10d0bcfd fix for (apply values '(1))
* libguile/vm-i-system.c (return/values): In the
  multiple-values-to-a-single-value-continuation (or MV but where N=1),
  null out the correct number of values from the stack. Fixes aborts on
  (apply values '(1)).

* testsuite/t-values.scm (call-with-values): Add a test.
2008-11-01 18:37:48 +01:00
Andy Wingo
42906d7406 fix multiple values coming from interpreted or C procedures
* libguile/vm-i-system.c (call, goto/args): Handle the case in which a
  non-program (i.e. interpreted program or a subr) returns multiple
  values.

* testsuite/t-values.scm: Add test case that exhibited this problem.
2008-11-01 18:19:19 +01:00
Andy Wingo
3fd8807eab make-procedure-with-setter inherits name from getter
* libguile/procs.c (scm_make_procedure_with_setter): Patch through the
  getter's procedure name to the procedure-with-setter. Fixes part of the
  srfi-17 test, as the VM doesn't set procedure-name on define -- but
  perhaps that is the bug that should be fixed. In any case this patching
  is cheap.

* test-suite/tests/eval.test: Change so that (define name pws) is
  initially passed an anonymous procedure-with-setter, as was the case
  before the procs.c change.
2008-11-01 17:12:23 +01:00
Ludovic Courtès
627796347f Fix initialization of the SMOB GC "kind".
* libguile/smob.c (scm_smob_prehistory): When initializing
  SMOB_GC_KIND, pass 1 as the CLEAR_NEW_OBJECTS argument to
  `GC_new_kind ()'.  Without this, an assertion failure is
  triggered in libgc's `reclaim.c'.
2008-10-31 21:55:55 +01:00
Andy Wingo
1e4b834ab1 new ops: slot-ref, slot-set. remove and recompile your .go files
* libguile/vm-i-scheme.c (slot-ref, slot-set): New ops.
2008-10-31 14:09:01 +01:00
Andy Wingo
4631414e29 compile goops submodules, goops.test now passes again
* libguile/goops.c (get_slot_value, set_slot_value): While keeping the
  inlined getter/setter dispatch for closures, allow the getters and
  setters to be any kind of procedure.

* oop/goops.scm (compute-getters-n-setters): Relax the checks on
  getter/setter procedures, so that if a getter is a procedure but not a
  closure, we don't try to poke its arity.

* oop/goops/Makefile.am (SOURCES): Compile all the goops submodules!

* oop/goops/old-define-method.scm: Removed, in an act of housekeeping.

* oop/goops/compile.scm:
* oop/goops/dispatch.scm: Break a circular module dependency by making
  sure that (oop goops) is loaded when we go to compile submodules.

* oop/goops/compile.scm (compile-method/memoizer)
  (compile-method/memoizer+next): Allow a procedure without source
  through. This can happen with getter and setter lambdas that were
  compiled, and in that case there is no next-method call anyway. Ideally
  we should be able to specify compile-method for accessor methods...
2008-10-31 11:35:47 +01:00
Andy Wingo
fd7ac322a5 fix chaining up from interpreted to compiled methods; allow compiled init-thunk
* libguile/goops.c (scm_sys_initialize_object): Don't assume that an init
  thunk is a closure; just go through scm_call_0 instead.

* oop/goops/compile.scm (make-make-next-method/memoizer): Allow for the
  case that the next method is compiled.
2008-10-31 10:14:49 +01:00
Ludovic Courtès
47b6e9bd8e Don't invoke `on_thread_exit ()' from a pthread key destructor.
The `on_thread_exit ()' function allocates memory via libgc.  When
called from the context of a pthread key detructor, the thread is
essentially "dead" already and `GC_lookup_thread ()' returns NULL,
which triggers an assertion in libgc's `thread_local_alloc.c'.  This
patch arranges so that `on_thread_exit ()' is called from a suitable
context.

* libguile/threads.c (on_thread_exit): Remove now invalid comment
  about access to libgc's TLS.
  (init_thread_key): Don't pass `on_thread_exit ()' to
  `scm_i_pthread_key_create ()'.
  (scm_leave_guile_cleanup): Invoke `do_thread_exit ()'.
  (really_launch): Invoke `pthread_exit ()'.
2008-10-31 00:27:20 +01:00
Andy Wingo
05b37c17ff fix up some assumptions that cmethods were lists
* libguile/eval.i.c (type_dispatch, apply_vm_cmethod)
  (apply_memoized_cmethod): Tweak the nastiness a bit more so as to deal
  with the '(no-method) empty entries. I would like to stop the search if
  the cdr isn't a pair, but currently with the inlined memoized bits, the
  cdr is a pair. The fix would be to make the memoizer return a procedure
  and not the already-inlined bits -- slightly slower but the vm will be
  faster anyway.

* libguile/objects.c (scm_mcache_lookup_cmethod): Same fixes here.

* oop/goops/dispatch.scm (cache-hashval, cache-try-hash!): Allow non-list
  cmethod tails.
2008-10-30 15:50:48 +01:00
Andy Wingo
5487977b1b runtime byte compilation of goops methods, whooooo
* ice-9/boot-9.scm (make-modules-in): Change to make sure that we are
  making modules in modules; that is, that a global binding of `compile'
  doesn't prevent a module from importing a submodule named `compile'.
  (resolve-module): Clean up a bit, and serialize the logic.

* libguile/objects.c (scm_mcache_lookup_cmethod, scm_apply_generic):
* libguile/eval.i.c (CEVAL): Now that cmethod entries can have a program
  as their tail instead of a memoized proc, we have to change the halting
  condition on the method cache search, in both places: the one that's
  inlined into eval.i.c and the one in objects.c. If the cmethod isn't a
  pair, apply it.

* libguile/goops.c (make): In the `make' procedure that's used before
  GOOPS is booted, bind #:formals, #:body, and #:compile-env on methods.

* oop/goops/compile.scm (compute-entry-with-cmethod): There was a
  terrible trick here that involved putting a dummy pair in the cache,
  then modifying it in place with the result of memoization. The note
  claimed that this was to cut recursion short, or something. I can't see
  how it could recurse, given that `methods' is changing each time. Also,
  the pair trick doesn't work with byte-compiled methods. So, remove it.
  (compile-method): Dispatch to the appropriate method compiler, based on
  whether the method was defined with the interpreter or with the
  compiler.
  (make-next-method): New function, generically computes a `next-method'
  procedure, though the caller has to supply the arguments.
  (compile-method/vm): Exciting method byte compiler!
  (make-make-next-method/memoizer, compile-method/memoizer): Add the
  /memoizer suffix, and move all this code to the bottom of the file.
2008-10-30 13:42:40 +01:00
Andy Wingo
3de80ed52f recompiling with compile environments, fluid languages, cleanups
* ice-9/boot-9.scm (compile-time-environment): Remove definition from
  boot-9 -- instead, autoload it and `compile' from (system base
  compile).

* libguile/objcodes.h:
* libguile/objcodes.c (scm_objcode_to_program): Add an optional argument,
  `external', the external list to set on the returned program.

* libguile/vm-i-system.c (externals): New instruction, returns the
  external list. Only used by (compile-time-environment).

* libguile/vm.c (scm_load_compiled_with_vm): Adapt to
  scm_objcode_to_program change.

* module/language/scheme/translate.scm (translate): Actually pay
  attention to the environment passed as an argument.
  (custom-transformer-table): Expand out (compile-time-environment) to
  something that can be passed to `compile'.

* module/system/base/compile.scm (*current-language*): Instead of
  hard-coding `scheme' in various places, use a current language fluid,
  initialized to `scheme'.
  (compile-file, load-source-file): Adapt to *current-language*.
  (load-source-file): Ada
  (scheme-eval): Removed, no one used this.
  (compiled-file-name): Don't hard-code "scm" and "go"; instead use the
  %load-extensions and %load-compiled-extensions.
  (cenv-module, cenv-ghil-env, cenv-externals): Some accessors for
  compile-time environments.
  (compile-time-environment): Here we define (compile-time-environment)
  to something that will return #f; the compiler however produces
  different code as noted above.
  (compile): New function, compiles an expression into a thunk, then runs
  the thunk to get the value. Useful for procedures. The optional second
  argument can be either a module or a compile-time-environment; in the
  latter case, we can recompile even with lexical bindings.
  (compile-in): If the env specifies a module, set that module for the
  duration of the compilation.

* module/system/base/syntax.scm (%compute-initargs): Fix a bug where the
  default value for a field would always replace a user-supplied value.
  Whoops.

* module/system/il/ghil.scm (ghil-env-dereify): New function, takes the
  result of ghil-env-reify and turns it back into a GHIL environment.

* scripts/compile (compile): Remove some of the tricky error handling, as
  the library procedures handle this for us.

* test-suite/tests/compiler.test: Add a test for the dynamic compilation
  bits.
2008-10-30 10:57:36 +01:00
Ludovic Courtès
979172b656 Document the impossibility to call the GC from within `on_thread_exit ()'.
* libguile/threads.c (on_thread_exit): Add `FIXME' comment.
2008-10-28 09:52:51 +01:00
Neil Jerram
9c646eee43 Fix stack calibration-related errors when running make distcheck.
* libguile/Makefile.am (stack-limit-calibration.scm): Use $(srcdir), to
  support building in a different directory.
  (MOSTLYCLEANFILES): Add stack-limit-calibration.scm.
2008-10-26 21:45:33 +00:00
Andy Wingo
21497600d2 add formals', body', and `compile-env' slots to <method>
* ice-9/boot-9.scm (compile-time-environment): Return #f instead of
  erroring under the interpreter, a bit more sane.

* libguile/goops.c (create_standard_classes):
* libguile/goops.h (scm_si_formals, scm_si_body, scm_si_compile_env):
* oop/goops.scm (method, initialize): Add `formals', `body', and
  `compile-env' slots to <method>.
2008-10-25 22:58:48 +02:00
Neil Jerram
7776113a28 Add measure-hwm.scm to the set of distribution files.
* libguile/Makefile.am (EXTRA_DIST): Add measure-hwm.scm.
2008-10-24 23:14:20 +01:00
Neil Jerram
f9d44e8476 Fix hang in srfi-18.test
* libguile/threads.h (held_mutex): New field.

	* libguile/threads.c (enqueue, remqueue, dequeue): Use critical
	section to protect access to the queue.
	(guilify_self_1): Initialize held_mutex field.
	(on_thread_exit): If held_mutex non-null, unlock it.
	(fat_mutex_unlock, fat_cond_free, scm_make_condition_variable,
	fat_cond_signal, fat_cond_broadcast): Delete now unnecessary uses
	of c->lock.
	(fat_mutex_unlock): Pass m->lock to block_self() instead of
	c->lock; move scm_i_pthread_mutex_unlock(m->lock) call from before
	block_self() to after.
	(scm_pthread_cond_wait, scm_pthread_cond_timedwait,
	scm_i_thread_sleep_for_gc): Set held_mutex before pthread call;
	reset it afterwards.

I was seeing a hang in srfi-18.test, when running make check in master,
in the "exception handler installation is thread-safe" test.  It wasn't
100% reproducible, so looked like a race.

The problem is that wait-condition-variable is not actually
atomic in the way that it is supposed to be.  It unlocks the mutex,
then starts waiting on the cond var.  So it is possible for another
thread to lock the same mutex, and signal the cond var, before the
wait-condition-variable thread starts waiting.

In order for wait-condition-variable to be atomic - e.g. in a race
where thread A holds (Scheme-level) mutex M, and calls
(wait-condition-variable C M), and thread B calls (begin (lock-mutex
M) (signal-condition-variable C)) - it needs to call pthread_cond_wait
with the same underlying mutex as is involved in the `lock-mutex'
call.  In terms of the threads.c code, this means that it has to use
M->lock, not C->lock.

block_self() used its mutex arg for two purposes: for protecting
access and changes to the wait queue, and for the pthread_cond_wait
call.  But it wouldn't work reliably to use M->lock to protect C's
wait queue, because in theory two threads can call
(wait-condition-variable C M1) and (wait-condition-variable C M2)
concurrently, with M1 and M2 different.  So we either have to pass
both C->lock and M->lock into block_self(), or use some other mutex to
protect the wait queue.  For this patch, I switched to using the
critical section mutex, because that is a global and so easily
available.  (If that turns out to be a problem for performance, we
could make each queue structure have its own mutex, but there's no
reason to believe yet that it is a problem, because the critical
section mutex isn't used much overall.)

So then we call block_self() with M->lock, and move where M->lock is
unlocked to after the block_self() call, instead of before.

That solves the first hang, but introduces a new one, when a SRFI-18
thread is terminated (`thread-terminate!') between being launched
(`make-thread') and started (`thread-start!').  The problem now is
that pthread_cond_wait is a cancellation point (see man
pthread_cancel), so the pthread_cond_wait call is one of the few
places where a thread-terminate! call can take effect.  If the thread
is cancelled at that point, M->lock ends up still being locked, and
then when do_thread_exit() tries to lock M->lock again, it hangs.

The fix for that is a new `held_mutex' field in scm_i_thread, which is
set to point to the mutex just before a pthread_cond_(timed)wait call,
and set to NULL again afterwards.  If on_thread_exit() finds that
held_mutex is non-NULL, it unlocks that mutex.

A detail is that checking and unlocking held_mutex must be done before
on_thread_exit() calls scm_i_ensure_signal_delivery_thread(), because
the innards of scm_i_ensure_signal_delivery_thread() can do another
pthread_cond_wait() call and so overwrite held_mutex.  But that's OK,
because it's fine for the mutex check and unlock to happen outside
Guile mode.

Lastly, C->lock is then not needed, so I've removed it.
2008-10-24 22:08:59 +01:00
Neil Jerram
d2a510879b Fix hang in srfi-18.test
* libguile/threads.h (held_mutex): New field.

	* libguile/threads.c (enqueue, remqueue, dequeue): Use critical
	section to protect access to the queue.
	(guilify_self_1): Initialize held_mutex field.
	(on_thread_exit): If held_mutex non-null, unlock it.
	(fat_mutex_unlock, fat_cond_free, scm_make_condition_variable,
	fat_cond_signal, fat_cond_broadcast): Delete now unnecessary uses
	of c->lock.
	(fat_mutex_unlock): Pass m->lock to block_self() instead of
	c->lock; move scm_i_pthread_mutex_unlock(m->lock) call from before
	block_self() to after.
	(scm_pthread_cond_wait, scm_pthread_cond_timedwait,
	scm_i_thread_sleep_for_gc): Set held_mutex before pthread call;
	reset it afterwards.

I was seeing a hang in srfi-18.test, when running make check in master,
in the "exception handler installation is thread-safe" test.  It wasn't
100% reproducible, so looked like a race.

The problem is that wait-condition-variable is not actually
atomic in the way that it is supposed to be.  It unlocks the mutex,
then starts waiting on the cond var.  So it is possible for another
thread to lock the same mutex, and signal the cond var, before the
wait-condition-variable thread starts waiting.

In order for wait-condition-variable to be atomic - e.g. in a race
where thread A holds (Scheme-level) mutex M, and calls
(wait-condition-variable C M), and thread B calls (begin (lock-mutex
M) (signal-condition-variable C)) - it needs to call pthread_cond_wait
with the same underlying mutex as is involved in the `lock-mutex'
call.  In terms of the threads.c code, this means that it has to use
M->lock, not C->lock.

block_self() used its mutex arg for two purposes: for protecting
access and changes to the wait queue, and for the pthread_cond_wait
call.  But it wouldn't work reliably to use M->lock to protect C's
wait queue, because in theory two threads can call
(wait-condition-variable C M1) and (wait-condition-variable C M2)
concurrently, with M1 and M2 different.  So we either have to pass
both C->lock and M->lock into block_self(), or use some other mutex to
protect the wait queue.  For this patch, I switched to using the
critical section mutex, because that is a global and so easily
available.  (If that turns out to be a problem for performance, we
could make each queue structure have its own mutex, but there's no
reason to believe yet that it is a problem, because the critical
section mutex isn't used much overall.)

So then we call block_self() with M->lock, and move where M->lock is
unlocked to after the block_self() call, instead of before.

That solves the first hang, but introduces a new one, when a SRFI-18
thread is terminated (`thread-terminate!') between being launched
(`make-thread') and started (`thread-start!').  The problem now is
that pthread_cond_wait is a cancellation point (see man
pthread_cancel), so the pthread_cond_wait call is one of the few
places where a thread-terminate! call can take effect.  If the thread
is cancelled at that point, M->lock ends up still being locked, and
then when do_thread_exit() tries to lock M->lock again, it hangs.

The fix for that is a new `held_mutex' field in scm_i_thread, which is
set to point to the mutex just before a pthread_cond_(timed)wait call,
and set to NULL again afterwards.  If on_thread_exit() finds that
held_mutex is non-NULL, it unlocks that mutex.

A detail is that checking and unlocking held_mutex must be done before
on_thread_exit() calls scm_i_ensure_signal_delivery_thread(), because
the innards of scm_i_ensure_signal_delivery_thread() can do another
pthread_cond_wait() call and so overwrite held_mutex.  But that's OK,
because it's fine for the mutex check and unlock to happen outside
Guile mode.

Lastly, C->lock is then not needed, so I've removed it.
2008-10-24 21:51:47 +01:00
Ludovic Courtès
7f9ec18a1f Expose `GC_dump ()' at the Scheme level.
* libguile/gc.h (scm_gc_dump): New declaration.

* libguile/gc.c (scm_gc_dump): New function.
2008-10-23 17:46:08 +02:00