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