Hey Hey, Ho Ho, libco has got to go
libco
is awkward, has too many backends to maintain, and there are no really clear speed advantages using the amd64.c
backend over sjlj.c
or even ucontext.c
in most cases on my Alpine x86_64 system (musl libc, libucontext):
Super Mario World - 5000 frames
amd64.c : called 5 times, best result: 27.0883s, avg: 29.0407s, total: 147.0036s
sjlj.c : called 5 times, best result: 27.0283s, avg: 29.0067s, total: 145.0338s
ucontext.c : called 5 times, best result: 27.0282s, avg: 27.0303s, total: 136.0516s
Hayazashi Nidan Morita Shougi 2 - 2500 frames
amd64.c : called 5 times, best result: 29.0890s, avg: 30.0014s, total: 150.0071s
sjlj.c : called 5 times, best result: 30.0861s, avg: 31.0167s, total: 155.0835s
ucontext.c : called 5 times, best result: 30.0813s, avg: 30.0975s, total: 154.0878s
Super Castlevania IV - 5000 frames
amd64.c : called 5 times, best result: 26.0590s, avg: 26.0704s, total: 133.0522s
sjlj.c : called 5 times, best result: 26.0083s, avg: 26.0183s, total: 130.0916s
ucontext.c : called 5 times, best result: 26.0880s, avg: 26.0902s, total: 134.0514s
Doom - 2500 frames
amd64.c : called 5 times, best result: 20.0582s, avg: 20.0699s, total: 103.0496s
sjlj.c : called 5 times, best result: 21.0475s, avg: 21.0674s, total: 108.0374s
ucontext.c : called 5 times, best result: 21.0373s, avg: 21.0494s, total: 107.0474s
Mega Man X3 - 2500 frames
amd64.c : called 5 times, best result: 14.0555s, avg: 14.0557s, total: 72.0789s
sjlj.c : called 5 times, best result: 14.0355s, avg: 14.0356s, total: 71.0783s
ucontext.c : called 5 times, best result: 14.0455s, avg: 14.0476s, total: 72.0382s
Mega Man X3 LLE - 2500 frames
amd64.c : called 5 times, best result: 20.0065s, avg: 20.0133s, total: 100.0667s
sjlj.c : called 5 times, best result: 21.0675s, avg: 21.0839s, total: 109.0196s
ucontext.c : called 5 times, best result: 20.0372s, avg: 20.0516s, total: 102.0582s
At the time of this issue's creation, sjlj
and ucontext
both have problems which were inherited from the original codebase, and can be observed there as well as in the libretro port:
- sjlj: segfaults on reset, segfaults on state loading
- ucontext: segfaults on exit if a reset or state load has been performed
A replacement is required. Whether this will be an all-inclusive libco backend that is standards-compliant, or a total replacement is yet to be determined.
Possible solutions:
- Fix sjlj or ucontext backends
- Use a different coroutine library which is more architecture/OS independent (or at least hides the gory details and is well maintained)
- ideally not C++20 coroutines as this is now a C++11 codebase
- Switch to pthreads -- a longshot with some major implications
Edited by Rupert Carmichael