Mark all forward declarations as `{.gcsafe.}` to ensure the compiler checks the proc bodies for gc-safeness.
All global variables are now marked as `{.threadvar.}` to ensure they are thread-local, the values of which are not copied during thread creation, thus requiring the remaining changes.
When a new thread is created, the thread-local (`{.threadvar.}`) vars are not intialised and the global proc calls are not called, which, in our case was just `init_edn_readers()`. To workaround this, another variable, `initialised`, was created to keep track of whether or not the initialisation had occured. It will have occurred in the main thread, but would not have occured subsequently created threads. Every time `read` is called, we check if initialisation hasn’t yet happened, in which case we initialise it. Very similar to a singleton pattern.