Re: A fix for SBCL error "thread local storage exhausted" when creating too many rules

David Scherfgen via Maxima-discuss <[email protected]> Sun, 7 Jun 2026 15:24:50 +0200
Newsgroups gmane.comp.mathematics.maxima.general
Message-ID <CAMTHLKiX4hn3uifFwLcuJyAhrYWu96qtABMyK-9Ng4_v+LspMw@mail.gmail.com>
Hi Michel,

Thanks for looking into this and sharing your experiment! You are right
about how special variables behave, but we have to make a distinction
between executing rules and creating/destroying them.

Because dynamically bound special variables are indeed thread-local,
executing existing rules or functions in parallel is generally safe. When a
thread executes a rule, the Lisp system dynamically binds those generated
symbols strictly within that thread's local environment, without
interfering with other threads. In fact, SBCL's mechanism of assigning a
Thread-Local Storage (TLS) index to these special variables is exactly what
guarantees this isolation.

Regarding the new *rule-symbol-pool*, you are correct that it introduces
shared state (it's not dynamically bound, it's a "global variable"). If two
threads were to define or destroy rules concurrently, they would race on
the pool. I could wrap the pool in a standard mutex, but the reality is
that creating or destroying rules concurrently would break Maxima even
without my patch.

Currently, rule creation and destruction heavily mutate global state that
is not shared safely between threads. For instance, defrule and tellsimp
destructively modify global lists like $rules, and they write directly to
symbol property lists. Similarly, concurrent modifications to the
facts/assume database would inevitably corrupt the environment. There are
many places like this in the codebase that currently prevent Maxima from
working correctly if multiple threads are mutating the environment at the
same time.

So, while parallel evaluation without global side effects can work nicely
as your experiment shows, parallel mutation of the environment is already
unsafe, and I reckon it would be a "nightmare" to find and fix every
thread-unsafe access to some global state, whether it's a global variable
or some symbol property list.

As for increasing the TLS limit: While adjusting the --tls-limit parameter
in SBCL pushes the ceiling higher, it's ultimately only a delay of the
inevitable for certain workflows. Because SBCL never reclaims a TLS slot
once a symbol has been dynamically bound, a long-running Maxima session
that programmatically defines and removes rules in a loop will eventually
exhaust any limit we set.

By recycling the symbols, we permanently cap the TLS consumption to the
maximum number of rules that exist at any one time, completely eliminating
the leak without restricting parallel execution of those rules.

Best regards,
David

Michel Talon <[email protected]> schrieb am So., 7. Juni
2026, 15:04:

> I am not sure that using threads in maxima is radically impossible. I have
> made a small experiment that you can see here:
>
>
> https://github.com/maxima-project-on-github/maxima-packages/tree/master/mtalon/maxima-parallel
> /distribute_over_tranches_thread.lisp
> <https://github.com/maxima-project-on-github/maxima-packages/blob/master/mtalon/maxima-parallel/distribute_over_tranches_thread.lisp>
>
> This seems to work. I have even tried with a collection of partfrac
> invocations, which notoriously use the global variable var (perhaps *var*
> nowadays) to communicate the main var between various functions, and it
> worked OK. So probably all those special variables are in thread local
> storage, and don't interfere between threads. As far as the problem of
> local storage exhaustion is concerned i think it is no big deal since one
> can easily increase the size of thread local storage in sbcl
>
> https://sourceforge.net/p/maxima/mailman/message/59161071/
>
> https://sourceforge.net/p/maxima/mailman/message/59160998/
>
> Personnally i have already increased tls-limit in the script "maxima" to
> get rid of such problems. Of course you can solve it for maxima rules, but
> it may reappear elsewhere, and the solution may cause problems to run
> maxima threaded programs.
>
>
>
> Le 07/06/2026 à 11:01, David Scherfgen via Maxima-discuss a écrit :
>
> Hi Gunter,
>
> If we ever try to make Maxima thread-safe, then we need to protect the
> access to *rule-symbol-pool* using a mutex.
> To be honest, I doubt that'll happen, though. There's so much "global
> state" in Maxima that's shared between threads.
>
> Best regards
> David
>
> --
> Michel Talon
>
>

_______________________________________________
Maxima-discuss mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/maxima-discuss