Closed ghost closed 4 years ago
Quite possibly there is a different syntax here that is required?
There are two errors here: first errno
is some kind of variable, not a function, so it is not directly accessible via the primitive mechanism of the Keiko machine. Second, errno
is actually defined as a macro in the C library, and "man errno" sternly warns us to "#include <errno.h>"
and not try writing our own extern
declaration for it.
The error message you're getting refers to TLS, which in this context means Thread Local Storage, not Transport Layer Security. In fact, errno
is defined in the GNU C library as
# define errno (*__errno_location ())
This use of a global variable is, of course, a wart on the design of the C library that becomes painful as soon as multiple threads enter the picture.
The simple and portable solution is to introduce a simple C function get_errno
, defined by
#include <errno.h>
int get_errno(void) { return errno; }
and then arrange to call that function as a primitive from Oberon. Other solutions (such as exposing the function __errno_location
) are not likely to work because on amd64 that function will return a 64-bit pointer that is not addressible from the Keiko virtual machine.
Thanks so much Mike. I'll close this issue and update my project accordingly. It lives here and seems to be running well enough. It needs a lot more work to be considered safe and sound for more than localhost use as a learning project. I'll update it with get_errno
as you suggest.
Looking at your project, it's as I suspected: you've managed to live without adding C code so far, but this change will drive you to use -C and link a custom runtime every time. Since errno
is guaranteed by ISO C, I see no reason not to add get_errno
as above as an unused support routine in the runtime. I've done that and pushed a new revision. Sadly, the actual values of errno
are not guaranteed to be consistent between platforms, and that affects portability.
You should be careful, by the way, with any routine (such as fopen
for example) that allocates and returns a pointer to storage. Typically, such storage will not be addressible from Keiko. There are things we can do about that if the need arises.
I've done as you suggested and created a simple errno.c
containing a get_errno
implementation and linked it using -C. Thanks again. Working with Oberon-2 is a great pleasure. I look forward to your forthcoming Oberon-64 implementation which I presume will be the canonical 64-bit implementation. :wink:
On amd64, the JIT already uses the extended register set and SSE for floating point. The only thing that is not 64-bit is the heap, which uses 32-bit pointers. There's a good reason for that, the same reason why both Lua and the most common VMs for Java use 32-bit pointers: it is because interpreting 64-bit pointers would seriously slow down the garbage collector. Google "Java compressed object pointers" to understand the issues.
Attempting to surface the C primitive
errno
as procedure fails to link. The following output is produced:The error is reproducible via the following code :
PROCEDURE err(): INTEGER IS "errno";