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