If I understood Duane Rettig's response correctly, when a thread binds a special variable using a let, that binding is only visible for that particular thread. Is this how other Lisps behave?
With that in mind, in order to make with-errno work, the foreign function call expression would have to be identified and bound with a let. So something like this:
(defmacro with-errno (&body body)
(let ((exprs-before-ffc ...)
(ffc-expression ..)
(exprs-after-ffc ..))
`,@exprs-before-ffc
(let ((errno ,ffc-expression))
,@(exprs-after-ffc))))
There's some complications such as, how to determine which expression is a foreign function call since defcfun can assign any arbitrary name. There's also the issue of what should the foreign function call return? It seems like it would have to return errno as the last value.
To mitigate the first concern, perhaps a more explicit interface would help:
(with-foreign-funcall-errno (result errno (foreign-funcall "strlen" ...))
...)
You mentioned that a foreign function call could return errno as the first value, how about returning it as the last?
Another alternative is to optimize the way synchronization is done, so that we could improve the thread-local code I wrote before.