Home | History | Annotate | Download | only in docs
      1 Bionic C Library Overview:
      2 ==========================
      3 
      4 Introduction:
      5 
      6 Core Philosophy:
      7 
      8   The core idea behind Bionic's design is: KEEP IT REALLY SIMPLE.
      9 
     10   This implies that the C library should only provide lightweight wrappers
     11   around kernel facilities and not try to be too smart to deal with edge cases.
     12 
     13   The name "Bionic" comes from the fact that it is part-BSD and part-Linux:
     14   its source code consists in a mix of BSD C library pieces with custom
     15   Linux-specific bits used to deal with threads, processes, signals and a few
     16   others things.
     17 
     18   All original BSD pieces carry the BSD copyright disclaimer. Bionic-specific 
     19   bits carry the Android Open Source Project copyright disclaimer. And
     20   everything is released under the BSD license.
     21 
     22 Architectures:
     23 
     24   Bionic currently supports the ARM and x86 instruction sets. In theory, it
     25   should be possible to support more, but this may require a little work (e.g.
     26   adding system call IDs to SYSCALLS.TXT, described below, or modifying the
     27   dynamic linker).
     28 
     29   The ARM-specific code is under arch-arm/ and the x86-specific one is under
     30   arch-x86/
     31 
     32   Note that the x86 version is only meant to run on an x86 Android device. We
     33   make absolutely no claim that you could build and use Bionic on a stock x86
     34   Linux distribution (though that would be cool, so patches are welcomed :-))
     35 
     36 Syscall stubs:
     37 
     38   Each system call function is implemented by a tiny assembler source fragment
     39   (called a "syscall stub"), which is generated automatically by
     40   tools/gensyscalls.py which reads the SYSCALLS.TXT file for input.
     41 
     42   SYSCALLS.TXT contains the list of all syscall stubs to generate, along with
     43   the corresponding syscall numeric identifier (which may differ between ARM
     44   and x86), and its signature
     45 
     46   If you modify this file, you may want to use tools/checksyscalls.py which
     47   checks its content against official Linux kernel header files, and will
     48   report errors when invalid syscall ids are used.
     49 
     50   Sometimes, the C library function is really a wrapper that calls the
     51   corresponding syscall with another name. For example, the exit() function
     52   is provided by the C library and calls the _exit() syscall stub.
     53 
     54   See SYSCALLS.TXT for documentation and details.
     55 
     56 
     57 time_t:
     58 
     59   time_t is 32-bit as defined by the kernel on 32-bit CPUs. A 64-bit version
     60   would be preferrable to avoid the Y2038 bug, but the kernel maintainers
     61   consider that this is not needed at the moment.
     62 
     63   Instead, Bionic provides a <time64.h> header that defines a time64_t type,
     64   and related functions like mktime64(), localtime64(), etc...
     65 
     66   strftime() uses time64_t internally, so the '%s' format (seconds since the
     67   epoch) is supported for dates >= 2038.
     68 
     69 
     70 strftime_tz():
     71 
     72   Bionic also provides the non-standard strftime_tz() function, a variant
     73   of strftime() which also accepts a time locale descriptor as defined
     74   by "struct strftime_locale" in <time.h>.
     75 
     76   This function is used by the low-level framework code in Android.
     77 
     78 
     79 Timezone management:
     80 
     81   The name of the current timezone is taken from the TZ environment variable,
     82   if defined. Otherwise, the system property named 'persist.sys.timezone' is
     83   checked instead.
     84 
     85   The zoneinfo timezone database and index files are located under directory
     86   /system/usr/share/zoneinfo, instead of the more Posix-compliant path of
     87   /usr/share/zoneinfo
     88 
     89 
     90 off_t:
     91 
     92   For similar reasons, off_t is 32-bit. We define loff_t as the 64-bit variant
     93   due to BSD inheritance, but off64_t should be available as a typedef to ease
     94   porting of current Linux-specific code.
     95 
     96 
     97 Linux kernel headers:
     98 
     99   Bionic comes with its own set of "clean" Linux kernel headers to allow
    100   user-space code to use kernel-specific declarations (e.g. IOCTLs, structure
    101   declarations, constants, etc...). They are located in:
    102 
    103      ./kernel/common,
    104      ./kernel/arch-arm
    105      ./kernel/arch-x86
    106 
    107   These headers have been generated by a tool (kernel/tools/update-all.py) to
    108   only include the public definitions from the original Linux kernel headers.
    109 
    110   If you want to know why and how this is done, read kernel/README.TXT to get
    111   all the (gory) details.
    112 
    113 
    114 PThread implementation:
    115 
    116    Bionic's C library comes with its own pthread implementation bundled in.
    117    This is different from other historical C libraries which:
    118 
    119     - place it in an external library (-lpthread)
    120     - play linker tricks with weak symbols at dynamic link time
    121 
    122    The support for real-time features (a.k.a. -lrt) is also bundled in the
    123    C library.
    124 
    125    The implementation is based on futexes and strives to provide *very* short
    126    code paths for common operations. Notable features are the following:
    127 
    128       - pthread_mutex_t, pthread_cond_t are only 4 bytes each.
    129 
    130       - Normal, recursive and error-check mutexes are supported, and the code
    131         path is heavily optimized for the normal case, which is used most of
    132         the time.
    133 
    134       - Process-shared mutexes and condition variables are not supported.
    135         Their implementation requires far more complexity and was absolutely
    136         not needed for Android (which uses other inter-process synchronization
    137         capabilities).
    138 
    139         Note that they could be added in the future without breaking the ABI
    140         by specifying more sophisticated code paths (which may make the common
    141         paths slightly slower though).
    142 
    143       - There is currently no support for read/write locks, priority-ceiling in
    144         mutexes and other more advanced features. Again, the main idea being
    145         that this was not needed for Android at all but could be added in the
    146         future.
    147 
    148 pthread_cancel():
    149 
    150    pthread_cancel() will *not* be supported in Bionic, because doing this would
    151    involve making the C library significantly bigger for very little benefit.
    152 
    153    Consider that:
    154 
    155      - A proper implementation must insert pthread cancellation checks in a lot
    156        of different places of the C library. And conformance is very difficult
    157        to test properly.
    158 
    159      - A proper implementation must also clean up resources, like releasing
    160        memory, or unlocking mutexes, properly if the cancellation happens in a
    161        complex function (e.g. inside gethostbyname() or fprintf() + complex
    162        formatting rules). This tends to slow down the path of many functions.
    163 
    164      - pthread cancellation cannot stop all threads: e.g. it can't do anything
    165        against an infinite loop
    166 
    167      - pthread cancellation itself has short-comings and isn't very portable
    168        (see http://advogato.org/person/slamb/diary.html?start=49 for example).
    169 
    170    All of this is contrary to the Bionic design goals. If your code depends on
    171    thread cancellation, please consider alternatives.
    172 
    173    Note however that Bionic does implement pthread_cleanup_push() and
    174    pthread_cleanup_pop(), which can be used to handle cleanups that happen when
    175    a thread voluntarily exits through pthread_exit() or returning from its
    176    main function.
    177 
    178 
    179 pthread_once():
    180 
    181   Do not call fork() within a callback provided to pthread_once(). Doing this
    182   may result in a deadlock in the child process the next time it calls
    183   pthread_once().
    184 
    185   Also, you can't throw a C++ Exception from the callback (see C++ Exception
    186   Support below).
    187 
    188   The current implementation of pthread_once() lacks the necessary support of
    189   multi-core-safe double-checked-locking (read and write barriers).
    190 
    191 
    192 Thread-specific data
    193 
    194   The thread-specific storage only provides for a bit less than 64
    195   pthread_key_t objects to each process. The implementation provides 64 real
    196   slots but also uses about 5 of them (exact number may depend on
    197   implementation) for its own use (e.g. two slots are pre-allocated by the C
    198   library to speed-up the Android OpenGL sub-system).
    199 
    200   Note that Posix mandates a minimum of 128 slots, but we do not claim to be
    201   Posix-compliant.
    202 
    203   Except for the main thread, the TLS area is stored at the top of the stack.
    204   See comments in bionic/libc/bionic/pthread.c for details.
    205 
    206   At the moment, thread-local storage defined through the __thread compiler
    207   keyword is not supported by the Bionic C library and dynamic linker.
    208 
    209 
    210 Multi-core support
    211 
    212   At the moment, Bionic does not provide or use read/write memory barriers.
    213   This means that using it on certain multi-core systems might not be
    214   supported, depending on its exact CPU architecture.
    215 
    216 
    217 Android-specific features:
    218 
    219   Bionic provides a small number of Android-specific features to its clients:
    220 
    221   - access to system properties:
    222 
    223        Android provides a simple shared value/key space to all processes on the
    224        system. It stores a liberal number of 'properties', each of them being a
    225        simple size-limited string that can be associated to a size-limited
    226        string value.
    227 
    228        The header <sys/system_properties.h> can be used to read system
    229        properties and also defines the maximum size of keys and values.
    230 
    231    - Android-specific user/group management:
    232 
    233        There is no /etc/passwd or /etc/groups in Android. By design, it is
    234        meant to be used by a single handset user. On the other hand, Android
    235        uses the Linux user/group management features extensively to secure
    236        process permissions, like access to various filesystem directories.
    237 
    238        In the Android scheme, each installed application gets its own
    239        uid_t/gid_t starting from 10000; lower numerical ids are reserved for
    240        system daemons.
    241 
    242        getpwnam() recognizes some hard-coded subsystems names (e.g. "radio")
    243        and will translate them to their low-user-id values. It also recognizes
    244        "app_1234" as the synthetic name of the application that was installed
    245        with uid 10000 + 1234, which is 11234. getgrnam() works similarly
    246 
    247        getgrouplist() will always return a single group for any user name,
    248        which is the one passed as an input parameter.
    249 
    250        getgrgid() will similarly only return a structure that contains a
    251        single-element members list, corresponding to the user with the same
    252        numerical value than the group.
    253 
    254        See bionic/libc/bionic/stubs.c for more details.
    255 
    256     - getservent()
    257 
    258        There is no /etc/services on Android. Instead the C library embeds a
    259        constant list of services in its executable, which is parsed on demand
    260        by the various functions that depend on it. See
    261        bionic/libc/netbsd/net/getservent.c and
    262        bionic/libc/netbsd/net/services.h
    263 
    264        The list of services defined internally might change liberally in the
    265        future. This feature is mostly historically and is very rarely used.
    266 
    267        The getservent() returns thread-local data. getservbyport() and
    268        getservbyname() are also implemented in a similar fashion.
    269 
    270      - getprotoent()
    271 
    272        There is no /etc/protocol on Android. Bionic does not currently
    273        implement getprotoent() and related functions. If added, it will
    274        likely be done in a way similar to getservent()
    275 
    276 DNS resolver:
    277 
    278   Bionic uses a NetBSD-derived resolver library which has been modified in
    279   the following ways:
    280 
    281      - don't implement the name-server-switch feature (a.k.a. <nsswitch.h>)
    282 
    283      - read /system/etc/resolv.conf instead of /etc/resolv.conf
    284 
    285      - read the list of servers from system properties. the code looks for
    286        'net.dns1', 'net.dns2', etc.. Each property should contain the IP
    287        address of a DNS server.
    288 
    289        these properties are set/modified by other parts of the Android system
    290        (e.g. the dhcpd daemon).
    291 
    292        the implementation also supports per-process DNS server list, using the
    293        properties 'net.dns1.<pid>', 'net.dns2.<pid>', etc... Where <pid> stands
    294        for the numerical ID of the current process.
    295 
    296      - when performing a query, use a properly randomized Query ID (instead of
    297        a incremented one), for increased security.
    298 
    299      - when performing a query, bind the local client socket to a random port
    300        for increased security.
    301 
    302      - get rid of *many* unfortunate thread-safety issues in the original code
    303 
    304   Bionic does *not* expose implementation details of its DNS resolver; the
    305   content of <arpa/nameser.h> is intentionally blank. The resolver
    306   implementation might change completely in the future.
    307 
    308 
    309 PThread Real-Time Timers:
    310 
    311   timer_create(), timer_gettime(), timer_settime() and timer_getoverrun() are
    312   supported.
    313 
    314   Bionic also now supports SIGEV_THREAD real-time timers (see timer_create()).
    315   The implementation simply uses a single thread per timer, unlike GLibc which
    316   uses complex heuristics to try to use the less threads possible when several
    317   timers with compatible properties are used.
    318 
    319   This means that if your code uses a lot of SIGEV_THREAD timers, your program
    320   may consume a lot of memory. However, if your program needs many of these
    321   timers, it'd better handle timeout events directly instead.
    322 
    323   Other timers (e.g. SIGEV_SIGNAL) are handled by the kernel and use much less
    324   system resources.
    325 
    326 
    327 Binary Compatibility:
    328 
    329   Bionic is *not* in any way binary-compatible with the GNU C Library, ucLibc
    330   or any known Linux C library. This means several things:
    331 
    332   - You cannot expect to build something against the GNU C Library headers and
    333     have it dynamically link properly to Bionic later.
    334 
    335   - You should *really* use the Android toolchain to build your program against
    336     Bionic. The toolchain deals with many important details that are crucial
    337     to get something working properly.
    338 
    339   Failure to do so will usually result in the inability to run or link your
    340   program, or even runtime crashes. Several random web pages on the Internet
    341   describe how you can succesfully write a "hello-world" program with the
    342   ARM GNU toolchain. These examples usually work by chance, if anything else,
    343   and you should not follow these instructions unless you want to waste a lot
    344   of your time in the process.
    345 
    346   Note however that you *can* generate a binary that is built against the
    347   GNU C Library headers and then statically linked to it. The corresponding
    348   executable should be able to run (if it doesn't use dlopen()/dlsym())
    349 
    350 
    351 Dynamic Linker:
    352 
    353   Bionic comes with its own dynamic linker (just like ld.so on Linux really
    354   comes from GLibc). This linker does not support all the relocations
    355   generated by other GCC ARM toolchains.
    356 
    357 
    358 C++ Exceptions Support:
    359 
    360   At the moment, Bionic doesn't support C++ exceptions, what this really means
    361   is the following:
    362 
    363     - If pthread_once() is called with a C++ callback that throws an exception,
    364       then the C library will keep the corresponding pthread_once_t mutex
    365       locked. Any further call to pthread_once() will result in a deadlock.
    366 
    367       A proper implementation should be able to register a C++ exception
    368       cleanup handler before the callback to properly unlock the
    369       pthread_once_t. Unfortunately this requires tricky assembly code that
    370       is highly dependent on the compiler.
    371 
    372       This feature is not planned to be supported anytime soon.
    373 
    374     - The same problem may arise if you throw an exception within a callback
    375       called from the C library. Fortunately, these cases are very rare in the
    376       real-world, but any callback you provide to the C library should *not*
    377       throw an exception.
    378 
    379     - Bionic lacks a few support functions to have exception support work
    380       properly.
    381 
    382 System V IPCs:
    383 
    384   Bionic intentionally does not provide support for System-V IPCs mechanisms,
    385   like the ones provided by semget(), shmget(), msgget(). The reason for this
    386   is to avoid denial-of-service. For a detailed rationale about this, please
    387   read the file docs/SYSV-IPCS.TXT.
    388 
    389 Include Paths:
    390 
    391   The Android build system should automatically provide the necessary include
    392   paths required to build against the C library headers. However, if you want
    393   to do that yourself, you will need to add:
    394 
    395       libc/arch-$ARCH/include
    396       libc/include
    397       libc/kernel/common
    398       libc/kernel/arch-$ARCH
    399 
    400   to your C include path.
    401