From 63c188ec42e76ff768e81f6b65b11c68fc43351e Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Wed, 27 May 2015 00:22:43 -0400 Subject: replace atomics with locks in locale-setting code this is part of a general program of removing direct use of atomics where they are not necessary to meet correctness or performance needs, but in this case it's also an optimization. only the global locale needs synchronization; allocated locales referenced with locale_t handles are immutable during their lifetimes, and using atomics to initialize them increases their cost of setup. --- src/locale/__setlocalecat.c | 35 +++++++++++++++++++---------------- 1 file changed, 19 insertions(+), 16 deletions(-) (limited to 'src/locale/__setlocalecat.c') diff --git a/src/locale/__setlocalecat.c b/src/locale/__setlocalecat.c index c93e9ba0..e829da56 100644 --- a/src/locale/__setlocalecat.c +++ b/src/locale/__setlocalecat.c @@ -17,8 +17,9 @@ char *__strchrnul(const char *, int); static struct __locale_map *findlocale(const char *name, size_t n) { + static int lock[2]; static void *volatile loc_head; - struct __locale_map *p, *new, *old_head; + struct __locale_map *p, *new = 0; const char *path = 0, *z; char buf[256]; size_t l; @@ -28,11 +29,18 @@ static struct __locale_map *findlocale(const char *name, size_t n) for (p=loc_head; p; p=p->next) if (!strcmp(name, p->name)) return p; + LOCK(lock); + + for (p=loc_head; p; p=p->next) + if (!strcmp(name, p->name)) { + UNLOCK(lock); + return p; + } + if (!libc.secure) path = getenv("MUSL_LOCPATH"); /* FIXME: add a default path? */ - if (!path) return 0; - for (; *path; path=z+!!*z) { + if (path) for (; *path; path=z+!!*z) { z = __strchrnul(path, ':'); l = z - path - !!*z; if (l >= sizeof buf - n - 2) continue; @@ -45,20 +53,19 @@ static struct __locale_map *findlocale(const char *name, size_t n) new = malloc(sizeof *new); if (!new) { __munmap((void *)map, map_size); - return 0; + break; } new->map = map; new->map_size = map_size; memcpy(new->name, name, n); new->name[n] = 0; - do { - old_head = loc_head; - new->next = old_head; - } while (a_cas_p(&loc_head, old_head, new) != old_head); - return new; + new->next = loc_head; + loc_head = new; + break; } } - return 0; + UNLOCK(lock); + return new; } static const char envvars[][12] = { @@ -85,11 +92,10 @@ int __setlocalecat(locale_t loc, int cat, const char *val) int builtin = (val[0]=='C' && !val[1]) || !strcmp(val, "C.UTF-8") || !strcmp(val, "POSIX"); - struct __locale_map *data, *old; switch (cat) { case LC_CTYPE: - a_store(&loc->ctype_utf8, !builtin || val[1]=='.'); + loc->ctype_utf8 = !builtin || val[1]=='.'; break; case LC_MESSAGES: if (builtin) { @@ -100,10 +106,7 @@ int __setlocalecat(locale_t loc, int cat, const char *val) } /* fall through */ default: - data = builtin ? 0 : findlocale(val, n); - if (data == loc->cat[cat-2]) break; - do old = loc->cat[cat-2]; - while (a_cas_p(&loc->cat[cat-2], old, data) != old); + loc->cat[cat-2] = builtin ? 0 : findlocale(val, n); case LC_NUMERIC: break; } -- cgit v1.2.1