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