-
Notifications
You must be signed in to change notification settings - Fork 37
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
multithreaded uLisp #74
Comments
That sounds an exciting idea. Are you sure it will be possible to make uLisp multithreaded? I'm not sure I would want to adopt this for the standard version of uLisp, because I don't want to start having features that are exclusive to one platform. However, as I said for your other suggestion, if you would like to do a FreeRTOS fork of uLisp I'd be very interested to try it out, and promote it on the forum. |
I already did find that someone on the forum was able to run uLisp in its own freeRTOS task (http://forum.ulisp.com/t/ulisp-as-freertos-task/1126), but that was still only one task; the other tasks have to be done in C. TBH I think as long as you keep all of the uLisp tasks pinned to the same core (on 2-core ESPs), then because two tasks can't run at the same time on the same core, there won't be any garbage collector corruptions as long as it can mark all the tasks. I do want to try out freeRTOS tasks, and honestly I think it would be a good exercise to implement a Unfortunately it's AP test season, and I have two, so I won't be able to test this anytime soon. |
OK, there's no urgency. I hope your AP tests go well! |
I got to thinking about this a little more lately and I don't actually think that any C code changes would be necessary. The way it would work is that there would be a function/macro that would transform a standard lambda body into a coroutine by adding a parameter called I'm not well-versed on continuation-passing style, but from what I've read about it it seems like it is what is needed here. I assume that someone more-well-versed in Lisp would know about how this kind of stuff is actually pulled off or if it is even possible. Just an idea. |
The problem is that the routines in uLisp aren't currently written to be reentrant. There are global variables, such as Another problem is garbage collection. I'm not sure what would happen if one thread invoked a garbage collection while a second thread was executing, or worse, what would happen if two threads both invoked garbage collection at the same time! |
Well, that would be the problem inherent with the multiple-FreeRTOS-threads approach. The continuation-passing approach still only uses one thread and AFAIK it can be done in pure Lisp, so it wouldn't need any sort of reentrant routines on the C API side. I'm not sure whether infinite-continuations would blow up the stack or not, but considering that continuation-passing is common practice in Scheme and both uLisp and all R5RS-compliant implementations of Scheme have tail-call optimization (meaning looping via infinite recursion is possible), so it may not affect much. |
Hmmm... interesting. I'll need to think about that. |
Wikipedia has some Scheme code that implements cooperative multitasking here. Once uLisp has macros I think that would make it a lot easier to port. |
On a second look, while macros would make it easier, it relies on But to make it easier to make such extensions possible to causal hackers like me, I think adding a third -typedef object *(*fn_ptr_type)(object *, object *);
+typedef object *(*fn_ptr_type)(object *, object *, void *); In stock uLisp it would do absolutely nothing but be passed around to the other functions (and would mostly be I'm busy applying to universities right now, but if I get a free moment here and there I'm going to try to add it into my fork of ulisp-builder. |
Great! And good luck with the university applications. |
I had another idea that would require editing the uLisp source (i.e. not an extension): making the multithreading feature of the esp32's FreeRTOS available to uLisp. I wish it was also available on Teensy too but there aren't any good libraries for that. You could (ab)use
setjmp()
/longjmp()
to switch contexts but I'm not sure how well that would work.To be able to preserve the atomic nature of garbage collections, the garbage collector can't call
yield()
and must have some way to mark all the running threads.The changes would look something like this
And then any of the functions that refer to global variables, could instead look in the
Then you could implement functions like
(spawn)
,(send)
,(receive)
, and(kill)
for threads to be started and stopped and for them to communicate between each other.The text was updated successfully, but these errors were encountered: