Some implementation details

Here are some details about the implementation which might be interesting, although they do not affect the ISO-defined semantics of the library.

  • It is possible to configure eCos to have the standard C library without the kernel. You might want to do this to use less memory.

  • The opaque type returned by clock() is called clock_t, and is implemented as a 64 bit integer. The value returned by clock() is only correct if the kernel is configured with real-time clock support, as determined by the CYGVAR_KERNEL_COUNTERS_CLOCK configuration option in kernel.h .

  • The FILE type is not implemented as a structure, but rather as a CYG_ADDRESS.

  • The GNU C compiler will replace its own built-in implementations instead of calls to some C library functions. This can be turned off with the -fno-builtin option. But it is recommended for normal use to leave compiler builtins enabled. The functions affected by this are described in the documentation associated with the particular GNU compiler version you are using, but include at least: abs() , cos() , fabs() , labs() , memcmp() , memcpy() , sin() , sqrt() , strcmp() , strcpy() , and strlen() .

  • memcpy() and memset() are located in the infrastructure package, not in the C library package. This is because the compiler calls these functions, and the kernel needs to resolve them even if the C library is not configured.

  • Error codes such as EDOM and ERANGE, as well as strerror() , are implemented in the error package. The error package is separate from the rest of the C and math libraries so that the rest of eCos can use these error handling facilities even if the C library is not configured.

  • The memory allocation package CYGPKG_MEMALLOC is responsible for providing the various heap management functions such as malloc(), free(), etc.

  • Signals, as implemented by <signal.h>, are guaranteed to work correctly if raised using the raise() function from a normal working program context. Using signals from within an ISR or DSR context is not expected to work. Also, it is not guaranteed that if CYGSEM_LIBC_SIGNALS_HWEXCEPTIONS is set, that handling a signal using signal() will necessarily catch that form of exception. For example, it may be expected that a divide-by-zero error would be caught by handling SIGFPE. However it depends on the underlying HAL implementation to implement the required hardware exception. And indeed the hardware itself may not be capable of detecting these exceptions so it may not be possible for the HAL implementer to do this in any case. Despite this lack of guarantees in this respect, the signals implementation is still ISO C compliant since ISO C does not offer any such guarantees either.

  • If you include the POSIX compatibility layer in your configuration, by default it will present a conflict if the C library signals implementation is also present. Only one signals implementation may be present.

  • The getenv() function is implemented (as long as the CYGPKG_LIBC_STDLIB package is present in your configuration), but there is no shell or putenv() function to set the environment dynamically. The environment is set in a global variable environ, declared as:

    extern char **environ; // Standard environment definition

    If the "ISO environment startup/termination" (CYGPKG_LIBC_STARTUP) package is included in your configuration, the environment can be statically initialized at startup time using the CYGDAT_LIBC_DEFAULT_ENVIRONMENT option. If so, remember that the final entry of the array initializer must be NULL.

Here is a minimal eCos program which demonstrates the use of environments (see also the test case in language/c/libc/VERSION/tests/stdlib/getenv.c):

#include <stdio.h>
#include <stdlib.h> // Main header for stdlib functions

extern char **environ; // Standard environment definition

int
main( int argc, char *argv[] )
{
 char *str;
 char *env[] = { "PATH=/usr/local/bin:/usr/bin",
 "HOME=/home/fred",
 "TEST=1234=5678",
 "home=hatstand",
 NULL };

 printf("Display the current PATH environment variable\n");

 environ = (char **)&env;

 str = getenv("PATH");

 if (str==NULL) {
  printf("The current PATH is unset\n");
 } else {
  printf("The current PATH is \"%s\"\n", str);
 }
 return 0;
} 
2017-02-09
Documentation license for this page: Open Publication License