musl: update to version 1.1.10+git
[openwrt/openwrt.git] / toolchain / musl / patches / 001-git-2015-06-16.patch
1 commit 1b0cdc8700d29ef018bf226d74b2b58b23bce91c
2 Author: Rich Felker <dalias@aerifal.cx>
3 Date: Tue Jun 16 07:11:19 2015 +0000
4
5 refactor stdio open file list handling, move it out of global libc struct
6
7 functions which open in-memory FILE stream variants all shared a tail
8 with __fdopen, adding the FILE structure to stdio's open file list.
9 replacing this common tail with a function call reduces code size and
10 duplication of logic. the list is also partially encapsulated now.
11
12 function signatures were chosen to facilitate tail call optimization
13 and reduce the need for additional accessor functions.
14
15 with these changes, static linked programs that do not use stdio no
16 longer have an open file list at all.
17
18 commit f22a9edaf8a6f2ca1d314d18b3785558279a5c03
19 Author: Rich Felker <dalias@aerifal.cx>
20 Date: Tue Jun 16 06:18:00 2015 +0000
21
22 byte-based C locale, phase 3: make MB_CUR_MAX variable to activate code
23
24 this patch activates the new byte-based C locale (high bytes treated
25 as abstract code unit "characters" rather than decoded as multibyte
26 characters) by making the value of MB_CUR_MAX depend on the active
27 locale. for the C locale, the LC_CTYPE category pointer is null,
28 yielding a value of 1. all other locales yield a value of 4.
29
30 commit 16f18d036d9a7bf590ee6eb86785c0a9658220b6
31 Author: Rich Felker <dalias@aerifal.cx>
32 Date: Tue Jun 16 05:35:31 2015 +0000
33
34 byte-based C locale, phase 2: stdio and iconv (multibyte callers)
35
36 this patch adjusts libc components which use the multibyte functions
37 internally, and which depend on them operating in a particular
38 encoding, to make the appropriate locale changes before calling them
39 and restore the calling thread's locale afterwards. activating the
40 byte-based C locale without these changes would cause regressions in
41 stdio and iconv.
42
43 in the case of iconv, the current implementation was simply using the
44 multibyte functions as UTF-8 conversions. setting a multibyte UTF-8
45 locale for the duration of the iconv operation allows the code to
46 continue working.
47
48 in the case of stdio, POSIX requires that FILE streams have an
49 encoding rule bound at the time of setting wide orientation. as long
50 as all locales, including the C locale, used the same encoding,
51 treating high bytes as UTF-8, there was no need to store an encoding
52 rule as part of the stream's state.
53
54 a new locale field in the FILE structure points to the locale that
55 should be made active during fgetwc/fputwc/ungetwc on the stream. it
56 cannot point to the locale active at the time the stream becomes
57 oriented, because this locale could be mutable (the global locale) or
58 could be destroyed (locale_t objects produced by newlocale) before the
59 stream is closed. instead, a pointer to the static C or C.UTF-8 locale
60 object added in commit commit aeeac9ca5490d7d90fe061ab72da446c01ddf746
61 is used. this is valid since categories other than LC_CTYPE will not
62 affect these functions.
63
64 commit 1507ebf837334e9e07cfab1ca1c2e88449069a80
65 Author: Rich Felker <dalias@aerifal.cx>
66 Date: Tue Jun 16 04:44:17 2015 +0000
67
68 byte-based C locale, phase 1: multibyte character handling functions
69
70 this patch makes the functions which work directly on multibyte
71 characters treat the high bytes as individual abstract code units
72 rather than as multibyte sequences when MB_CUR_MAX is 1. since
73 MB_CUR_MAX is presently defined as a constant 4, all of the new code
74 added is dead code, and optimizing compilers' code generation should
75 not be affected at all. a future commit will activate the new code.
76
77 as abstract code units, bytes 0x80 to 0xff are represented by wchar_t
78 values 0xdf80 to 0xdfff, at the end of the surrogates range. this
79 ensures that they will never be misinterpreted as Unicode characters,
80 and that all wctype functions return false for these "characters"
81 without needing locale-specific logic. a high range outside of Unicode
82 such as 0x7fffff80 to 0x7fffffff was also considered, but since C11's
83 char16_t also needs to be able to represent conversions of these
84 bytes, the surrogate range was the natural choice.
85
86 commit 38e2f727237230300fea6aff68802db04625fd23
87 Author: Rich Felker <dalias@aerifal.cx>
88 Date: Tue Jun 16 04:21:38 2015 +0000
89
90 fix btowc corner case
91
92 btowc is required to interpret its argument by conversion to unsigned
93 char, unless the argument is equal to EOF. since the conversion to
94 produces a non-character value anyway, we can just unconditionally
95 convert, for now.
96
97 commit ee59c296d56bf26f49f354d6eb32b4b6d4190188
98 Author: Szabolcs Nagy <nsz@port70.net>
99 Date: Wed Jun 3 10:32:14 2015 +0100
100
101 arm: add vdso support
102
103 vdso will be available on arm in linux v4.2, the user-space code
104 for it is in kernel commit 8512287a8165592466cb9cb347ba94892e9c56a5
105
106 commit e3bc22f1eff87b8f029a6ab31f1a269d69e4b053
107 Author: Rich Felker <dalias@aerifal.cx>
108 Date: Sun Jun 14 01:59:02 2015 +0000
109
110 refactor malloc's expand_heap to share with __simple_malloc
111
112 this extends the brk/stack collision protection added to full malloc
113 in commit 276904c2f6bde3a31a24ebfa201482601d18b4f9 to also protect the
114 __simple_malloc function used in static-linked programs that don't
115 reference the free function.
116
117 it also extends support for using mmap when brk fails, which full
118 malloc got in commit 5446303328adf4b4e36d9fba21848e6feb55fab4, to
119 __simple_malloc.
120
121 since __simple_malloc may expand the heap by arbitrarily large
122 increments, the stack collision detection is enhanced to detect
123 interval overlap rather than just proximity of a single address to the
124 stack. code size is increased a bit, but this is partly offset by the
125 sharing of code between the two malloc implementations, which due to
126 linking semantics, both get linked in a program that needs the full
127 malloc with realloc/free support.
128
129 commit 4ef9b828c1f39553a69e0635ac91f0fcadd6e8c6
130 Author: Rich Felker <dalias@aerifal.cx>
131 Date: Sat Jun 13 20:53:02 2015 +0000
132
133 remove cancellation points in stdio
134
135 commit 58165923890865a6ac042fafce13f440ee986fd9 added these optional
136 cancellation points on the basis that cancellable stdio could be
137 useful, to unblock threads stuck on stdio operations that will never
138 complete. however, the only way to ensure that cancellation can
139 achieve this is to violate the rules for side effects when
140 cancellation is acted upon, discarding knowledge of any partial data
141 transfer already completed. our implementation exhibited this behavior
142 and was thus non-conforming.
143
144 in addition to improving correctness, removing these cancellation
145 points moderately reduces code size, and should significantly improve
146 performance on i386, where sysenter/syscall instructions can be used
147 instead of "int $128" for non-cancellable syscalls.
148
149 commit 536c6d5a4205e2a3f161f2983ce1e0ac3082187d
150 Author: Rich Felker <dalias@aerifal.cx>
151 Date: Sat Jun 13 05:17:16 2015 +0000
152
153 fix idiom for setting stdio stream orientation to wide
154
155 the old idiom, f->mode |= f->mode+1, was adapted from the idiom for
156 setting byte orientation, f->mode |= f->mode-1, but the adaptation was
157 incorrect. unless the stream was alreasdy set byte-oriented, this code
158 incremented f->mode each time it was executed, which would eventually
159 lead to overflow. it could be fixed by changing it to f->mode |= 1,
160 but upcoming changes will require slightly more work at the time of
161 wide orientation, so it makes sense to just call fwide. as an
162 optimization in the single-character functions, fwide is only called
163 if the stream is not already wide-oriented.
164
165 commit f8f565df467c13248104223f99abf7f37cef7584
166 Author: Rich Felker <dalias@aerifal.cx>
167 Date: Sat Jun 13 04:42:38 2015 +0000
168
169 add printing of null %s arguments as "(null)" in wide printf
170
171 this is undefined, but supported in our implementation of the normal
172 printf, so for consistency the wide variant should support it too.
173
174 commit f9e25d813860d53cd1e9b6145cc63375d2fe2529
175 Author: Rich Felker <dalias@aerifal.cx>
176 Date: Sat Jun 13 04:37:27 2015 +0000
177
178 add %m support to wide printf
179
180 commit ec634aad91f57479ef17525e33ed446c780a61f4
181 Author: Rich Felker <dalias@aerifal.cx>
182 Date: Thu Jun 11 05:01:04 2015 +0000
183
184 add sh asm for vfork
185
186 commit c30cbcb0a646b1f13a22c645616dce624465b883
187 Author: Rich Felker <dalias@aerifal.cx>
188 Date: Wed Jun 10 02:27:40 2015 +0000
189
190 implement arch-generic version of __unmapself
191
192 this can be used to put off writing an asm version of __unmapself for
193 new archs, or as a permanent solution on archs where it's not
194 practical or even possible to run momentarily with no stack.
195
196 the concept here is simple: the caller takes a lock on a global shared
197 stack and uses it to make the munmap and exit syscalls. the only trick
198 is unlocking, which must be done after the thread exits, and this is
199 achieved by using the set_tid_address syscall to have the kernel zero
200 and futex-wake the lock word as part of the exit syscall.
201
202 commit 276904c2f6bde3a31a24ebfa201482601d18b4f9
203 Author: Rich Felker <dalias@aerifal.cx>
204 Date: Tue Jun 9 20:30:35 2015 +0000
205
206 in malloc, refuse to use brk if it grows into stack
207
208 the linux/nommu fdpic ELF loader sets up the brk range to overlap
209 entirely with the main thread's stack (but growing from opposite
210 ends), so that the resulting failure mode for malloc is not to return
211 a null pointer but to start returning pointers to memory that overlaps
212 with the caller's stack. needless to say this extremely dangerous and
213 makes brk unusable.
214
215 since it's non-trivial to detect execution environments that might be
216 affected by this kernel bug, and since the severity of the bug makes
217 any sort of detection that might yield false-negatives unsafe, we
218 instead check the proximity of the brk to the stack pointer each time
219 the brk is to be expanded. both the main thread's stack (where the
220 real known risk lies) and the calling thread's stack are checked. an
221 arbitrary gap distance of 8 MB is imposed, chosen to be larger than
222 linux default main-thread stack reservation sizes and larger than any
223 reasonable stack configuration on nommu.
224
225 the effeciveness of this patch relies on an assumption that the amount
226 by which the brk is being grown is smaller than the gap limit, which
227 is always true for malloc's use of brk. reliance on this assumption is
228 why the check is being done in malloc-specific code and not in __brk.
229
230 commit bd1eaceaa3975bd2a2a34e211cff896affaecadf
231 Author: Rich Felker <dalias@aerifal.cx>
232 Date: Tue Jun 9 20:09:27 2015 +0000
233
234 fix spurious errors from pwd/grp functions when nscd backend is absent
235
236 for several pwd/grp functions, the only way the caller can distinguish
237 between a successful negative result ("no such user/group") and an
238 internal error is by clearing errno before the call and checking errno
239 afterwards. the nscd backend support code correctly simulated a
240 not-found response on systems where such a backend is not running, but
241 failed to restore errno.
242
243 this commit also fixed an outdated/incorrect comment.
244
245 commit 75ce4503950621b11fcc7f1fd1187dbcf3cde312
246 Author: Rich Felker <dalias@aerifal.cx>
247 Date: Sun Jun 7 20:55:23 2015 +0000
248
249 fix regression in pre-v7 arm on kernels with kuser helper removed
250
251 the arm atomics/TLS runtime selection code is called from
252 __set_thread_area and depends on having libc.auxv and __hwcap
253 available. commit 71f099cb7db821c51d8f39dfac622c61e54d794c moved the
254 first call to __set_thread_area to the top of dynamic linking stage 3,
255 before this data is made available, causing the runtime detection code
256 to always see __hwcap as zero and thereby select the atomics/TLS
257 implementations based on kuser helper.
258
259 upcoming work on superh will use similar runtime detection.
260
261 ideally this early-init code should be cleanly refactored and shared
262 between the dynamic linker and static-linked startup.
263
264 commit 32f3c4f70633488550c29a2444f819aafdf345ff
265 Author: Rich Felker <dalias@aerifal.cx>
266 Date: Sun Jun 7 03:09:16 2015 +0000
267
268 add multiple inclusion guard to locale_impl.h
269
270 commit 04b8360adbb6487f61aa0c00e53ec3a90a5a0d29
271 Author: Rich Felker <dalias@aerifal.cx>
272 Date: Sun Jun 7 02:59:49 2015 +0000
273
274 remove redefinition of MB_CUR_MAX in locale_impl.h
275
276 unless/until the byte-based C locale is implemented, defining
277 MB_CUR_MAX to 1 in the C locale is wrong. no internal code currently
278 uses the MB_CUR_MAX macro, but having it defined inconsistently is
279 error-prone. applications get the value from stdlib.h and were
280 unaffected.
281
282 commit 16bf466532d7328e971012b0731ad493b017ad29
283 Author: Rich Felker <dalias@aerifal.cx>
284 Date: Sat Jun 6 18:53:02 2015 +0000
285
286 make static C and C.UTF-8 locales available outside of newlocale
287
288 commit 312eea2ea4f4363fb01b73660c08bfcf43dd3bb4
289 Author: Rich Felker <dalias@aerifal.cx>
290 Date: Sat Jun 6 18:20:30 2015 +0000
291
292 remove another invalid skip of locking in ungetwc
293
294 commit 3d7e32d28dc9962e9efc1c317c5b44b5b2df3008
295 Author: Rich Felker <dalias@aerifal.cx>
296 Date: Sat Jun 6 18:16:22 2015 +0000
297
298 add macro version of ctype.h isascii function
299
300 presumably internal code (ungetwc and fputwc) was written assuming a
301 macro implementation existed; otherwise use of isascii is just a
302 pessimization.
303
304 commit 7e816a6487932cbb3cb71d94b609e50e81f4e5bf
305 Author: Rich Felker <dalias@aerifal.cx>
306 Date: Sat Jun 6 18:11:17 2015 +0000
307
308 remove invalid skip of locking in ungetwc
309
310 aside from being invalid, the early check only optimized the error
311 case, and likely pessimized the common case by separating the
312 two branches on isascii(c) at opposite ends of the function.
313
314 commit 63f4b9f18f3674124d8bcb119739fec85e6da005
315 Author: Timo Teräs <timo.teras@iki.fi>
316 Date: Fri Jun 5 10:39:42 2015 +0300
317
318 fix uselocale((locale_t)0) not to modify locale
319
320 commit 68630b55c0c7219fe9df70dc28ffbf9efc8021d8 made the new locale to
321 be assigned unconditonally resulting in crashes later on.
322
323 --- a/arch/arm/syscall_arch.h
324 +++ b/arch/arm/syscall_arch.h
325 @@ -72,3 +72,7 @@ static inline long __syscall6(long n, lo
326 register long r5 __asm__("r5") = f;
327 __asm_syscall("r"(r7), "0"(r0), "r"(r1), "r"(r2), "r"(r3), "r"(r4), "r"(r5));
328 }
329 +
330 +#define VDSO_USEFUL
331 +#define VDSO_CGT_SYM "__vdso_clock_gettime"
332 +#define VDSO_CGT_VER "LINUX_2.6"
333 --- a/include/ctype.h
334 +++ b/include/ctype.h
335 @@ -64,6 +64,7 @@ int isascii(int);
336 int toascii(int);
337 #define _tolower(a) ((a)|0x20)
338 #define _toupper(a) ((a)&0x5f)
339 +#define isascii(a) (0 ? isascii(a) : (unsigned)(a) < 128)
340
341 #endif
342
343 --- a/include/stdlib.h
344 +++ b/include/stdlib.h
345 @@ -76,7 +76,8 @@ size_t wcstombs (char *__restrict, const
346 #define EXIT_FAILURE 1
347 #define EXIT_SUCCESS 0
348
349 -#define MB_CUR_MAX ((size_t)+4)
350 +size_t __ctype_get_mb_cur_max(void);
351 +#define MB_CUR_MAX (__ctype_get_mb_cur_max())
352
353 #define RAND_MAX (0x7fffffff)
354
355 --- a/src/ctype/__ctype_get_mb_cur_max.c
356 +++ b/src/ctype/__ctype_get_mb_cur_max.c
357 @@ -1,6 +1,7 @@
358 -#include <stddef.h>
359 +#include <stdlib.h>
360 +#include "locale_impl.h"
361
362 size_t __ctype_get_mb_cur_max()
363 {
364 - return 4;
365 + return MB_CUR_MAX;
366 }
367 --- a/src/ctype/isascii.c
368 +++ b/src/ctype/isascii.c
369 @@ -1,4 +1,5 @@
370 #include <ctype.h>
371 +#undef isascii
372
373 int isascii(int c)
374 {
375 --- a/src/internal/libc.h
376 +++ b/src/internal/libc.h
377 @@ -17,8 +17,6 @@ struct __libc {
378 int secure;
379 volatile int threads_minus_1;
380 size_t *auxv;
381 - FILE *ofl_head;
382 - volatile int ofl_lock[2];
383 size_t tls_size;
384 size_t page_size;
385 struct __locale_struct global_locale;
386 --- a/src/internal/locale_impl.h
387 +++ b/src/internal/locale_impl.h
388 @@ -1,3 +1,6 @@
389 +#ifndef _LOCALE_IMPL_H
390 +#define _LOCALE_IMPL_H
391 +
392 #include <locale.h>
393 #include <stdlib.h>
394 #include "libc.h"
395 @@ -12,6 +15,10 @@ struct __locale_map {
396 const struct __locale_map *next;
397 };
398
399 +extern const struct __locale_map __c_dot_utf8;
400 +extern const struct __locale_struct __c_locale;
401 +extern const struct __locale_struct __c_dot_utf8_locale;
402 +
403 const struct __locale_map *__get_locale(int, const char *);
404 const char *__mo_lookup(const void *, size_t, const char *);
405 const char *__lctrans(const char *, const struct __locale_map *);
406 @@ -20,9 +27,14 @@ const char *__lctrans_cur(const char *);
407 #define LCTRANS(msg, lc, loc) __lctrans(msg, (loc)->cat[(lc)])
408 #define LCTRANS_CUR(msg) __lctrans_cur(msg)
409
410 +#define C_LOCALE ((locale_t)&__c_locale)
411 +#define UTF8_LOCALE ((locale_t)&__c_dot_utf8_locale)
412 +
413 #define CURRENT_LOCALE (__pthread_self()->locale)
414
415 #define CURRENT_UTF8 (!!__pthread_self()->locale->cat[LC_CTYPE])
416
417 #undef MB_CUR_MAX
418 #define MB_CUR_MAX (CURRENT_UTF8 ? 4 : 1)
419 +
420 +#endif
421 --- a/src/internal/stdio_impl.h
422 +++ b/src/internal/stdio_impl.h
423 @@ -47,6 +47,7 @@ struct _IO_FILE {
424 unsigned char *shend;
425 off_t shlim, shcnt;
426 FILE *prev_locked, *next_locked;
427 + struct __locale_struct *locale;
428 };
429
430 size_t __stdio_read(FILE *, unsigned char *, size_t);
431 @@ -75,8 +76,9 @@ int __putc_unlocked(int, FILE *);
432 FILE *__fdopen(int, const char *);
433 int __fmodeflags(const char *);
434
435 -#define OFLLOCK() LOCK(libc.ofl_lock)
436 -#define OFLUNLOCK() UNLOCK(libc.ofl_lock)
437 +FILE *__ofl_add(FILE *f);
438 +FILE **__ofl_lock(void);
439 +void __ofl_unlock(void);
440
441 #define feof(f) ((f)->flags & F_EOF)
442 #define ferror(f) ((f)->flags & F_ERR)
443 --- a/src/ldso/dynlink.c
444 +++ b/src/ldso/dynlink.c
445 @@ -1192,6 +1192,17 @@ _Noreturn void __dls3(size_t *sp)
446 char **argv_orig = argv;
447 char **envp = argv+argc+1;
448
449 + /* Find aux vector just past environ[] and use it to initialize
450 + * global data that may be needed before we can make syscalls. */
451 + __environ = envp;
452 + for (i=argc+1; argv[i]; i++);
453 + libc.auxv = auxv = (void *)(argv+i+1);
454 + decode_vec(auxv, aux, AUX_CNT);
455 + __hwcap = aux[AT_HWCAP];
456 + libc.page_size = aux[AT_PAGESZ];
457 + libc.secure = ((aux[0]&0x7800)!=0x7800 || aux[AT_UID]!=aux[AT_EUID]
458 + || aux[AT_GID]!=aux[AT_EGID] || aux[AT_SECURE]);
459 +
460 /* Setup early thread pointer in builtin_tls for ldso/libc itself to
461 * use during dynamic linking. If possible it will also serve as the
462 * thread pointer at runtime. */
463 @@ -1200,25 +1211,11 @@ _Noreturn void __dls3(size_t *sp)
464 a_crash();
465 }
466
467 - /* Find aux vector just past environ[] */
468 - for (i=argc+1; argv[i]; i++)
469 - if (!memcmp(argv[i], "LD_LIBRARY_PATH=", 16))
470 - env_path = argv[i]+16;
471 - else if (!memcmp(argv[i], "LD_PRELOAD=", 11))
472 - env_preload = argv[i]+11;
473 - auxv = (void *)(argv+i+1);
474 -
475 - decode_vec(auxv, aux, AUX_CNT);
476 -
477 /* Only trust user/env if kernel says we're not suid/sgid */
478 - if ((aux[0]&0x7800)!=0x7800 || aux[AT_UID]!=aux[AT_EUID]
479 - || aux[AT_GID]!=aux[AT_EGID] || aux[AT_SECURE]) {
480 - env_path = 0;
481 - env_preload = 0;
482 - libc.secure = 1;
483 + if (!libc.secure) {
484 + env_path = getenv("LD_LIBRARY_PATH");
485 + env_preload = getenv("LD_PRELOAD");
486 }
487 - libc.page_size = aux[AT_PAGESZ];
488 - libc.auxv = auxv;
489
490 /* If the main program was already loaded by the kernel,
491 * AT_PHDR will point to some location other than the dynamic
492 --- /dev/null
493 +++ b/src/locale/c_locale.c
494 @@ -0,0 +1,15 @@
495 +#include "locale_impl.h"
496 +#include <stdint.h>
497 +
498 +static const uint32_t empty_mo[] = { 0x950412de, 0, -1, -1, -1 };
499 +
500 +const struct __locale_map __c_dot_utf8 = {
501 + .map = empty_mo,
502 + .map_size = sizeof empty_mo,
503 + .name = "C.UTF-8"
504 +};
505 +
506 +const struct __locale_struct __c_locale = { 0 };
507 +const struct __locale_struct __c_dot_utf8_locale = {
508 + .cat[LC_CTYPE] = &__c_dot_utf8
509 +};
510 --- a/src/locale/iconv.c
511 +++ b/src/locale/iconv.c
512 @@ -5,6 +5,7 @@
513 #include <stdlib.h>
514 #include <limits.h>
515 #include <stdint.h>
516 +#include "locale_impl.h"
517
518 #define UTF_32BE 0300
519 #define UTF_16LE 0301
520 @@ -165,9 +166,12 @@ size_t iconv(iconv_t cd0, char **restric
521 int err;
522 unsigned char type = map[-1];
523 unsigned char totype = tomap[-1];
524 + locale_t *ploc = &CURRENT_LOCALE, loc = *ploc;
525
526 if (!in || !*in || !*inb) return 0;
527
528 + *ploc = UTF8_LOCALE;
529 +
530 for (; *inb; *in+=l, *inb-=l) {
531 c = *(unsigned char *)*in;
532 l = 1;
533 @@ -431,6 +435,7 @@ size_t iconv(iconv_t cd0, char **restric
534 break;
535 }
536 }
537 + *ploc = loc;
538 return x;
539 ilseq:
540 err = EILSEQ;
541 @@ -445,5 +450,6 @@ starved:
542 x = -1;
543 end:
544 errno = err;
545 + *ploc = loc;
546 return x;
547 }
548 --- a/src/locale/langinfo.c
549 +++ b/src/locale/langinfo.c
550 @@ -33,7 +33,8 @@ char *__nl_langinfo_l(nl_item item, loca
551 int idx = item & 65535;
552 const char *str;
553
554 - if (item == CODESET) return "UTF-8";
555 + if (item == CODESET)
556 + return MB_CUR_MAX==1 ? "UTF-8-CODE-UNITS" : "UTF-8";
557
558 switch (cat) {
559 case LC_NUMERIC:
560 --- a/src/locale/locale_map.c
561 +++ b/src/locale/locale_map.c
562 @@ -24,14 +24,6 @@ static const char envvars[][12] = {
563 "LC_MESSAGES",
564 };
565
566 -static const uint32_t empty_mo[] = { 0x950412de, 0, -1, -1, -1 };
567 -
568 -const struct __locale_map __c_dot_utf8 = {
569 - .map = empty_mo,
570 - .map_size = sizeof empty_mo,
571 - .name = "C.UTF-8"
572 -};
573 -
574 const struct __locale_map *__get_locale(int cat, const char *val)
575 {
576 static int lock[2];
577 @@ -107,8 +99,8 @@ const struct __locale_map *__get_locale(
578 * sake of being able to do message translations at the
579 * application level. */
580 if (!new && (new = malloc(sizeof *new))) {
581 - new->map = empty_mo;
582 - new->map_size = sizeof empty_mo;
583 + new->map = __c_dot_utf8.map;
584 + new->map_size = __c_dot_utf8.map_size;
585 memcpy(new->name, val, n);
586 new->name[n] = 0;
587 new->next = loc_head;
588 --- a/src/locale/newlocale.c
589 +++ b/src/locale/newlocale.c
590 @@ -3,16 +3,9 @@
591 #include "locale_impl.h"
592 #include "libc.h"
593
594 -extern const struct __locale_map __c_dot_utf8;
595 -
596 -static const struct __locale_struct c_locale = { 0 };
597 -static const struct __locale_struct c_dot_utf8_locale = {
598 - .cat[LC_CTYPE] = &__c_dot_utf8
599 -};
600 -
601 int __loc_is_allocated(locale_t loc)
602 {
603 - return loc && loc != &c_locale && loc != &c_dot_utf8_locale;
604 + return loc && loc != C_LOCALE && loc != UTF8_LOCALE;
605 }
606
607 locale_t __newlocale(int mask, const char *name, locale_t loc)
608 @@ -44,9 +37,9 @@ locale_t __newlocale(int mask, const cha
609 }
610
611 if (!j)
612 - return (locale_t)&c_locale;
613 - if (j==1 && tmp.cat[LC_CTYPE]==c_dot_utf8_locale.cat[LC_CTYPE])
614 - return (locale_t)&c_dot_utf8_locale;
615 + return C_LOCALE;
616 + if (j==1 && tmp.cat[LC_CTYPE]==&__c_dot_utf8)
617 + return UTF8_LOCALE;
618
619 if ((loc = malloc(sizeof *loc))) *loc = tmp;
620
621 --- a/src/locale/uselocale.c
622 +++ b/src/locale/uselocale.c
623 @@ -8,9 +8,7 @@ locale_t __uselocale(locale_t new)
624 locale_t old = self->locale;
625 locale_t global = &libc.global_locale;
626
627 - if (new == LC_GLOBAL_LOCALE) new = global;
628 -
629 - self->locale = new;
630 + if (new) self->locale = new == LC_GLOBAL_LOCALE ? global : new;
631
632 return old == global ? LC_GLOBAL_LOCALE : old;
633 }
634 --- /dev/null
635 +++ b/src/malloc/expand_heap.c
636 @@ -0,0 +1,72 @@
637 +#include <limits.h>
638 +#include <stdint.h>
639 +#include <errno.h>
640 +#include <sys/mman.h>
641 +#include "libc.h"
642 +#include "syscall.h"
643 +
644 +/* This function returns true if the interval [old,new]
645 + * intersects the 'len'-sized interval below &libc.auxv
646 + * (interpreted as the main-thread stack) or below &b
647 + * (the current stack). It is used to defend against
648 + * buggy brk implementations that can cross the stack. */
649 +
650 +static int traverses_stack_p(uintptr_t old, uintptr_t new)
651 +{
652 + const uintptr_t len = 8<<20;
653 + uintptr_t a, b;
654 +
655 + b = (uintptr_t)libc.auxv;
656 + a = b > len ? b-len : 0;
657 + if (new>a && old<b) return 1;
658 +
659 + b = (uintptr_t)&b;
660 + a = b > len ? b-len : 0;
661 + if (new>a && old<b) return 1;
662 +
663 + return 0;
664 +}
665 +
666 +void *__mmap(void *, size_t, int, int, int, off_t);
667 +
668 +/* Expand the heap in-place if brk can be used, or otherwise via mmap,
669 + * using an exponential lower bound on growth by mmap to make
670 + * fragmentation asymptotically irrelevant. The size argument is both
671 + * an input and an output, since the caller needs to know the size
672 + * allocated, which will be larger than requested due to page alignment
673 + * and mmap minimum size rules. The caller is responsible for locking
674 + * to prevent concurrent calls. */
675 +
676 +void *__expand_heap(size_t *pn)
677 +{
678 + static uintptr_t brk;
679 + static unsigned mmap_step;
680 + size_t n = *pn;
681 +
682 + if (n > SIZE_MAX/2 - PAGE_SIZE) {
683 + errno = ENOMEM;
684 + return 0;
685 + }
686 + n += -n & PAGE_SIZE-1;
687 +
688 + if (!brk) {
689 + brk = __syscall(SYS_brk, 0);
690 + brk += -brk & PAGE_SIZE-1;
691 + }
692 +
693 + if (n < SIZE_MAX-brk && !traverses_stack_p(brk, brk+n)
694 + && __syscall(SYS_brk, brk+n)==brk+n) {
695 + *pn = n;
696 + brk += n;
697 + return (void *)(brk-n);
698 + }
699 +
700 + size_t min = (size_t)PAGE_SIZE << mmap_step/2;
701 + if (n < min) n = min;
702 + void *area = __mmap(0, n, PROT_READ|PROT_WRITE,
703 + MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
704 + if (area == MAP_FAILED) return 0;
705 + *pn = n;
706 + mmap_step++;
707 + return area;
708 +}
709 --- a/src/malloc/lite_malloc.c
710 +++ b/src/malloc/lite_malloc.c
711 @@ -4,43 +4,46 @@
712 #include <errno.h>
713 #include "libc.h"
714
715 -uintptr_t __brk(uintptr_t);
716 -
717 #define ALIGN 16
718
719 +void *__expand_heap(size_t *);
720 +
721 void *__simple_malloc(size_t n)
722 {
723 - static uintptr_t cur, brk;
724 - uintptr_t base, new;
725 + static char *cur, *end;
726 static volatile int lock[2];
727 - size_t align=1;
728 + size_t align=1, pad;
729 + void *p;
730
731 if (!n) n++;
732 - if (n > SIZE_MAX/2) goto toobig;
733 -
734 while (align<n && align<ALIGN)
735 align += align;
736 - n = n + align - 1 & -align;
737
738 LOCK(lock);
739 - if (!cur) cur = brk = __brk(0)+16;
740 - base = cur + align-1 & -align;
741 - if (n > SIZE_MAX - PAGE_SIZE - base) goto fail;
742 - if (base+n > brk) {
743 - new = base+n + PAGE_SIZE-1 & -PAGE_SIZE;
744 - if (__brk(new) != new) goto fail;
745 - brk = new;
746 - }
747 - cur = base+n;
748 - UNLOCK(lock);
749
750 - return (void *)base;
751 + pad = -(uintptr_t)cur & align-1;
752 +
753 + if (n <= SIZE_MAX/2 + ALIGN) n += pad;
754 +
755 + if (n > end-cur) {
756 + size_t m = n;
757 + char *new = __expand_heap(&m);
758 + if (!new) {
759 + UNLOCK(lock);
760 + return 0;
761 + }
762 + if (new != end) {
763 + cur = new;
764 + n -= pad;
765 + pad = 0;
766 + }
767 + end = new + m;
768 + }
769
770 -fail:
771 + p = cur + pad;
772 + cur += n;
773 UNLOCK(lock);
774 -toobig:
775 - errno = ENOMEM;
776 - return 0;
777 + return p;
778 }
779
780 weak_alias(__simple_malloc, malloc);
781 --- a/src/malloc/malloc.c
782 +++ b/src/malloc/malloc.c
783 @@ -13,7 +13,6 @@
784 #define inline inline __attribute__((always_inline))
785 #endif
786
787 -uintptr_t __brk(uintptr_t);
788 void *__mmap(void *, size_t, int, int, int, off_t);
789 int __munmap(void *, size_t);
790 void *__mremap(void *, size_t, size_t, int, ...);
791 @@ -31,13 +30,9 @@ struct bin {
792 };
793
794 static struct {
795 - uintptr_t brk;
796 - size_t *heap;
797 volatile uint64_t binmap;
798 struct bin bins[64];
799 - volatile int brk_lock[2];
800 volatile int free_lock[2];
801 - unsigned mmap_step;
802 } mal;
803
804
805 @@ -152,69 +147,52 @@ void __dump_heap(int x)
806 }
807 #endif
808
809 +void *__expand_heap(size_t *);
810 +
811 static struct chunk *expand_heap(size_t n)
812 {
813 - static int init;
814 + static int heap_lock[2];
815 + static void *end;
816 + void *p;
817 struct chunk *w;
818 - uintptr_t new;
819 -
820 - lock(mal.brk_lock);
821
822 - if (!init) {
823 - mal.brk = __brk(0);
824 -#ifdef SHARED
825 - mal.brk = mal.brk + PAGE_SIZE-1 & -PAGE_SIZE;
826 -#endif
827 - mal.brk = mal.brk + 2*SIZE_ALIGN-1 & -SIZE_ALIGN;
828 - mal.heap = (void *)mal.brk;
829 - init = 1;
830 + /* The argument n already accounts for the caller's chunk
831 + * overhead needs, but if the heap can't be extended in-place,
832 + * we need room for an extra zero-sized sentinel chunk. */
833 + n += SIZE_ALIGN;
834 +
835 + lock(heap_lock);
836 +
837 + p = __expand_heap(&n);
838 + if (!p) {
839 + unlock(heap_lock);
840 + return 0;
841 }
842
843 - if (n > SIZE_MAX - mal.brk - 2*PAGE_SIZE) goto fail;
844 - new = mal.brk + n + SIZE_ALIGN + PAGE_SIZE - 1 & -PAGE_SIZE;
845 - n = new - mal.brk;
846 -
847 - if (__brk(new) != new) {
848 - size_t min = (size_t)PAGE_SIZE << mal.mmap_step/2;
849 - n += -n & PAGE_SIZE-1;
850 - if (n < min) n = min;
851 - void *area = __mmap(0, n, PROT_READ|PROT_WRITE,
852 - MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
853 - if (area == MAP_FAILED) goto fail;
854 -
855 - mal.mmap_step++;
856 - area = (char *)area + SIZE_ALIGN - OVERHEAD;
857 - w = area;
858 + /* If not just expanding existing space, we need to make a
859 + * new sentinel chunk below the allocated space. */
860 + if (p != end) {
861 + /* Valid/safe because of the prologue increment. */
862 n -= SIZE_ALIGN;
863 + p = (char *)p + SIZE_ALIGN;
864 + w = MEM_TO_CHUNK(p);
865 w->psize = 0 | C_INUSE;
866 - w->csize = n | C_INUSE;
867 - w = NEXT_CHUNK(w);
868 - w->psize = n | C_INUSE;
869 - w->csize = 0 | C_INUSE;
870 -
871 - unlock(mal.brk_lock);
872 -
873 - return area;
874 }
875
876 - w = MEM_TO_CHUNK(mal.heap);
877 - w->psize = 0 | C_INUSE;
878 -
879 - w = MEM_TO_CHUNK(new);
880 + /* Record new heap end and fill in footer. */
881 + end = (char *)p + n;
882 + w = MEM_TO_CHUNK(end);
883 w->psize = n | C_INUSE;
884 w->csize = 0 | C_INUSE;
885
886 - w = MEM_TO_CHUNK(mal.brk);
887 + /* Fill in header, which may be new or may be replacing a
888 + * zero-size sentinel header at the old end-of-heap. */
889 + w = MEM_TO_CHUNK(p);
890 w->csize = n | C_INUSE;
891 - mal.brk = new;
892 -
893 - unlock(mal.brk_lock);
894 +
895 + unlock(heap_lock);
896
897 return w;
898 -fail:
899 - unlock(mal.brk_lock);
900 - errno = ENOMEM;
901 - return 0;
902 }
903
904 static int adjust_size(size_t *n)
905 --- a/src/multibyte/btowc.c
906 +++ b/src/multibyte/btowc.c
907 @@ -1,7 +1,10 @@
908 #include <stdio.h>
909 #include <wchar.h>
910 +#include <stdlib.h>
911 +#include "internal.h"
912
913 wint_t btowc(int c)
914 {
915 - return c<128U ? c : EOF;
916 + int b = (unsigned char)c;
917 + return b<128U ? b : (MB_CUR_MAX==1 && c!=EOF) ? CODEUNIT(c) : WEOF;
918 }
919 --- a/src/multibyte/internal.h
920 +++ b/src/multibyte/internal.h
921 @@ -23,3 +23,10 @@ extern const uint32_t bittab[];
922
923 #define SA 0xc2u
924 #define SB 0xf4u
925 +
926 +/* Arbitrary encoding for representing code units instead of characters. */
927 +#define CODEUNIT(c) (0xdfff & (signed char)(c))
928 +#define IS_CODEUNIT(c) ((unsigned)(c)-0xdf80 < 0x80)
929 +
930 +/* Get inline definition of MB_CUR_MAX. */
931 +#include "locale_impl.h"
932 --- a/src/multibyte/mbrtowc.c
933 +++ b/src/multibyte/mbrtowc.c
934 @@ -4,6 +4,7 @@
935 * unnecessary.
936 */
937
938 +#include <stdlib.h>
939 #include <wchar.h>
940 #include <errno.h>
941 #include "internal.h"
942 @@ -27,6 +28,7 @@ size_t mbrtowc(wchar_t *restrict wc, con
943 if (!n) return -2;
944 if (!c) {
945 if (*s < 0x80) return !!(*wc = *s);
946 + if (MB_CUR_MAX==1) return (*wc = CODEUNIT(*s)), 1;
947 if (*s-SA > SB-SA) goto ilseq;
948 c = bittab[*s++-SA]; n--;
949 }
950 --- a/src/multibyte/mbsrtowcs.c
951 +++ b/src/multibyte/mbsrtowcs.c
952 @@ -7,6 +7,8 @@
953 #include <stdint.h>
954 #include <wchar.h>
955 #include <errno.h>
956 +#include <string.h>
957 +#include <stdlib.h>
958 #include "internal.h"
959
960 size_t mbsrtowcs(wchar_t *restrict ws, const char **restrict src, size_t wn, mbstate_t *restrict st)
961 @@ -24,6 +26,23 @@ size_t mbsrtowcs(wchar_t *restrict ws, c
962 }
963 }
964
965 + if (MB_CUR_MAX==1) {
966 + if (!ws) return strlen((const char *)s);
967 + for (;;) {
968 + if (!wn) {
969 + *src = (const void *)s;
970 + return wn0;
971 + }
972 + if (!*s) break;
973 + c = *s++;
974 + *ws++ = CODEUNIT(c);
975 + wn--;
976 + }
977 + *ws = 0;
978 + *src = 0;
979 + return wn0-wn;
980 + }
981 +
982 if (!ws) for (;;) {
983 if (*s-1u < 0x7f && (uintptr_t)s%4 == 0) {
984 while (!(( *(uint32_t*)s | *(uint32_t*)s-0x01010101) & 0x80808080)) {
985 --- a/src/multibyte/mbtowc.c
986 +++ b/src/multibyte/mbtowc.c
987 @@ -4,6 +4,7 @@
988 * unnecessary.
989 */
990
991 +#include <stdlib.h>
992 #include <wchar.h>
993 #include <errno.h>
994 #include "internal.h"
995 @@ -19,6 +20,7 @@ int mbtowc(wchar_t *restrict wc, const c
996 if (!wc) wc = &dummy;
997
998 if (*s < 0x80) return !!(*wc = *s);
999 + if (MB_CUR_MAX==1) return (*wc = CODEUNIT(*s)), 1;
1000 if (*s-SA > SB-SA) goto ilseq;
1001 c = bittab[*s++-SA];
1002
1003 --- a/src/multibyte/wcrtomb.c
1004 +++ b/src/multibyte/wcrtomb.c
1005 @@ -4,8 +4,10 @@
1006 * unnecessary.
1007 */
1008
1009 +#include <stdlib.h>
1010 #include <wchar.h>
1011 #include <errno.h>
1012 +#include "internal.h"
1013
1014 size_t wcrtomb(char *restrict s, wchar_t wc, mbstate_t *restrict st)
1015 {
1016 @@ -13,6 +15,13 @@ size_t wcrtomb(char *restrict s, wchar_t
1017 if ((unsigned)wc < 0x80) {
1018 *s = wc;
1019 return 1;
1020 + } else if (MB_CUR_MAX == 1) {
1021 + if (!IS_CODEUNIT(wc)) {
1022 + errno = EILSEQ;
1023 + return -1;
1024 + }
1025 + *s = wc;
1026 + return 1;
1027 } else if ((unsigned)wc < 0x800) {
1028 *s++ = 0xc0 | (wc>>6);
1029 *s = 0x80 | (wc&0x3f);
1030 --- a/src/multibyte/wctob.c
1031 +++ b/src/multibyte/wctob.c
1032 @@ -1,8 +1,10 @@
1033 -#include <stdio.h>
1034 #include <wchar.h>
1035 +#include <stdlib.h>
1036 +#include "internal.h"
1037
1038 int wctob(wint_t c)
1039 {
1040 if (c < 128U) return c;
1041 + if (MB_CUR_MAX==1 && IS_CODEUNIT(c)) return (unsigned char)c;
1042 return EOF;
1043 }
1044 --- a/src/passwd/nscd_query.c
1045 +++ b/src/passwd/nscd_query.c
1046 @@ -32,6 +32,7 @@ FILE *__nscd_query(int32_t req, const ch
1047 },
1048 .msg_iovlen = 2
1049 };
1050 + int errno_save = errno;
1051
1052 *swap = 0;
1053 retry:
1054 @@ -50,11 +51,14 @@ retry:
1055 return f;
1056
1057 if (connect(fd, (struct sockaddr*)&addr, sizeof(addr)) < 0) {
1058 - /* If there isn't a running nscd we return -1 to indicate that
1059 - * that is precisely what happened
1060 - */
1061 - if (errno == EACCES || errno == ECONNREFUSED || errno == ENOENT)
1062 + /* If there isn't a running nscd we simulate a "not found"
1063 + * result and the caller is responsible for calling
1064 + * fclose on the (unconnected) socket. The value of
1065 + * errno must be left unchanged in this case. */
1066 + if (errno == EACCES || errno == ECONNREFUSED || errno == ENOENT) {
1067 + errno = errno_save;
1068 return f;
1069 + }
1070 goto error;
1071 }
1072
1073 --- /dev/null
1074 +++ b/src/process/sh/vfork.s
1075 @@ -0,0 +1,23 @@
1076 +.global __vfork
1077 +.weak vfork
1078 +.type __vfork,@function
1079 +.type vfork,@function
1080 +__vfork:
1081 +vfork:
1082 + mov #95, r3
1083 + add r3, r3
1084 +
1085 + trapa #16
1086 + or r0, r0
1087 + or r0, r0
1088 + or r0, r0
1089 + or r0, r0
1090 + or r0, r0
1091 +
1092 + mov r0, r4
1093 + mov.l 1f, r0
1094 +2: braf r0
1095 + nop
1096 + .align 2
1097 + .hidden __syscall_ret
1098 +1: .long __syscall_ret@PLT-(2b+4-.)
1099 --- a/src/regex/fnmatch.c
1100 +++ b/src/regex/fnmatch.c
1101 @@ -18,6 +18,7 @@
1102 #include <stdlib.h>
1103 #include <wchar.h>
1104 #include <wctype.h>
1105 +#include "locale_impl.h"
1106
1107 #define END 0
1108 #define UNMATCHABLE -2
1109 @@ -229,7 +230,7 @@ static int fnmatch_internal(const char *
1110 * On illegal sequences we may get it wrong, but in that case
1111 * we necessarily have a matching failure anyway. */
1112 for (s=endstr; s>str && tailcnt; tailcnt--) {
1113 - if (s[-1] < 128U) s--;
1114 + if (s[-1] < 128U || MB_CUR_MAX==1) s--;
1115 else while ((unsigned char)*--s-0x80U<0x40 && s>str);
1116 }
1117 if (tailcnt) return FNM_NOMATCH;
1118 --- a/src/stdio/__fdopen.c
1119 +++ b/src/stdio/__fdopen.c
1120 @@ -54,13 +54,7 @@ FILE *__fdopen(int fd, const char *mode)
1121 if (!libc.threaded) f->lock = -1;
1122
1123 /* Add new FILE to open file list */
1124 - OFLLOCK();
1125 - f->next = libc.ofl_head;
1126 - if (libc.ofl_head) libc.ofl_head->prev = f;
1127 - libc.ofl_head = f;
1128 - OFLUNLOCK();
1129 -
1130 - return f;
1131 + return __ofl_add(f);
1132 }
1133
1134 weak_alias(__fdopen, fdopen);
1135 --- a/src/stdio/__stdio_exit.c
1136 +++ b/src/stdio/__stdio_exit.c
1137 @@ -16,8 +16,7 @@ static void close_file(FILE *f)
1138 void __stdio_exit(void)
1139 {
1140 FILE *f;
1141 - OFLLOCK();
1142 - for (f=libc.ofl_head; f; f=f->next) close_file(f);
1143 + for (f=*__ofl_lock(); f; f=f->next) close_file(f);
1144 close_file(__stdin_used);
1145 close_file(__stdout_used);
1146 }
1147 --- a/src/stdio/__stdio_read.c
1148 +++ b/src/stdio/__stdio_read.c
1149 @@ -1,12 +1,5 @@
1150 #include "stdio_impl.h"
1151 #include <sys/uio.h>
1152 -#include <pthread.h>
1153 -
1154 -static void cleanup(void *p)
1155 -{
1156 - FILE *f = p;
1157 - if (!f->lockcount) __unlockfile(f);
1158 -}
1159
1160 size_t __stdio_read(FILE *f, unsigned char *buf, size_t len)
1161 {
1162 @@ -16,9 +9,7 @@ size_t __stdio_read(FILE *f, unsigned ch
1163 };
1164 ssize_t cnt;
1165
1166 - pthread_cleanup_push(cleanup, f);
1167 - cnt = syscall_cp(SYS_readv, f->fd, iov, 2);
1168 - pthread_cleanup_pop(0);
1169 + cnt = syscall(SYS_readv, f->fd, iov, 2);
1170 if (cnt <= 0) {
1171 f->flags |= F_EOF ^ ((F_ERR^F_EOF) & cnt);
1172 return cnt;
1173 --- a/src/stdio/__stdio_write.c
1174 +++ b/src/stdio/__stdio_write.c
1175 @@ -1,12 +1,5 @@
1176 #include "stdio_impl.h"
1177 #include <sys/uio.h>
1178 -#include <pthread.h>
1179 -
1180 -static void cleanup(void *p)
1181 -{
1182 - FILE *f = p;
1183 - if (!f->lockcount) __unlockfile(f);
1184 -}
1185
1186 size_t __stdio_write(FILE *f, const unsigned char *buf, size_t len)
1187 {
1188 @@ -19,9 +12,7 @@ size_t __stdio_write(FILE *f, const unsi
1189 int iovcnt = 2;
1190 ssize_t cnt;
1191 for (;;) {
1192 - pthread_cleanup_push(cleanup, f);
1193 - cnt = syscall_cp(SYS_writev, f->fd, iov, iovcnt);
1194 - pthread_cleanup_pop(0);
1195 + cnt = syscall(SYS_writev, f->fd, iov, iovcnt);
1196 if (cnt == rem) {
1197 f->wend = f->buf + f->buf_size;
1198 f->wpos = f->wbase = f->buf;
1199 @@ -34,11 +25,8 @@ size_t __stdio_write(FILE *f, const unsi
1200 }
1201 rem -= cnt;
1202 if (cnt > iov[0].iov_len) {
1203 - f->wpos = f->wbase = f->buf;
1204 cnt -= iov[0].iov_len;
1205 iov++; iovcnt--;
1206 - } else if (iovcnt == 2) {
1207 - f->wbase += cnt;
1208 }
1209 iov[0].iov_base = (char *)iov[0].iov_base + cnt;
1210 iov[0].iov_len -= cnt;
1211 --- a/src/stdio/fclose.c
1212 +++ b/src/stdio/fclose.c
1213 @@ -14,11 +14,11 @@ int fclose(FILE *f)
1214 __unlist_locked_file(f);
1215
1216 if (!(perm = f->flags & F_PERM)) {
1217 - OFLLOCK();
1218 + FILE **head = __ofl_lock();
1219 if (f->prev) f->prev->next = f->next;
1220 if (f->next) f->next->prev = f->prev;
1221 - if (libc.ofl_head == f) libc.ofl_head = f->next;
1222 - OFLUNLOCK();
1223 + if (*head == f) *head = f->next;
1224 + __ofl_unlock();
1225 }
1226
1227 r = fflush(f);
1228 --- a/src/stdio/fflush.c
1229 +++ b/src/stdio/fflush.c
1230 @@ -35,13 +35,12 @@ int fflush(FILE *f)
1231
1232 r = __stdout_used ? fflush(__stdout_used) : 0;
1233
1234 - OFLLOCK();
1235 - for (f=libc.ofl_head; f; f=f->next) {
1236 + for (f=*__ofl_lock(); f; f=f->next) {
1237 FLOCK(f);
1238 if (f->wpos > f->wbase) r |= __fflush_unlocked(f);
1239 FUNLOCK(f);
1240 }
1241 - OFLUNLOCK();
1242 + __ofl_unlock();
1243
1244 return r;
1245 }
1246 --- a/src/stdio/fgetwc.c
1247 +++ b/src/stdio/fgetwc.c
1248 @@ -1,8 +1,9 @@
1249 #include "stdio_impl.h"
1250 +#include "locale_impl.h"
1251 #include <wchar.h>
1252 #include <errno.h>
1253
1254 -wint_t __fgetwc_unlocked(FILE *f)
1255 +static wint_t __fgetwc_unlocked_internal(FILE *f)
1256 {
1257 mbstate_t st = { 0 };
1258 wchar_t wc;
1259 @@ -10,8 +11,6 @@ wint_t __fgetwc_unlocked(FILE *f)
1260 unsigned char b;
1261 size_t l;
1262
1263 - f->mode |= f->mode+1;
1264 -
1265 /* Convert character from buffer if possible */
1266 if (f->rpos < f->rend) {
1267 l = mbrtowc(&wc, (void *)f->rpos, f->rend - f->rpos, &st);
1268 @@ -39,6 +38,16 @@ wint_t __fgetwc_unlocked(FILE *f)
1269 return wc;
1270 }
1271
1272 +wint_t __fgetwc_unlocked(FILE *f)
1273 +{
1274 + locale_t *ploc = &CURRENT_LOCALE, loc = *ploc;
1275 + if (f->mode <= 0) fwide(f, 1);
1276 + *ploc = f->locale;
1277 + wchar_t wc = __fgetwc_unlocked_internal(f);
1278 + *ploc = loc;
1279 + return wc;
1280 +}
1281 +
1282 wint_t fgetwc(FILE *f)
1283 {
1284 wint_t c;
1285 --- a/src/stdio/fmemopen.c
1286 +++ b/src/stdio/fmemopen.c
1287 @@ -110,11 +110,5 @@ FILE *fmemopen(void *restrict buf, size_
1288
1289 if (!libc.threaded) f->lock = -1;
1290
1291 - OFLLOCK();
1292 - f->next = libc.ofl_head;
1293 - if (libc.ofl_head) libc.ofl_head->prev = f;
1294 - libc.ofl_head = f;
1295 - OFLUNLOCK();
1296 -
1297 - return f;
1298 + return __ofl_add(f);
1299 }
1300 --- a/src/stdio/fopen.c
1301 +++ b/src/stdio/fopen.c
1302 @@ -18,7 +18,7 @@ FILE *fopen(const char *restrict filenam
1303 /* Compute the flags to pass to open() */
1304 flags = __fmodeflags(mode);
1305
1306 - fd = sys_open_cp(filename, flags, 0666);
1307 + fd = sys_open(filename, flags, 0666);
1308 if (fd < 0) return 0;
1309 if (flags & O_CLOEXEC)
1310 __syscall(SYS_fcntl, fd, F_SETFD, FD_CLOEXEC);
1311 --- a/src/stdio/fputwc.c
1312 +++ b/src/stdio/fputwc.c
1313 @@ -1,4 +1,5 @@
1314 #include "stdio_impl.h"
1315 +#include "locale_impl.h"
1316 #include <wchar.h>
1317 #include <limits.h>
1318 #include <ctype.h>
1319 @@ -7,8 +8,10 @@ wint_t __fputwc_unlocked(wchar_t c, FILE
1320 {
1321 char mbc[MB_LEN_MAX];
1322 int l;
1323 + locale_t *ploc = &CURRENT_LOCALE, loc = *ploc;
1324
1325 - f->mode |= f->mode+1;
1326 + if (f->mode <= 0) fwide(f, 1);
1327 + *ploc = f->locale;
1328
1329 if (isascii(c)) {
1330 c = putc_unlocked(c, f);
1331 @@ -20,6 +23,8 @@ wint_t __fputwc_unlocked(wchar_t c, FILE
1332 l = wctomb(mbc, c);
1333 if (l < 0 || __fwritex((void *)mbc, l, f) < l) c = WEOF;
1334 }
1335 + if (c==WEOF) f->flags |= F_ERR;
1336 + *ploc = loc;
1337 return c;
1338 }
1339
1340 --- a/src/stdio/fputws.c
1341 +++ b/src/stdio/fputws.c
1342 @@ -1,23 +1,28 @@
1343 #include "stdio_impl.h"
1344 +#include "locale_impl.h"
1345 #include <wchar.h>
1346
1347 int fputws(const wchar_t *restrict ws, FILE *restrict f)
1348 {
1349 unsigned char buf[BUFSIZ];
1350 size_t l=0;
1351 + locale_t *ploc = &CURRENT_LOCALE, loc = *ploc;
1352
1353 FLOCK(f);
1354
1355 - f->mode |= f->mode+1;
1356 + fwide(f, 1);
1357 + *ploc = f->locale;
1358
1359 while (ws && (l = wcsrtombs((void *)buf, (void*)&ws, sizeof buf, 0))+1 > 1)
1360 if (__fwritex(buf, l, f) < l) {
1361 FUNLOCK(f);
1362 + *ploc = loc;
1363 return -1;
1364 }
1365
1366 FUNLOCK(f);
1367
1368 + *ploc = loc;
1369 return l; /* 0 or -1 */
1370 }
1371
1372 --- a/src/stdio/fwide.c
1373 +++ b/src/stdio/fwide.c
1374 @@ -1,13 +1,14 @@
1375 -#include <wchar.h>
1376 #include "stdio_impl.h"
1377 -
1378 -#define SH (8*sizeof(int)-1)
1379 -#define NORMALIZE(x) ((x)>>SH | -((-(x))>>SH))
1380 +#include "locale_impl.h"
1381
1382 int fwide(FILE *f, int mode)
1383 {
1384 FLOCK(f);
1385 - if (!f->mode) f->mode = NORMALIZE(mode);
1386 + if (mode) {
1387 + if (!f->locale) f->locale = MB_CUR_MAX==1
1388 + ? C_LOCALE : UTF8_LOCALE;
1389 + if (!f->mode) f->mode = mode>0 ? 1 : -1;
1390 + }
1391 mode = f->mode;
1392 FUNLOCK(f);
1393 return mode;
1394 --- /dev/null
1395 +++ b/src/stdio/ofl.c
1396 @@ -0,0 +1,16 @@
1397 +#include "stdio_impl.h"
1398 +#include "libc.h"
1399 +
1400 +static FILE *ofl_head;
1401 +static volatile int ofl_lock[2];
1402 +
1403 +FILE **__ofl_lock()
1404 +{
1405 + LOCK(ofl_lock);
1406 + return &ofl_head;
1407 +}
1408 +
1409 +void __ofl_unlock()
1410 +{
1411 + UNLOCK(ofl_lock);
1412 +}
1413 --- /dev/null
1414 +++ b/src/stdio/ofl_add.c
1415 @@ -0,0 +1,11 @@
1416 +#include "stdio_impl.h"
1417 +
1418 +FILE *__ofl_add(FILE *f)
1419 +{
1420 + FILE **head = __ofl_lock();
1421 + f->next = *head;
1422 + if (*head) (*head)->prev = f;
1423 + *head = f;
1424 + __ofl_unlock();
1425 + return f;
1426 +}
1427 --- a/src/stdio/open_memstream.c
1428 +++ b/src/stdio/open_memstream.c
1429 @@ -79,11 +79,5 @@ FILE *open_memstream(char **bufp, size_t
1430
1431 if (!libc.threaded) f->lock = -1;
1432
1433 - OFLLOCK();
1434 - f->next = libc.ofl_head;
1435 - if (libc.ofl_head) libc.ofl_head->prev = f;
1436 - libc.ofl_head = f;
1437 - OFLUNLOCK();
1438 -
1439 - return f;
1440 + return __ofl_add(f);
1441 }
1442 --- a/src/stdio/open_wmemstream.c
1443 +++ b/src/stdio/open_wmemstream.c
1444 @@ -81,11 +81,5 @@ FILE *open_wmemstream(wchar_t **bufp, si
1445
1446 if (!libc.threaded) f->lock = -1;
1447
1448 - OFLLOCK();
1449 - f->next = libc.ofl_head;
1450 - if (libc.ofl_head) libc.ofl_head->prev = f;
1451 - libc.ofl_head = f;
1452 - OFLUNLOCK();
1453 -
1454 - return f;
1455 + return __ofl_add(f);
1456 }
1457 --- a/src/stdio/ungetwc.c
1458 +++ b/src/stdio/ungetwc.c
1459 @@ -1,4 +1,5 @@
1460 #include "stdio_impl.h"
1461 +#include "locale_impl.h"
1462 #include <wchar.h>
1463 #include <limits.h>
1464 #include <ctype.h>
1465 @@ -8,21 +9,19 @@ wint_t ungetwc(wint_t c, FILE *f)
1466 {
1467 unsigned char mbc[MB_LEN_MAX];
1468 int l=1;
1469 -
1470 - if (c == WEOF) return c;
1471 -
1472 - /* Try conversion early so we can fail without locking if invalid */
1473 - if (!isascii(c) && (l = wctomb((void *)mbc, c)) < 0)
1474 - return WEOF;
1475 + locale_t *ploc = &CURRENT_LOCALE, loc = *ploc;
1476
1477 FLOCK(f);
1478
1479 - f->mode |= f->mode+1;
1480 + if (f->mode <= 0) fwide(f, 1);
1481 + *ploc = f->locale;
1482
1483 if (!f->rpos) __toread(f);
1484 - if (!f->rpos || f->rpos < f->buf - UNGET + l) {
1485 + if (!f->rpos || f->rpos < f->buf - UNGET + l || c == WEOF ||
1486 + (!isascii(c) && (l = wctomb((void *)mbc, c)) < 0)) {
1487 FUNLOCK(f);
1488 - return EOF;
1489 + *ploc = loc;
1490 + return WEOF;
1491 }
1492
1493 if (isascii(c)) *--f->rpos = c;
1494 @@ -31,5 +30,6 @@ wint_t ungetwc(wint_t c, FILE *f)
1495 f->flags &= ~F_EOF;
1496
1497 FUNLOCK(f);
1498 + *ploc = loc;
1499 return c;
1500 }
1501 --- a/src/stdio/vfwprintf.c
1502 +++ b/src/stdio/vfwprintf.c
1503 @@ -293,7 +293,10 @@ static int wprintf_core(FILE *f, const w
1504 if ((fl&LEFT_ADJ)) fprintf(f, "%.*s", w-p, "");
1505 l=w;
1506 continue;
1507 + case 'm':
1508 + arg.p = strerror(errno);
1509 case 's':
1510 + if (!arg.p) arg.p = "(null)";
1511 bs = arg.p;
1512 if (p<0) p = INT_MAX;
1513 for (i=l=0; l<p && (i=mbtowc(&wc, bs, MB_LEN_MAX))>0; bs+=i, l++);
1514 @@ -356,7 +359,7 @@ int vfwprintf(FILE *restrict f, const wc
1515 }
1516
1517 FLOCK(f);
1518 - f->mode |= f->mode+1;
1519 + fwide(f, 1);
1520 olderr = f->flags & F_ERR;
1521 f->flags &= ~F_ERR;
1522 ret = wprintf_core(f, fmt, &ap2, nl_arg, nl_type);
1523 --- a/src/stdio/vfwscanf.c
1524 +++ b/src/stdio/vfwscanf.c
1525 @@ -104,7 +104,7 @@ int vfwscanf(FILE *restrict f, const wch
1526
1527 FLOCK(f);
1528
1529 - f->mode |= f->mode+1;
1530 + fwide(f, 1);
1531
1532 for (p=fmt; *p; p++) {
1533
1534 --- /dev/null
1535 +++ b/src/thread/__unmapself.c
1536 @@ -0,0 +1,29 @@
1537 +#include "pthread_impl.h"
1538 +#include "atomic.h"
1539 +#include "syscall.h"
1540 +/* cheat and reuse CRTJMP macro from dynlink code */
1541 +#include "dynlink.h"
1542 +
1543 +static volatile int lock;
1544 +static void *unmap_base;
1545 +static size_t unmap_size;
1546 +static char shared_stack[256];
1547 +
1548 +static void do_unmap()
1549 +{
1550 + __syscall(SYS_munmap, unmap_base, unmap_size);
1551 + __syscall(SYS_exit);
1552 +}
1553 +
1554 +void __unmapself(void *base, size_t size)
1555 +{
1556 + int tid=__pthread_self()->tid;
1557 + char *stack = shared_stack + sizeof shared_stack;
1558 + stack -= (uintptr_t)stack % 16;
1559 + while (lock || a_cas(&lock, 0, tid))
1560 + a_spin();
1561 + __syscall(SYS_set_tid_address, &lock);
1562 + unmap_base = base;
1563 + unmap_size = size;
1564 + CRTJMP(do_unmap, stack);
1565 +}
1566 --- a/src/thread/pthread_create.c
1567 +++ b/src/thread/pthread_create.c
1568 @@ -191,8 +191,9 @@ int __pthread_create(pthread_t *restrict
1569 if (!libc.can_do_threads) return ENOSYS;
1570 self = __pthread_self();
1571 if (!libc.threaded) {
1572 - for (FILE *f=libc.ofl_head; f; f=f->next)
1573 + for (FILE *f=*__ofl_lock(); f; f=f->next)
1574 init_file_lock(f);
1575 + __ofl_unlock();
1576 init_file_lock(__stdin_used);
1577 init_file_lock(__stdout_used);
1578 init_file_lock(__stderr_used);