diff options
Diffstat (limited to 'toolchain/uClibc/uClibc-0.9.28-500-mutex-cancel.patch')
-rw-r--r-- | toolchain/uClibc/uClibc-0.9.28-500-mutex-cancel.patch | 8631 |
1 files changed, 8631 insertions, 0 deletions
diff --git a/toolchain/uClibc/uClibc-0.9.28-500-mutex-cancel.patch b/toolchain/uClibc/uClibc-0.9.28-500-mutex-cancel.patch new file mode 100644 index 000000000..5e56a7397 --- /dev/null +++ b/toolchain/uClibc/uClibc-0.9.28-500-mutex-cancel.patch @@ -0,0 +1,8631 @@ +diff --git a/include/printf.h b/include/printf.h +index 340b6cb..2dea58f 100644 +--- a/include/printf.h ++++ b/include/printf.h +@@ -75,6 +75,7 @@ struct printf_info + unsigned int is_short:1; /* h flag. */ + unsigned int is_long:1; /* l flag. */ + unsigned int is_long_double:1;/* L flag. */ ++ unsigned int __padding:20;/* non-gnu -- total of 32 bits on 32bit arch */ + + #elif __BYTE_ORDER == __BIG_ENDIAN + +diff --git a/include/pthread.h b/include/pthread.h +index 8c01172..cee112b 100644 +--- a/include/pthread.h ++++ b/include/pthread.h +@@ -644,7 +644,8 @@ extern void _pthread_cleanup_pop (struct + /* Install a cleanup handler as pthread_cleanup_push does, but also + saves the current cancellation type and set it to deferred cancellation. */ + +-#ifdef __USE_GNU ++/* #ifdef __USE_GNU */ ++#if defined(__USE_GNU) || defined(_LIBC) + # define pthread_cleanup_push_defer_np(routine,arg) \ + { struct _pthread_cleanup_buffer _buffer; \ + _pthread_cleanup_push_defer (&_buffer, (routine), (arg)); +diff --git a/libc/inet/getnetent.c b/libc/inet/getnetent.c +index 181c5ad..659bf5d 100644 +--- a/libc/inet/getnetent.c ++++ b/libc/inet/getnetent.c +@@ -22,18 +22,9 @@ + #include <netdb.h> + #include <arpa/inet.h> + ++#include <bits/uClibc_mutex.h> + +-#ifdef __UCLIBC_HAS_THREADS__ +-#include <pthread.h> +-static pthread_mutex_t mylock = PTHREAD_MUTEX_INITIALIZER; +-# define LOCK __pthread_mutex_lock(&mylock) +-# define UNLOCK __pthread_mutex_unlock(&mylock); +-#else +-# define LOCK +-# define UNLOCK +-#endif +- +- ++__UCLIBC_MUTEX_STATIC(mylock, PTHREAD_MUTEX_INITIALIZER); + + #define MAXALIASES 35 + static const char NETDB[] = _PATH_NETWORKS; +@@ -46,25 +37,25 @@ int _net_stayopen; + + void setnetent(int f) + { +- LOCK; ++ __UCLIBC_MUTEX_LOCK(mylock); + if (netf == NULL) +- netf = fopen(NETDB, "r" ); ++ netf = fopen(NETDB, "r" ); + else +- rewind(netf); ++ rewind(netf); + _net_stayopen |= f; +- UNLOCK; ++ __UCLIBC_MUTEX_UNLOCK(mylock); + return; + } + + void endnetent(void) + { +- LOCK; ++ __UCLIBC_MUTEX_LOCK(mylock); + if (netf) { +- fclose(netf); +- netf = NULL; ++ fclose(netf); ++ netf = NULL; + } + _net_stayopen = 0; +- UNLOCK; ++ __UCLIBC_MUTEX_UNLOCK(mylock); + } + + static char * any(register char *cp, char *match) +@@ -72,10 +63,10 @@ static char * any(register char *cp, cha + register char *mp, c; + + while ((c = *cp)) { +- for (mp = match; *mp; mp++) +- if (*mp == c) +- return (cp); +- cp++; ++ for (mp = match; *mp; mp++) ++ if (*mp == c) ++ return (cp); ++ cp++; + } + return ((char *)0); + } +@@ -84,59 +75,62 @@ struct netent * getnetent(void) + { + char *p; + register char *cp, **q; ++ struct netent *rv = NULL; + +- LOCK; ++ __UCLIBC_MUTEX_LOCK(mylock); + if (netf == NULL && (netf = fopen(NETDB, "r" )) == NULL) { +- UNLOCK; +- return (NULL); ++ goto DONE; + } +-again: ++ again: + + if (!line) { +- line = malloc(BUFSIZ + 1); +- if (!line) +- abort(); ++ line = malloc(BUFSIZ + 1); ++ if (!line) ++ abort(); + } + + p = fgets(line, BUFSIZ, netf); + if (p == NULL) { +- UNLOCK; +- return (NULL); ++ goto DONE; + } + if (*p == '#') +- goto again; ++ goto again; + cp = any(p, "#\n"); + if (cp == NULL) +- goto again; ++ goto again; + *cp = '\0'; + net.n_name = p; + cp = any(p, " \t"); + if (cp == NULL) +- goto again; ++ goto again; + *cp++ = '\0'; + while (*cp == ' ' || *cp == '\t') +- cp++; ++ cp++; + p = any(cp, " \t"); + if (p != NULL) +- *p++ = '\0'; ++ *p++ = '\0'; + net.n_net = inet_network(cp); + net.n_addrtype = AF_INET; + q = net.n_aliases = net_aliases; + if (p != NULL) +- cp = p; ++ cp = p; + while (cp && *cp) { +- if (*cp == ' ' || *cp == '\t') { +- cp++; +- continue; +- } +- if (q < &net_aliases[MAXALIASES - 1]) +- *q++ = cp; +- cp = any(cp, " \t"); +- if (cp != NULL) +- *cp++ = '\0'; ++ if (*cp == ' ' || *cp == '\t') { ++ cp++; ++ continue; ++ } ++ if (q < &net_aliases[MAXALIASES - 1]) ++ *q++ = cp; ++ cp = any(cp, " \t"); ++ if (cp != NULL) ++ *cp++ = '\0'; + } + *q = NULL; +- UNLOCK; +- return (&net); ++ ++ rv = &net; ++ ++ DONE: ++ __UCLIBC_MUTEX_UNLOCK(mylock); ++ return rv; + } + +diff --git a/libc/inet/getproto.c b/libc/inet/getproto.c +index c9f35f1..3665d89 100644 +--- a/libc/inet/getproto.c ++++ b/libc/inet/getproto.c +@@ -62,17 +62,9 @@ + #include <string.h> + #include <errno.h> + +-#ifdef __UCLIBC_HAS_THREADS__ +-#include <pthread.h> +-static pthread_mutex_t mylock = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP; +-# define LOCK __pthread_mutex_lock(&mylock) +-# define UNLOCK __pthread_mutex_unlock(&mylock); +-#else +-# define LOCK +-# define UNLOCK +-#endif +- ++#include <bits/uClibc_mutex.h> + ++__UCLIBC_MUTEX_STATIC(mylock, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP); + + #define MAXALIASES 35 + #define SBUFSIZE (BUFSIZ + 1 + (sizeof(char *) * MAXALIASES)) +@@ -85,109 +77,114 @@ static int proto_stayopen; + static void __initbuf(void) + { + if (!static_aliases) { +- static_aliases = malloc(SBUFSIZE); +- if (!static_aliases) +- abort(); ++ static_aliases = malloc(SBUFSIZE); ++ if (!static_aliases) ++ abort(); + } + } + + void setprotoent(int f) + { +- LOCK; ++ __UCLIBC_MUTEX_LOCK(mylock); + if (protof == NULL) +- protof = fopen(_PATH_PROTOCOLS, "r" ); ++ protof = fopen(_PATH_PROTOCOLS, "r" ); + else +- rewind(protof); ++ rewind(protof); + proto_stayopen |= f; +- UNLOCK; ++ __UCLIBC_MUTEX_UNLOCK(mylock); + } + + void endprotoent(void) + { +- LOCK; ++ __UCLIBC_MUTEX_LOCK(mylock); + if (protof) { +- fclose(protof); +- protof = NULL; ++ fclose(protof); ++ protof = NULL; + } + proto_stayopen = 0; +- UNLOCK; ++ __UCLIBC_MUTEX_UNLOCK(mylock); + } + + int getprotoent_r(struct protoent *result_buf, +- char *buf, size_t buflen, +- struct protoent **result) ++ char *buf, size_t buflen, ++ struct protoent **result) + { + char *p; + register char *cp, **q; + char **proto_aliases; + char *line; ++ int rv; + + *result = NULL; + + if (buflen < sizeof(*proto_aliases)*MAXALIASES) { +- errno=ERANGE; +- return errno; ++ errno=ERANGE; ++ return errno; + } +- LOCK; ++ ++ __UCLIBC_MUTEX_LOCK(mylock); + proto_aliases=(char **)buf; + buf+=sizeof(*proto_aliases)*MAXALIASES; + buflen-=sizeof(*proto_aliases)*MAXALIASES; + + if (buflen < BUFSIZ+1) { +- UNLOCK; +- errno=ERANGE; +- return errno; ++ errno=rv=ERANGE; ++ goto DONE; + } + line=buf; + buf+=BUFSIZ+1; + buflen-=BUFSIZ+1; + + if (protof == NULL && (protof = fopen(_PATH_PROTOCOLS, "r" )) == NULL) { +- UNLOCK; +- return errno; ++ rv=errno; ++ goto DONE; + } +-again: ++ again: + if ((p = fgets(line, BUFSIZ, protof)) == NULL) { +- UNLOCK; +- return TRY_AGAIN; ++ rv=TRY_AGAIN; ++ goto DONE; + } + + if (*p == '#') +- goto again; ++ goto again; + cp = strpbrk(p, "#\n"); + if (cp == NULL) +- goto again; ++ goto again; + *cp = '\0'; + result_buf->p_name = p; + cp = strpbrk(p, " \t"); + if (cp == NULL) +- goto again; ++ goto again; + *cp++ = '\0'; + while (*cp == ' ' || *cp == '\t') +- cp++; ++ cp++; + p = strpbrk(cp, " \t"); + if (p != NULL) +- *p++ = '\0'; ++ *p++ = '\0'; + result_buf->p_proto = atoi(cp); + q = result_buf->p_aliases = proto_aliases; + if (p != NULL) { +- cp = p; +- while (cp && *cp) { +- if (*cp == ' ' || *cp == '\t') { +- cp++; +- continue; +- } +- if (q < &proto_aliases[MAXALIASES - 1]) +- *q++ = cp; +- cp = strpbrk(cp, " \t"); +- if (cp != NULL) +- *cp++ = '\0'; +- } ++ cp = p; ++ while (cp && *cp) { ++ if (*cp == ' ' || *cp == '\t') { ++ cp++; ++ continue; ++ } ++ if (q < &proto_aliases[MAXALIASES - 1]) ++ *q++ = cp; ++ cp = strpbrk(cp, " \t"); ++ if (cp != NULL) ++ *cp++ = '\0'; ++ } + } + *q = NULL; + *result=result_buf; +- UNLOCK; +- return 0; ++ ++ rv = 0; ++ ++ DONE: ++ __UCLIBC_MUTEX_UNLOCK(mylock); ++ return rv; + } + + struct protoent * getprotoent(void) +@@ -201,26 +198,26 @@ struct protoent * getprotoent(void) + + + int getprotobyname_r(const char *name, +- struct protoent *result_buf, +- char *buf, size_t buflen, +- struct protoent **result) ++ struct protoent *result_buf, ++ char *buf, size_t buflen, ++ struct protoent **result) + { + register char **cp; + int ret; + +- LOCK; ++ __UCLIBC_MUTEX_LOCK(mylock); + setprotoent(proto_stayopen); + while (!(ret=getprotoent_r(result_buf, buf, buflen, result))) { +- if (strcmp(result_buf->p_name, name) == 0) +- break; +- for (cp = result_buf->p_aliases; *cp != 0; cp++) +- if (strcmp(*cp, name) == 0) +- goto found; ++ if (strcmp(result_buf->p_name, name) == 0) ++ break; ++ for (cp = result_buf->p_aliases; *cp != 0; cp++) ++ if (strcmp(*cp, name) == 0) ++ goto found; + } +-found: ++ found: + if (!proto_stayopen) +- endprotoent(); +- UNLOCK; ++ endprotoent(); ++ __UCLIBC_MUTEX_UNLOCK(mylock); + return *result?0:ret; + } + +@@ -236,20 +233,20 @@ struct protoent * getprotobyname(const c + + + int getprotobynumber_r (int proto_num, +- struct protoent *result_buf, +- char *buf, size_t buflen, +- struct protoent **result) ++ struct protoent *result_buf, ++ char *buf, size_t buflen, ++ struct protoent **result) + { + int ret; + +- LOCK; ++ __UCLIBC_MUTEX_LOCK(mylock); + setprotoent(proto_stayopen); + while (!(ret=getprotoent_r(result_buf, buf, buflen, result))) +- if (result_buf->p_proto == proto_num) +- break; ++ if (result_buf->p_proto == proto_num) ++ break; + if (!proto_stayopen) +- endprotoent(); +- UNLOCK; ++ endprotoent(); ++ __UCLIBC_MUTEX_UNLOCK(mylock); + return *result?0:ret; + } + +diff --git a/libc/inet/getservice.c b/libc/inet/getservice.c +index cbe5c50..b666057 100644 +--- a/libc/inet/getservice.c ++++ b/libc/inet/getservice.c +@@ -65,20 +65,9 @@ + #include <arpa/inet.h> + #include <errno.h> + ++#include <bits/uClibc_mutex.h> + +- +-#ifdef __UCLIBC_HAS_THREADS__ +-#include <pthread.h> +-static pthread_mutex_t mylock = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP; +-# define LOCK __pthread_mutex_lock(&mylock) +-# define UNLOCK __pthread_mutex_unlock(&mylock); +-#else +-# define LOCK +-# define UNLOCK +-#endif +- +- +- ++__UCLIBC_MUTEX_STATIC(mylock, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP); + + #define MAXALIASES 35 + #define SBUFSIZE (BUFSIZ + 1 + (sizeof(char *) * MAXALIASES)) +@@ -91,32 +80,32 @@ static int serv_stayopen; + static void __initbuf(void) + { + if (!servbuf) { +- servbuf = malloc(SBUFSIZE); +- if (!servbuf) +- abort(); ++ servbuf = malloc(SBUFSIZE); ++ if (!servbuf) ++ abort(); + } + } + + void setservent(int f) + { +- LOCK; ++ __UCLIBC_MUTEX_LOCK(mylock); + if (servf == NULL) +- servf = fopen(_PATH_SERVICES, "r" ); ++ servf = fopen(_PATH_SERVICES, "r" ); + else +- rewind(servf); ++ rewind(servf); + serv_stayopen |= f; +- UNLOCK; ++ __UCLIBC_MUTEX_UNLOCK(mylock); + } + + void endservent(void) + { +- LOCK; ++ __UCLIBC_MUTEX_LOCK(mylock); + if (servf) { +- fclose(servf); +- servf = NULL; ++ fclose(servf); ++ servf = NULL; + } + serv_stayopen = 0; +- UNLOCK; ++ __UCLIBC_MUTEX_UNLOCK(mylock); + } + + struct servent * getservent(void) +@@ -149,127 +138,129 @@ struct servent * getservbyport(int port, + } + + int getservent_r(struct servent * result_buf, +- char * buf, size_t buflen, +- struct servent ** result) ++ char * buf, size_t buflen, ++ struct servent ** result) + { + char *p; + register char *cp, **q; + char **serv_aliases; + char *line; ++ int rv; + + *result=NULL; + + if (buflen < sizeof(*serv_aliases)*MAXALIASES) { +- errno=ERANGE; +- return errno; ++ errno=ERANGE; ++ return errno; + } +- LOCK; ++ __UCLIBC_MUTEX_LOCK(mylock); + serv_aliases=(char **)buf; + buf+=sizeof(*serv_aliases)*MAXALIASES; + buflen-=sizeof(*serv_aliases)*MAXALIASES; + + if (buflen < BUFSIZ+1) { +- UNLOCK; +- errno=ERANGE; +- return errno; ++ errno=rv=ERANGE; ++ goto DONE; + } + line=buf; + buf+=BUFSIZ+1; + buflen-=BUFSIZ+1; + + if (servf == NULL && (servf = fopen(_PATH_SERVICES, "r" )) == NULL) { +- UNLOCK; +- errno=EIO; +- return errno; ++ errno=rv=EIO; ++ goto DONE; + } +-again: ++ again: + if ((p = fgets(line, BUFSIZ, servf)) == NULL) { +- UNLOCK; +- errno=EIO; +- return errno; ++ errno=rv=EIO; ++ goto DONE; + } + if (*p == '#') +- goto again; ++ goto again; + cp = strpbrk(p, "#\n"); + if (cp == NULL) +- goto again; ++ goto again; + *cp = '\0'; + result_buf->s_name = p; + p = strpbrk(p, " \t"); + if (p == NULL) +- goto again; ++ goto again; + *p++ = '\0'; + while (*p == ' ' || *p == '\t') +- p++; ++ p++; + cp = strpbrk(p, ",/"); + if (cp == NULL) +- goto again; ++ goto again; + *cp++ = '\0'; + result_buf->s_port = htons((u_short)atoi(p)); + result_buf->s_proto = cp; + q = result_buf->s_aliases = serv_aliases; + cp = strpbrk(cp, " \t"); + if (cp != NULL) +- *cp++ = '\0'; ++ *cp++ = '\0'; + while (cp && *cp) { +- if (*cp == ' ' || *cp == '\t') { +- cp++; +- continue; +- } +- if (q < &serv_aliases[MAXALIASES - 1]) +- *q++ = cp; +- cp = strpbrk(cp, " \t"); +- if (cp != NULL) +- *cp++ = '\0'; ++ if (*cp == ' ' || *cp == '\t') { ++ cp++; ++ continue; ++ } ++ if (q < &serv_aliases[MAXALIASES - 1]) ++ *q++ = cp; ++ cp = strpbrk(cp, " \t"); ++ if (cp != NULL) ++ *cp++ = '\0'; + } + *q = NULL; + *result=result_buf; +- UNLOCK; +- return 0; ++ ++ rv = 0; ++ ++ DONE: ++ __UCLIBC_MUTEX_UNLOCK(mylock); ++ return rv; + } + + int getservbyname_r(const char *name, const char *proto, +- struct servent * result_buf, char * buf, size_t buflen, +- struct servent ** result) ++ struct servent * result_buf, char * buf, size_t buflen, ++ struct servent ** result) + { + register char **cp; + int ret; + +- LOCK; ++ __UCLIBC_MUTEX_LOCK(mylock); + setservent(serv_stayopen); + while (!(ret=getservent_r(result_buf, buf, buflen, result))) { +- if (strcmp(name, result_buf->s_name) == 0) +- goto gotname; +- for (cp = result_buf->s_aliases; *cp; cp++) +- if (strcmp(name, *cp) == 0) +- goto gotname; +- continue; +-gotname: +- if (proto == 0 || strcmp(result_buf->s_proto, proto) == 0) +- break; ++ if (strcmp(name, result_buf->s_name) == 0) ++ goto gotname; ++ for (cp = result_buf->s_aliases; *cp; cp++) ++ if (strcmp(name, *cp) == 0) ++ goto gotname; ++ continue; ++ gotname: ++ if (proto == 0 || strcmp(result_buf->s_proto, proto) == 0) ++ break; + } + if (!serv_stayopen) +- endservent(); +- UNLOCK; ++ endservent(); ++ __UCLIBC_MUTEX_UNLOCK(mylock); + return *result?0:ret; + } + + int getservbyport_r(int port, const char *proto, +- struct servent * result_buf, char * buf, +- size_t buflen, struct servent ** result) ++ struct servent * result_buf, char * buf, ++ size_t buflen, struct servent ** result) + { + int ret; + +- LOCK; ++ __UCLIBC_MUTEX_LOCK(mylock); + setservent(serv_stayopen); + while (!(ret=getservent_r(result_buf, buf, buflen, result))) { +- if (result_buf->s_port != port) +- continue; +- if (proto == 0 || strcmp(result_buf->s_proto, proto) == 0) +- break; ++ if (result_buf->s_port != port) ++ continue; ++ if (proto == 0 || strcmp(result_buf->s_proto, proto) == 0) ++ break; + } + if (!serv_stayopen) +- endservent(); +- UNLOCK; ++ endservent(); ++ __UCLIBC_MUTEX_UNLOCK(mylock); + return *result?0:ret; + } +diff --git a/libc/inet/resolv.c b/libc/inet/resolv.c +index 27b60ef..0f583ab 100644 +--- a/libc/inet/resolv.c ++++ b/libc/inet/resolv.c +@@ -7,7 +7,7 @@ + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. +-*/ ++ */ + + /* + * Portions Copyright (c) 1985, 1993 +@@ -153,6 +153,11 @@ + #include <sys/utsname.h> + #include <sys/un.h> + ++#include <bits/uClibc_mutex.h> ++ ++__UCLIBC_MUTEX_EXTERN(__resolv_lock); ++ ++ + #define MAX_RECURSE 5 + #define REPLY_TIMEOUT 10 + #define MAX_RETRIES 3 +@@ -180,18 +185,6 @@ extern char * __nameserver[MAX_SERVERS]; + extern int __searchdomains; + extern char * __searchdomain[MAX_SEARCH]; + +-#ifdef __UCLIBC_HAS_THREADS__ +-#include <pthread.h> +-extern pthread_mutex_t __resolv_lock; +-# define BIGLOCK __pthread_mutex_lock(&__resolv_lock) +-# define BIGUNLOCK __pthread_mutex_unlock(&__resolv_lock); +-#else +-# define BIGLOCK +-# define BIGUNLOCK +-#endif +- +- +- + /* Structs */ + struct resolv_header { + int id; +@@ -229,49 +222,49 @@ enum etc_hosts_action { + + /* function prototypes */ + extern int __get_hosts_byname_r(const char * name, int type, +- struct hostent * result_buf, +- char * buf, size_t buflen, +- struct hostent ** result, +- int * h_errnop); ++ struct hostent * result_buf, ++ char * buf, size_t buflen, ++ struct hostent ** result, ++ int * h_errnop); + extern int __get_hosts_byaddr_r(const char * addr, int len, int type, +- struct hostent * result_buf, +- char * buf, size_t buflen, +- struct hostent ** result, +- int * h_errnop); ++ struct hostent * result_buf, ++ char * buf, size_t buflen, ++ struct hostent ** result, ++ int * h_errnop); + extern void __open_etc_hosts(FILE **fp); + extern int __read_etc_hosts_r(FILE *fp, const char * name, int type, +- enum etc_hosts_action action, +- struct hostent * result_buf, +- char * buf, size_t buflen, +- struct hostent ** result, +- int * h_errnop); ++ enum etc_hosts_action action, ++ struct hostent * result_buf, ++ char * buf, size_t buflen, ++ struct hostent ** result, ++ int * h_errnop); + extern int __dns_lookup(const char * name, int type, int nscount, +- char ** nsip, unsigned char ** outpacket, struct resolv_answer * a); ++ char ** nsip, unsigned char ** outpacket, struct resolv_answer * a); + + extern int __encode_dotted(const char * dotted, unsigned char * dest, int maxlen); + extern int __decode_dotted(const unsigned char * message, int offset, +- char * dest, int maxlen); ++ char * dest, int maxlen); + extern int __length_dotted(const unsigned char * message, int offset); + extern int __encode_header(struct resolv_header * h, unsigned char * dest, int maxlen); + extern int __decode_header(unsigned char * data, struct resolv_header * h); + extern int __encode_question(struct resolv_question * q, +- unsigned char * dest, int maxlen); ++ unsigned char * dest, int maxlen); + extern int __decode_question(unsigned char * message, int offset, +- struct resolv_question * q); ++ struct resolv_question * q); + extern int __encode_answer(struct resolv_answer * a, +- unsigned char * dest, int maxlen); ++ unsigned char * dest, int maxlen); + extern int __decode_answer(unsigned char * message, int offset, +- struct resolv_answer * a); ++ struct resolv_answer * a); + extern int __length_question(unsigned char * message, int offset); + extern int __open_nameservers(void); + extern void __close_nameservers(void); + extern int __dn_expand(const u_char *, const u_char *, const u_char *, +- char *, int); ++ char *, int); + extern int __ns_name_uncompress(const u_char *, const u_char *, +- const u_char *, char *, size_t); ++ const u_char *, char *, size_t); + extern int __ns_name_ntop(const u_char *, char *, size_t); + extern int __ns_name_unpack(const u_char *, const u_char *, const u_char *, +- u_char *, size_t); ++ u_char *, size_t); + + + #ifdef L_encodeh +@@ -361,7 +354,7 @@ int __encode_dotted(const char *dotted, + This routine understands compressed data. */ + + int __decode_dotted(const unsigned char *data, int offset, +- char *dest, int maxlen) ++ char *dest, int maxlen) + { + int l; + int measure = 1; +@@ -435,7 +428,7 @@ int __length_dotted(const unsigned char + + #ifdef L_encodeq + int __encode_question(struct resolv_question *q, +- unsigned char *dest, int maxlen) ++ unsigned char *dest, int maxlen) + { + int i; + +@@ -460,7 +453,7 @@ int __encode_question(struct resolv_ques + + #ifdef L_decodeq + int __decode_question(unsigned char *message, int offset, +- struct resolv_question *q) ++ struct resolv_question *q) + { + char temp[256]; + int i; +@@ -525,7 +518,7 @@ int __encode_answer(struct resolv_answer + + #ifdef L_decodea + int __decode_answer(unsigned char *message, int offset, +- struct resolv_answer *a) ++ struct resolv_answer *a) + { + char temp[256]; + int i; +@@ -557,11 +550,11 @@ int __decode_answer(unsigned char *messa + + #ifdef L_encodep + int __encode_packet(struct resolv_header *h, +- struct resolv_question **q, +- struct resolv_answer **an, +- struct resolv_answer **ns, +- struct resolv_answer **ar, +- unsigned char *dest, int maxlen) ++ struct resolv_question **q, ++ struct resolv_answer **an, ++ struct resolv_answer **ns, ++ struct resolv_answer **ar, ++ unsigned char *dest, int maxlen) + { + int i, total = 0; + int j; +@@ -621,7 +614,7 @@ int __decode_packet(unsigned char *data, + + #ifdef L_formquery + int __form_query(int id, const char *name, int type, unsigned char *packet, +- int maxlen) ++ int maxlen) + { + struct resolv_header h; + struct resolv_question q; +@@ -649,14 +642,7 @@ int __form_query(int id, const char *nam + + #ifdef L_dnslookup + +-#ifdef __UCLIBC_HAS_THREADS__ +-static pthread_mutex_t mylock = PTHREAD_MUTEX_INITIALIZER; +-# define LOCK __pthread_mutex_lock(&mylock) +-# define UNLOCK __pthread_mutex_unlock(&mylock); +-#else +-# define LOCK +-# define UNLOCK +-#endif ++__UCLIBC_MUTEX_STATIC(mylock, PTHREAD_MUTEX_INITIALIZER); + + /* Just for the record, having to lock __dns_lookup() just for these two globals + * is pretty lame. I think these two variables can probably be de-global-ized, +@@ -665,7 +651,7 @@ static pthread_mutex_t mylock = PTHREAD_ + static int ns=0, id=1; + + int __dns_lookup(const char *name, int type, int nscount, char **nsip, +- unsigned char **outpacket, struct resolv_answer *a) ++ unsigned char **outpacket, struct resolv_answer *a) + { + int i, j, len, fd, pos, rc; + struct timeval tv; +@@ -693,10 +679,10 @@ int __dns_lookup(const char *name, int t + DPRINTF("Looking up type %d answer for '%s'\n", type, name); + + /* Mess with globals while under lock */ +- LOCK; ++ __UCLIBC_MUTEX_LOCK(mylock); + local_ns = ns % nscount; + local_id = id; +- UNLOCK; ++ __UCLIBC_MUTEX_UNLOCK(mylock); + + while (retries < MAX_RETRIES) { + if (fd != -1) +@@ -722,13 +708,13 @@ int __dns_lookup(const char *name, int t + + strncpy(lookup,name,MAXDNAME); + if (variant >= 0) { +- BIGLOCK; +- if (variant < __searchdomains) { +- strncat(lookup,".", MAXDNAME); +- strncat(lookup,__searchdomain[variant], MAXDNAME); +- } +- BIGUNLOCK; +- } ++ __UCLIBC_MUTEX_LOCK(__resolv_lock); ++ if (variant < __searchdomains) { ++ strncat(lookup,".", MAXDNAME); ++ strncat(lookup,__searchdomain[variant], MAXDNAME); ++ } ++ __UCLIBC_MUTEX_UNLOCK(__resolv_lock); ++ } + DPRINTF("lookup name: %s\n", lookup); + q.dotted = (char *)lookup; + q.qtype = type; +@@ -750,7 +736,7 @@ int __dns_lookup(const char *name, int t + fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + #endif + if (fd < 0) { +- retries++; ++ retries++; + continue; + } + +@@ -772,11 +758,11 @@ int __dns_lookup(const char *name, int t + #endif + if (rc < 0) { + if (errno == ENETUNREACH) { +- /* routing error, presume not transient */ +- goto tryall; ++ /* routing error, presume not transient */ ++ goto tryall; + } else +- /* retry */ +- retries++; ++ /* retry */ ++ retries++; + continue; + } + +@@ -838,55 +824,55 @@ int __dns_lookup(const char *name, int t + + first_answer = 1; + for (j=0;j<h.ancount;j++,pos += i) +- { +- i = __decode_answer(packet, pos, &ma); ++ { ++ i = __decode_answer(packet, pos, &ma); + +- if (i<0) { +- DPRINTF("failed decode %d\n", i); +- goto again; +- } ++ if (i<0) { ++ DPRINTF("failed decode %d\n", i); ++ goto again; ++ } + +- if ( first_answer ) +- { +- ma.buf = a->buf; +- ma.buflen = a->buflen; +- ma.add_count = a->add_count; +- memcpy(a, &ma, sizeof(ma)); +- if (a->atype != T_SIG && (0 == a->buf || (type != T_A && type != T_AAAA))) +- { +- break; +- } +- if (a->atype != type) +- { +- free(a->dotted); +- continue; +- } +- a->add_count = h.ancount - j - 1; +- if ((a->rdlength + sizeof(struct in_addr*)) * a->add_count > a->buflen) +- { +- break; +- } +- a->add_count = 0; +- first_answer = 0; +- } +- else +- { +- free(ma.dotted); +- if (ma.atype != type) +- { +- continue; +- } +- if (a->rdlength != ma.rdlength) +- { +- free(a->dotted); +- DPRINTF("Answer address len(%u) differs from original(%u)\n", +- ma.rdlength, a->rdlength); +- goto again; ++ if ( first_answer ) ++ { ++ ma.buf = a->buf; ++ ma.buflen = a->buflen; ++ ma.add_count = a->add_count; ++ memcpy(a, &ma, sizeof(ma)); ++ if (a->atype != T_SIG && (0 == a->buf || (type != T_A && type != T_AAAA))) ++ { ++ break; ++ } ++ if (a->atype != type) ++ { ++ free(a->dotted); ++ continue; ++ } ++ a->add_count = h.ancount - j - 1; ++ if ((a->rdlength + sizeof(struct in_addr*)) * a->add_count > a->buflen) ++ { ++ break; ++ } ++ a->add_count = 0; ++ first_answer = 0; ++ } ++ else ++ { ++ free(ma.dotted); ++ if (ma.atype != type) ++ { ++ continue; ++ } ++ if (a->rdlength != ma.rdlength) ++ { ++ free(a->dotted); ++ DPRINTF("Answer address len(%u) differs from original(%u)\n", ++ ma.rdlength, a->rdlength); ++ goto again; ++ } ++ memcpy(a->buf + (a->add_count * ma.rdlength), ma.rdata, ma.rdlength); ++ ++a->add_count; ++ } + } +- memcpy(a->buf + (a->add_count * ma.rdlength), ma.rdata, ma.rdlength); +- ++a->add_count; +- } +- } + + DPRINTF("Answer name = |%s|\n", a->dotted); + DPRINTF("Answer type = |%d|\n", a->atype); +@@ -900,48 +886,48 @@ int __dns_lookup(const char *name, int t + free(lookup); + + /* Mess with globals while under lock */ +- LOCK; ++ __UCLIBC_MUTEX_LOCK(mylock); + ns = local_ns; + id = local_id; +- UNLOCK; ++ __UCLIBC_MUTEX_UNLOCK(mylock); + + return (len); /* success! */ + +- tryall: ++ tryall: + /* if there are other nameservers, give them a go, + otherwise return with error */ + { + variant = -1; +- local_ns = (local_ns + 1) % nscount; +- if (local_ns == 0) +- retries++; ++ local_ns = (local_ns + 1) % nscount; ++ if (local_ns == 0) ++ retries++; + +- continue; ++ continue; + } + +- again: ++ again: + /* if there are searchdomains, try them or fallback as passed */ + { + int sdomains; +- BIGLOCK; ++ __UCLIBC_MUTEX_LOCK(__resolv_lock); + sdomains=__searchdomains; +- BIGUNLOCK; ++ __UCLIBC_MUTEX_UNLOCK(__resolv_lock); + + if (variant < sdomains - 1) { +- /* next search */ +- variant++; ++ /* next search */ ++ variant++; + } else { +- /* next server, first search */ +- local_ns = (local_ns + 1) % nscount; +- if (local_ns == 0) +- retries++; ++ /* next server, first search */ ++ local_ns = (local_ns + 1) % nscount; ++ if (local_ns == 0) ++ retries++; + +- variant = -1; ++ variant = -1; + } + } + } + +-fail: ++ fail: + if (fd != -1) + close(fd); + if (lookup) +@@ -951,10 +937,10 @@ fail: + h_errno = NETDB_INTERNAL; + /* Mess with globals while under lock */ + if (local_ns != -1) { +- LOCK; ++ __UCLIBC_MUTEX_LOCK(mylock); + ns = local_ns; + id = local_id; +- UNLOCK; ++ __UCLIBC_MUTEX_UNLOCK(mylock); + } + return -1; + } +@@ -966,9 +952,8 @@ int __nameservers; + char * __nameserver[MAX_SERVERS]; + int __searchdomains; + char * __searchdomain[MAX_SEARCH]; +-#ifdef __UCLIBC_HAS_THREADS__ +-pthread_mutex_t __resolv_lock = PTHREAD_MUTEX_INITIALIZER; +-#endif ++ ++__UCLIBC_MUTEX_INIT(__resolv_lock, PTHREAD_MUTEX_INITIALIZER); + + /* + * we currently read formats not quite the same as that on normal +@@ -982,60 +967,63 @@ int __open_nameservers() + #define RESOLV_ARGS 5 + char szBuffer[128], *p, *argv[RESOLV_ARGS]; + int argc; ++ int rv = 0; + +- BIGLOCK; ++ __UCLIBC_MUTEX_LOCK(__resolv_lock); + if (__nameservers > 0) { +- BIGUNLOCK; +- return 0; ++ goto DONE; + } + + if ((fp = fopen("/etc/resolv.conf", "r")) || +- (fp = fopen("/etc/config/resolv.conf", "r"))) +- { +- +- while (fgets(szBuffer, sizeof(szBuffer), fp) != NULL) { ++ (fp = fopen("/etc/config/resolv.conf", "r"))) ++ { + +- for (p = szBuffer; *p && isspace(*p); p++) +- /* skip white space */; +- if (*p == '\0' || *p == '\n' || *p == '#') /* skip comments etc */ +- continue; +- argc = 0; +- while (*p && argc < RESOLV_ARGS) { +- argv[argc++] = p; +- while (*p && !isspace(*p) && *p != '\n') +- p++; +- while (*p && (isspace(*p) || *p == '\n')) /* remove spaces */ +- *p++ = '\0'; +- } ++ while (fgets(szBuffer, sizeof(szBuffer), fp) != NULL) { + +- if (strcmp(argv[0], "nameserver") == 0) { +- for (i = 1; i < argc && __nameservers < MAX_SERVERS; i++) { +- __nameserver[__nameservers++] = strdup(argv[i]); +- DPRINTF("adding nameserver %s\n", argv[i]); ++ for (p = szBuffer; *p && isspace(*p); p++) ++ /* skip white space */; ++ if (*p == '\0' || *p == '\n' || *p == '#') /* skip comments etc */ ++ continue; ++ argc = 0; ++ while (*p && argc < RESOLV_ARGS) { ++ argv[argc++] = p; ++ while (*p && !isspace(*p) && *p != '\n') ++ p++; ++ while (*p && (isspace(*p) || *p == '\n')) /* remove spaces */ ++ *p++ = '\0'; + } +- } + +- /* domain and search are mutually exclusive, the last one wins */ +- if (strcmp(argv[0],"domain")==0 || strcmp(argv[0],"search")==0) { +- while (__searchdomains > 0) { +- free(__searchdomain[--__searchdomains]); +- __searchdomain[__searchdomains] = NULL; ++ if (strcmp(argv[0], "nameserver") == 0) { ++ for (i = 1; i < argc && __nameservers < MAX_SERVERS; i++) { ++ __nameserver[__nameservers++] = strdup(argv[i]); ++ DPRINTF("adding nameserver %s\n", argv[i]); ++ } + } +- for (i=1; i < argc && __searchdomains < MAX_SEARCH; i++) { +- __searchdomain[__searchdomains++] = strdup(argv[i]); +- DPRINTF("adding search %s\n", argv[i]); ++ ++ /* domain and search are mutually exclusive, the last one wins */ ++ if (strcmp(argv[0],"domain")==0 || strcmp(argv[0],"search")==0) { ++ while (__searchdomains > 0) { ++ free(__searchdomain[--__searchdomains]); ++ __searchdomain[__searchdomains] = NULL; ++ } ++ for (i=1; i < argc && __searchdomains < MAX_SEARCH; i++) { ++ __searchdomain[__searchdomains++] = strdup(argv[i]); ++ DPRINTF("adding search %s\n", argv[i]); ++ } + } + } ++ fclose(fp); ++ DPRINTF("nameservers = %d\n", __nameservers); ++ goto DONE; + } +- fclose(fp); +- DPRINTF("nameservers = %d\n", __nameservers); +- BIGUNLOCK; +- return 0; +- } + DPRINTF("failed to open %s\n", "resolv.conf"); + h_errno = NO_RECOVERY; +- BIGUNLOCK; +- return -1; ++ ++ rv = -1; ++ ++ DONE: ++ __UCLIBC_MUTEX_UNLOCK(__resolv_lock); ++ return rv; + } + #endif + +@@ -1044,7 +1032,7 @@ int __open_nameservers() + + void __close_nameservers(void) + { +- BIGLOCK; ++ __UCLIBC_MUTEX_LOCK(__resolv_lock); + while (__nameservers > 0) { + free(__nameserver[--__nameservers]); + __nameserver[__nameservers] = NULL; +@@ -1053,7 +1041,7 @@ void __close_nameservers(void) + free(__searchdomain[--__searchdomains]); + __searchdomain[__searchdomains] = NULL; + } +- BIGUNLOCK; ++ __UCLIBC_MUTEX_UNLOCK(__resolv_lock); + } + #endif + +@@ -1063,8 +1051,8 @@ struct hostent *gethostbyname(const char + { + static struct hostent h; + static char buf[sizeof(struct in_addr) + +- sizeof(struct in_addr *)*2 + +- sizeof(char *)*(ALIAS_DIM) + 384/*namebuffer*/ + 32/* margin */]; ++ sizeof(struct in_addr *)*2 + ++ sizeof(char *)*(ALIAS_DIM) + 384/*namebuffer*/ + 32/* margin */]; + struct hostent *hp; + + gethostbyname_r(name, &h, buf, sizeof(buf), &hp, &h_errno); +@@ -1082,8 +1070,8 @@ struct hostent *gethostbyname2(const cha + #else /* __UCLIBC_HAS_IPV6__ */ + static struct hostent h; + static char buf[sizeof(struct in6_addr) + +- sizeof(struct in6_addr *)*2 + +- sizeof(char *)*(ALIAS_DIM) + 384/*namebuffer*/ + 32/* margin */]; ++ sizeof(struct in6_addr *)*2 + ++ sizeof(char *)*(ALIAS_DIM) + 384/*namebuffer*/ + 32/* margin */]; + struct hostent *hp; + + gethostbyname2_r(name, family, &h, buf, sizeof(buf), &hp, &h_errno); +@@ -1119,7 +1107,7 @@ int res_init(void) + /** rp->rhook = NULL; **/ + /** rp->_u._ext.nsinit = 0; **/ + +- BIGLOCK; ++ __UCLIBC_MUTEX_LOCK(__resolv_lock); + if(__searchdomains) { + int i; + for(i=0; i<__searchdomains; i++) { +@@ -1139,7 +1127,7 @@ int res_init(void) + } + } + rp->nscount = __nameservers; +- BIGUNLOCK; ++ __UCLIBC_MUTEX_UNLOCK(__resolv_lock); + + return(0); + } +@@ -1175,10 +1163,10 @@ int res_query(const char *dname, int cla + + memset((char *) &a, '\0', sizeof(a)); + +- BIGLOCK; ++ __UCLIBC_MUTEX_LOCK(__resolv_lock); + __nameserversXX=__nameservers; + __nameserverXX=__nameserver; +- BIGUNLOCK; ++ __UCLIBC_MUTEX_UNLOCK(__resolv_lock); + i = __dns_lookup(dname, type, __nameserversXX, __nameserverXX, &packet, &a); + + if (i < 0) { +@@ -1207,10 +1195,10 @@ int res_query(const char *dname, int cla + * is detected. Error code, if any, is left in h_errno. + */ + int res_search(name, class, type, answer, anslen) +- const char *name; /* domain name */ +- int class, type; /* class and type of query */ +- u_char *answer; /* buffer to put answer */ +- int anslen; /* size of answer */ ++ const char *name; /* domain name */ ++ int class, type; /* class and type of query */ ++ u_char *answer; /* buffer to put answer */ ++ int anslen; /* size of answer */ + { + const char *cp, * const *domain; + HEADER *hp = (HEADER *)(void *)answer; +@@ -1256,11 +1244,11 @@ int res_search(name, class, type, answer + int done = 0; + + for (domain = (const char * const *)_res.dnsrch; +- *domain && !done; +- domain++) { ++ *domain && !done; ++ domain++) { + + ret = res_querydomain(name, *domain, class, type, +- answer, anslen); ++ answer, anslen); + if (ret > 0) + return (ret); + +@@ -1283,22 +1271,22 @@ int res_search(name, class, type, answer + } + + switch (h_errno) { +- case NO_DATA: +- got_nodata++; +- /* FALLTHROUGH */ +- case HOST_NOT_FOUND: +- /* keep trying */ +- break; +- case TRY_AGAIN: +- if (hp->rcode == SERVFAIL) { +- /* try next search element, if any */ +- got_servfail++; ++ case NO_DATA: ++ got_nodata++; ++ /* FALLTHROUGH */ ++ case HOST_NOT_FOUND: ++ /* keep trying */ + break; +- } +- /* FALLTHROUGH */ +- default: +- /* anything else implies that we're done */ +- done++; ++ case TRY_AGAIN: ++ if (hp->rcode == SERVFAIL) { ++ /* try next search element, if any */ ++ got_servfail++; ++ break; ++ } ++ /* FALLTHROUGH */ ++ default: ++ /* anything else implies that we're done */ ++ done++; + } + /* + * if we got here for some reason other than DNSRCH, +@@ -1342,10 +1330,10 @@ int res_search(name, class, type, answer + * removing a trailing dot from name if domain is NULL. + */ + int res_querydomain(name, domain, class, type, answer, anslen) +- const char *name, *domain; +- int class, type; /* class and type of query */ +- u_char *answer; /* buffer to put answer */ +- int anslen; /* size of answer */ ++ const char *name, *domain; ++ int class, type; /* class and type of query */ ++ u_char *answer; /* buffer to put answer */ ++ int anslen; /* size of answer */ + { + char nbuf[MAXDNAME]; + const char *longname = nbuf; +@@ -1359,7 +1347,7 @@ int res_querydomain(name, domain, class, + #ifdef DEBUG + if (_res.options & RES_DEBUG) + printf(";; res_querydomain(%s, %s, %d, %d)\n", +- name, domain?domain:"<Nil>", class, type); ++ name, domain?domain:"<Nil>", class, type); + #endif + if (domain == NULL) { + /* +@@ -1400,11 +1388,11 @@ struct hostent *gethostbyaddr (const voi + static struct hostent h; + static char buf[ + #ifndef __UCLIBC_HAS_IPV6__ +- sizeof(struct in_addr) + sizeof(struct in_addr *)*2 + ++ sizeof(struct in_addr) + sizeof(struct in_addr *)*2 + + #else +- sizeof(struct in6_addr) + sizeof(struct in6_addr *)*2 + ++ sizeof(struct in6_addr) + sizeof(struct in6_addr *)*2 + + #endif /* __UCLIBC_HAS_IPV6__ */ +- sizeof(char *)*(ALIAS_DIM) + 384/*namebuffer*/ + 32/* margin */]; ++ sizeof(char *)*(ALIAS_DIM) + 384/*namebuffer*/ + 32/* margin */]; + struct hostent *hp; + + gethostbyaddr_r(addr, len, type, &h, buf, sizeof(buf), &hp, &h_errno); +@@ -1425,11 +1413,11 @@ void __open_etc_hosts(FILE **fp) + } + + int __read_etc_hosts_r(FILE * fp, const char * name, int type, +- enum etc_hosts_action action, +- struct hostent * result_buf, +- char * buf, size_t buflen, +- struct hostent ** result, +- int * h_errnop) ++ enum etc_hosts_action action, ++ struct hostent * result_buf, ++ char * buf, size_t buflen, ++ struct hostent ** result, ++ int * h_errnop) + { + struct in_addr *in=NULL; + struct in_addr **addr_list=NULL; +@@ -1576,56 +1564,49 @@ int __read_etc_hosts_r(FILE * fp, const + + #ifdef L_gethostent + +-#ifdef __UCLIBC_HAS_THREADS__ +-static pthread_mutex_t mylock = PTHREAD_MUTEX_INITIALIZER; +-# define LOCK __pthread_mutex_lock(&mylock) +-# define UNLOCK __pthread_mutex_unlock(&mylock); +-#else +-# define LOCK +-# define UNLOCK +-#endif ++__UCLIBC_MUTEX_STATIC(mylock, PTHREAD_MUTEX_INITIALIZER); + + static int __stay_open; + static FILE * __gethostent_fp; + + void endhostent (void) + { +- LOCK; ++ __UCLIBC_MUTEX_LOCK(mylock); + __stay_open = 0; + if (__gethostent_fp) { +- fclose(__gethostent_fp); ++ fclose(__gethostent_fp); + } +- UNLOCK; ++ __UCLIBC_MUTEX_UNLOCK(mylock); + } + + void sethostent (int stay_open) + { +- LOCK; ++ __UCLIBC_MUTEX_LOCK(mylock); + __stay_open = stay_open; +- UNLOCK; ++ __UCLIBC_MUTEX_UNLOCK(mylock); + } + + int gethostent_r(struct hostent *result_buf, char *buf, size_t buflen, +- struct hostent **result, int *h_errnop) ++ struct hostent **result, int *h_errnop) + { +- int ret; ++ int ret = 0; + +- LOCK; ++ __UCLIBC_MUTEX_LOCK(mylock); + if (__gethostent_fp == NULL) { +- __open_etc_hosts(&__gethostent_fp); +- if (__gethostent_fp == NULL) { +- UNLOCK; +- *result=NULL; +- return 0; +- } ++ __open_etc_hosts(&__gethostent_fp); ++ if (__gethostent_fp == NULL) { ++ *result=NULL; ++ goto DONE; ++ } + } + + ret = __read_etc_hosts_r(__gethostent_fp, NULL, AF_INET, GETHOSTENT, +- result_buf, buf, buflen, result, h_errnop); ++ result_buf, buf, buflen, result, h_errnop); + if (__stay_open==0) { +- fclose(__gethostent_fp); ++ fclose(__gethostent_fp); + } +- UNLOCK; ++ DONE: ++ __UCLIBC_MUTEX_UNLOCK(mylock); + return(ret); + } + +@@ -1634,17 +1615,17 @@ struct hostent *gethostent (void) + static struct hostent h; + static char buf[ + #ifndef __UCLIBC_HAS_IPV6__ +- sizeof(struct in_addr) + sizeof(struct in_addr *)*2 + ++ sizeof(struct in_addr) + sizeof(struct in_addr *)*2 + + #else +- sizeof(struct in6_addr) + sizeof(struct in6_addr *)*2 + ++ sizeof(struct in6_addr) + sizeof(struct in6_addr *)*2 + + #endif /* __UCLIBC_HAS_IPV6__ */ +- sizeof(char *)*(ALIAS_DIM) + +- 80/*namebuffer*/ + 2/* margin */]; ++ sizeof(char *)*(ALIAS_DIM) + ++ 80/*namebuffer*/ + 2/* margin */]; + struct hostent *host; + +- LOCK; ++ __UCLIBC_MUTEX_LOCK(mylock); + gethostent_r(&h, buf, sizeof(buf), &host, &h_errno); +- UNLOCK; ++ __UCLIBC_MUTEX_UNLOCK(mylock); + return(host); + } + #endif +@@ -1652,23 +1633,23 @@ struct hostent *gethostent (void) + #ifdef L_get_hosts_byname_r + + int __get_hosts_byname_r(const char * name, int type, +- struct hostent * result_buf, +- char * buf, size_t buflen, +- struct hostent ** result, +- int * h_errnop) ++ struct hostent * result_buf, ++ char * buf, size_t buflen, ++ struct hostent ** result, ++ int * h_errnop) + { + return(__read_etc_hosts_r(NULL, name, type, GET_HOSTS_BYNAME, +- result_buf, buf, buflen, result, h_errnop)); ++ result_buf, buf, buflen, result, h_errnop)); + } + #endif + + #ifdef L_get_hosts_byaddr_r + + int __get_hosts_byaddr_r(const char * addr, int len, int type, +- struct hostent * result_buf, +- char * buf, size_t buflen, +- struct hostent ** result, +- int * h_errnop) ++ struct hostent * result_buf, ++ char * buf, size_t buflen, ++ struct hostent ** result, ++ int * h_errnop) + { + #ifndef __UCLIBC_HAS_IPV6__ + char ipaddr[INET_ADDRSTRLEN]; +@@ -1677,24 +1658,24 @@ int __get_hosts_byaddr_r(const char * ad + #endif /* __UCLIBC_HAS_IPV6__ */ + + switch (type) { +- case AF_INET: +- if (len != sizeof(struct in_addr)) +- return 0; +- break; ++ case AF_INET: ++ if (len != sizeof(struct in_addr)) ++ return 0; ++ break; + #ifdef __UCLIBC_HAS_IPV6__ +- case AF_INET6: +- if (len != sizeof(struct in6_addr)) +- return 0; +- break; ++ case AF_INET6: ++ if (len != sizeof(struct in6_addr)) ++ return 0; ++ break; + #endif /* __UCLIBC_HAS_IPV6__ */ +- default: +- return 0; ++ default: ++ return 0; + } + + inet_ntop(type, addr, ipaddr, sizeof(ipaddr)); + + return(__read_etc_hosts_r(NULL, ipaddr, type, GET_HOSTS_BYADDR, +- result_buf, buf, buflen, result, h_errnop)); ++ result_buf, buf, buflen, result, h_errnop)); + } + #endif + +@@ -1705,8 +1686,8 @@ int __get_hosts_byaddr_r(const char * ad + #endif /* min */ + + int getnameinfo (const struct sockaddr *sa, socklen_t addrlen, char *host, +- socklen_t hostlen, char *serv, socklen_t servlen, +- unsigned int flags) ++ socklen_t hostlen, char *serv, socklen_t servlen, ++ unsigned int flags) + { + int serrno = errno; + int ok = 0; +@@ -1720,167 +1701,167 @@ int getnameinfo (const struct sockaddr * + return EAI_FAMILY; + + switch (sa->sa_family) { +- case AF_LOCAL: +- break; +- case AF_INET: +- if (addrlen < sizeof (struct sockaddr_in)) +- return EAI_FAMILY; +- break; ++ case AF_LOCAL: ++ break; ++ case AF_INET: ++ if (addrlen < sizeof (struct sockaddr_in)) ++ return EAI_FAMILY; ++ break; + #ifdef __UCLIBC_HAS_IPV6__ +- case AF_INET6: +- if (addrlen < sizeof (struct sockaddr_in6)) +- return EAI_FAMILY; +- break; ++ case AF_INET6: ++ if (addrlen < sizeof (struct sockaddr_in6)) ++ return EAI_FAMILY; ++ break; + #endif /* __UCLIBC_HAS_IPV6__ */ +- default: +- return EAI_FAMILY; ++ default: ++ return EAI_FAMILY; + } + + if (host != NULL && hostlen > 0) + switch (sa->sa_family) { +- case AF_INET: ++ case AF_INET: + #ifdef __UCLIBC_HAS_IPV6__ +- case AF_INET6: ++ case AF_INET6: + #endif /* __UCLIBC_HAS_IPV6__ */ +- if (!(flags & NI_NUMERICHOST)) { ++ if (!(flags & NI_NUMERICHOST)) { + #ifdef __UCLIBC_HAS_IPV6__ +- if (sa->sa_family == AF_INET6) +- h = gethostbyaddr ((const void *) +- &(((const struct sockaddr_in6 *) sa)->sin6_addr), +- sizeof(struct in6_addr), AF_INET6); +- else +-#endif /* __UCLIBC_HAS_IPV6__ */ +- h = gethostbyaddr ((const void *) &(((const struct sockaddr_in *)sa)->sin_addr), +- sizeof(struct in_addr), AF_INET); +- +- if (h) { +- char *c; +- if ((flags & NI_NOFQDN) +- && (getdomainname (domain, sizeof(domain)) == 0) +- && (c = strstr (h->h_name, domain)) +- && (c != h->h_name) && (*(--c) == '.')) { +- strncpy (host, h->h_name, +- min(hostlen, (size_t) (c - h->h_name))); +- host[min(hostlen - 1, (size_t) (c - h->h_name))] = '\0'; +- ok = 1; +- } else { +- strncpy (host, h->h_name, hostlen); +- ok = 1; ++ if (sa->sa_family == AF_INET6) ++ h = gethostbyaddr ((const void *) ++ &(((const struct sockaddr_in6 *) sa)->sin6_addr), ++ sizeof(struct in6_addr), AF_INET6); ++ else ++#endif /* __UCLIBC_HAS_IPV6__ */ ++ h = gethostbyaddr ((const void *) &(((const struct sockaddr_in *)sa)->sin_addr), ++ sizeof(struct in_addr), AF_INET); ++ ++ if (h) { ++ char *c; ++ if ((flags & NI_NOFQDN) ++ && (getdomainname (domain, sizeof(domain)) == 0) ++ && (c = strstr (h->h_name, domain)) ++ && (c != h->h_name) && (*(--c) == '.')) { ++ strncpy (host, h->h_name, ++ min(hostlen, (size_t) (c - h->h_name))); ++ host[min(hostlen - 1, (size_t) (c - h->h_name))] = '\0'; ++ ok = 1; ++ } else { ++ strncpy (host, h->h_name, hostlen); ++ ok = 1; ++ } + } +- } +- } ++ } + +- if (!ok) { +- if (flags & NI_NAMEREQD) { +- errno = serrno; +- return EAI_NONAME; +- } else { +- const char *c; ++ if (!ok) { ++ if (flags & NI_NAMEREQD) { ++ errno = serrno; ++ return EAI_NONAME; ++ } else { ++ const char *c; + #ifdef __UCLIBC_HAS_IPV6__ +- if (sa->sa_family == AF_INET6) { +- const struct sockaddr_in6 *sin6p; ++ if (sa->sa_family == AF_INET6) { ++ const struct sockaddr_in6 *sin6p; + +- sin6p = (const struct sockaddr_in6 *) sa; ++ sin6p = (const struct sockaddr_in6 *) sa; + +- c = inet_ntop (AF_INET6, +- (const void *) &sin6p->sin6_addr, host, hostlen); ++ c = inet_ntop (AF_INET6, ++ (const void *) &sin6p->sin6_addr, host, hostlen); + #if 0 +- /* Does scope id need to be supported? */ +- uint32_t scopeid; +- scopeid = sin6p->sin6_scope_id; +- if (scopeid != 0) { +- /* Buffer is >= IFNAMSIZ+1. */ +- char scopebuf[IFNAMSIZ + 1]; +- char *scopeptr; +- int ni_numericscope = 0; +- size_t real_hostlen = __strnlen (host, hostlen); +- size_t scopelen = 0; +- +- scopebuf[0] = SCOPE_DELIMITER; +- scopebuf[1] = '\0'; +- scopeptr = &scopebuf[1]; +- +- if (IN6_IS_ADDR_LINKLOCAL (&sin6p->sin6_addr) +- || IN6_IS_ADDR_MC_LINKLOCAL (&sin6p->sin6_addr)) { +- if (if_indextoname (scopeid, scopeptr) == NULL) ++ /* Does scope id need to be supported? */ ++ uint32_t scopeid; ++ scopeid = sin6p->sin6_scope_id; ++ if (scopeid != 0) { ++ /* Buffer is >= IFNAMSIZ+1. */ ++ char scopebuf[IFNAMSIZ + 1]; ++ char *scopeptr; ++ int ni_numericscope = 0; ++ size_t real_hostlen = __strnlen (host, hostlen); ++ size_t scopelen = 0; ++ ++ scopebuf[0] = SCOPE_DELIMITER; ++ scopebuf[1] = '\0'; ++ scopeptr = &scopebuf[1]; ++ ++ if (IN6_IS_ADDR_LINKLOCAL (&sin6p->sin6_addr) ++ || IN6_IS_ADDR_MC_LINKLOCAL (&sin6p->sin6_addr)) { ++ if (if_indextoname (scopeid, scopeptr) == NULL) ++ ++ni_numericscope; ++ else ++ scopelen = strlen (scopebuf); ++ } else { + ++ni_numericscope; +- else +- scopelen = strlen (scopebuf); +- } else { +- ++ni_numericscope; +- } ++ } + +- if (ni_numericscope) +- scopelen = 1 + snprintf (scopeptr, +- (scopebuf +- + sizeof scopebuf +- - scopeptr), +- "%u", scopeid); +- +- if (real_hostlen + scopelen + 1 > hostlen) +- return EAI_SYSTEM; +- memcpy (host + real_hostlen, scopebuf, scopelen + 1); +- } ++ if (ni_numericscope) ++ scopelen = 1 + snprintf (scopeptr, ++ (scopebuf ++ + sizeof scopebuf ++ - scopeptr), ++ "%u", scopeid); ++ ++ if (real_hostlen + scopelen + 1 > hostlen) ++ return EAI_SYSTEM; ++ memcpy (host + real_hostlen, scopebuf, scopelen + 1); ++ } + #endif +- } else ++ } else + #endif /* __UCLIBC_HAS_IPV6__ */ +- c = inet_ntop (AF_INET, (const void *) +- &(((const struct sockaddr_in *) sa)->sin_addr), +- host, hostlen); +- +- if (c == NULL) { +- errno = serrno; +- return EAI_SYSTEM; ++ c = inet_ntop (AF_INET, (const void *) ++ &(((const struct sockaddr_in *) sa)->sin_addr), ++ host, hostlen); ++ ++ if (c == NULL) { ++ errno = serrno; ++ return EAI_SYSTEM; ++ } + } ++ ok = 1; + } +- ok = 1; +- } +- break; +- +- case AF_LOCAL: +- if (!(flags & NI_NUMERICHOST)) { +- struct utsname utsname; ++ break; + +- if (!uname (&utsname)) { +- strncpy (host, utsname.nodename, hostlen); +- break; ++ case AF_LOCAL: ++ if (!(flags & NI_NUMERICHOST)) { ++ struct utsname utsname; ++ ++ if (!uname (&utsname)) { ++ strncpy (host, utsname.nodename, hostlen); ++ break; ++ }; + }; +- }; + +- if (flags & NI_NAMEREQD) { +- errno = serrno; +- return EAI_NONAME; +- } ++ if (flags & NI_NAMEREQD) { ++ errno = serrno; ++ return EAI_NONAME; ++ } + +- strncpy (host, "localhost", hostlen); +- break; ++ strncpy (host, "localhost", hostlen); ++ break; + +- default: +- return EAI_FAMILY; +- } ++ default: ++ return EAI_FAMILY; ++ } + + if (serv && (servlen > 0)) { + switch (sa->sa_family) { +- case AF_INET: ++ case AF_INET: + #ifdef __UCLIBC_HAS_IPV6__ +- case AF_INET6: ++ case AF_INET6: + #endif /* __UCLIBC_HAS_IPV6__ */ +- if (!(flags & NI_NUMERICSERV)) { +- struct servent *s; +- s = getservbyport (((const struct sockaddr_in *) sa)->sin_port, +- ((flags & NI_DGRAM) ? "udp" : "tcp")); +- if (s) { +- strncpy (serv, s->s_name, servlen); +- break; ++ if (!(flags & NI_NUMERICSERV)) { ++ struct servent *s; ++ s = getservbyport (((const struct sockaddr_in *) sa)->sin_port, ++ ((flags & NI_DGRAM) ? "udp" : "tcp")); ++ if (s) { ++ strncpy (serv, s->s_name, servlen); ++ break; ++ } + } +- } +- snprintf (serv, servlen, "%d", +- ntohs (((const struct sockaddr_in *) sa)->sin_port)); +- break; ++ snprintf (serv, servlen, "%d", ++ ntohs (((const struct sockaddr_in *) sa)->sin_port)); ++ break; + +- case AF_LOCAL: +- strncpy (serv, ((const struct sockaddr_un *) sa)->sun_path, servlen); +- break; ++ case AF_LOCAL: ++ strncpy (serv, ((const struct sockaddr_un *) sa)->sun_path, servlen); ++ break; + } + } + if (host && (hostlen > 0)) +@@ -1896,10 +1877,10 @@ int getnameinfo (const struct sockaddr * + #ifdef L_gethostbyname_r + + int gethostbyname_r(const char * name, +- struct hostent * result_buf, +- char * buf, size_t buflen, +- struct hostent ** result, +- int * h_errnop) ++ struct hostent * result_buf, ++ char * buf, size_t buflen, ++ struct hostent ** result, ++ int * h_errnop) + { + struct in_addr *in; + struct in_addr **addr_list; +@@ -1921,7 +1902,7 @@ int gethostbyname_r(const char * name, + __set_errno(0); /* to check for missing /etc/hosts. */ + + if ((i=__get_hosts_byname_r(name, AF_INET, result_buf, +- buf, buflen, result, h_errnop))==0) ++ buf, buflen, result, h_errnop))==0) + return i; + switch (*h_errnop) { + case HOST_NOT_FOUND: +@@ -1983,60 +1964,60 @@ int gethostbyname_r(const char * name, + + for (;;) { + +- BIGLOCK; ++ __UCLIBC_MUTEX_LOCK(__resolv_lock); + __nameserversXX=__nameservers; + __nameserverXX=__nameserver; +- BIGUNLOCK; ++ __UCLIBC_MUTEX_UNLOCK(__resolv_lock); + a.buf = buf; + a.buflen = buflen; + a.add_count = 0; + i = __dns_lookup(name, T_A, __nameserversXX, __nameserverXX, &packet, &a); + + if (i < 0) { +- *h_errnop = HOST_NOT_FOUND; +- DPRINTF("__dns_lookup\n"); +- return TRY_AGAIN; ++ *h_errnop = HOST_NOT_FOUND; ++ DPRINTF("__dns_lookup\n"); ++ return TRY_AGAIN; + } + + if ((a.rdlength + sizeof(struct in_addr*)) * a.add_count + 256 > buflen) +- { +- free(a.dotted); +- free(packet); +- *h_errnop = NETDB_INTERNAL; +- DPRINTF("buffer too small for all addresses\n"); +- return ERANGE; +- } ++ { ++ free(a.dotted); ++ free(packet); ++ *h_errnop = NETDB_INTERNAL; ++ DPRINTF("buffer too small for all addresses\n"); ++ return ERANGE; ++ } + else if(a.add_count > 0) +- { +- memmove(buf - sizeof(struct in_addr*)*2, buf, a.add_count * a.rdlength); +- addr_list = (struct in_addr**)(buf + a.add_count * a.rdlength); +- addr_list[0] = in; +- for (i = a.add_count-1; i>=0; --i) +- addr_list[i+1] = (struct in_addr*)(buf - sizeof(struct in_addr*)*2 + a.rdlength * i); +- addr_list[a.add_count + 1] = 0; +- buflen -= (((char*)&(addr_list[a.add_count + 2])) - buf); +- buf = (char*)&addr_list[a.add_count + 2]; +- } ++ { ++ memmove(buf - sizeof(struct in_addr*)*2, buf, a.add_count * a.rdlength); ++ addr_list = (struct in_addr**)(buf + a.add_count * a.rdlength); ++ addr_list[0] = in; ++ for (i = a.add_count-1; i>=0; --i) ++ addr_list[i+1] = (struct in_addr*)(buf - sizeof(struct in_addr*)*2 + a.rdlength * i); ++ addr_list[a.add_count + 1] = 0; ++ buflen -= (((char*)&(addr_list[a.add_count + 2])) - buf); ++ buf = (char*)&addr_list[a.add_count + 2]; ++ } + + strncpy(buf, a.dotted, buflen); + free(a.dotted); + + if (a.atype == T_A) { /* ADDRESS */ +- memcpy(in, a.rdata, sizeof(*in)); +- result_buf->h_name = buf; +- result_buf->h_addrtype = AF_INET; +- result_buf->h_length = sizeof(*in); +- result_buf->h_addr_list = (char **) addr_list; ++ memcpy(in, a.rdata, sizeof(*in)); ++ result_buf->h_name = buf; ++ result_buf->h_addrtype = AF_INET; ++ result_buf->h_length = sizeof(*in); ++ result_buf->h_addr_list = (char **) addr_list; + #ifdef __UCLIBC_MJN3_ONLY__ + #warning TODO -- generate the full list + #endif +- result_buf->h_aliases = alias; /* TODO: generate the full list */ +- free(packet); +- break; ++ result_buf->h_aliases = alias; /* TODO: generate the full list */ ++ free(packet); ++ break; + } else { +- free(packet); +- *h_errnop=HOST_NOT_FOUND; +- return TRY_AGAIN; ++ free(packet); ++ *h_errnop=HOST_NOT_FOUND; ++ return TRY_AGAIN; + } + } + +@@ -2049,14 +2030,14 @@ int gethostbyname_r(const char * name, + #ifdef L_gethostbyname2_r + + int gethostbyname2_r(const char *name, int family, +- struct hostent * result_buf, +- char * buf, size_t buflen, +- struct hostent ** result, +- int * h_errnop) ++ struct hostent * result_buf, ++ char * buf, size_t buflen, ++ struct hostent ** result, ++ int * h_errnop) + { + #ifndef __UCLIBC_HAS_IPV6__ + return family == (AF_INET)? gethostbyname_r(name, result_buf, +- buf, buflen, result, h_errnop) : HOST_NOT_FOUND; ++ buf, buflen, result, h_errnop) : HOST_NOT_FOUND; + #else /* __UCLIBC_HAS_IPV6__ */ + struct in6_addr *in; + struct in6_addr **addr_list; +@@ -2084,7 +2065,7 @@ int gethostbyname2_r(const char *name, i + __set_errno(0); /* to check for missing /etc/hosts. */ + + if ((i=__get_hosts_byname_r(name, AF_INET, result_buf, +- buf, buflen, result, h_errnop))==0) ++ buf, buflen, result, h_errnop))==0) + return i; + switch (*h_errnop) { + case HOST_NOT_FOUND: +@@ -2137,10 +2118,10 @@ int gethostbyname2_r(const char *name, i + memset((char *) &a, '\0', sizeof(a)); + + for (;;) { +- BIGLOCK; +- __nameserversXX=__nameservers; +- __nameserverXX=__nameserver; +- BIGUNLOCK; ++ __UCLIBC_MUTEX_LOCK(__resolv_lock); ++ __nameserversXX=__nameservers; ++ __nameserverXX=__nameserver; ++ __UCLIBC_MUTEX_UNLOCK(__resolv_lock); + + i = __dns_lookup(buf, T_AAAA, __nameserversXX, __nameserverXX, &packet, &a); + +@@ -2190,10 +2171,10 @@ int gethostbyname2_r(const char *name, i + + #ifdef L_gethostbyaddr_r + int gethostbyaddr_r (const void *addr, socklen_t len, int type, +- struct hostent * result_buf, +- char * buf, size_t buflen, +- struct hostent ** result, +- int * h_errnop) ++ struct hostent * result_buf, ++ char * buf, size_t buflen, ++ struct hostent ** result, ++ int * h_errnop) + + { + struct in_addr *in; +@@ -2234,7 +2215,7 @@ int gethostbyaddr_r (const void *addr, s + + /* do /etc/hosts first */ + if ((i=__get_hosts_byaddr_r(addr, len, type, result_buf, +- buf, buflen, result, h_errnop))==0) ++ buf, buflen, result, h_errnop))==0) + return i; + switch (*h_errnop) { + case HOST_NOT_FOUND: +@@ -2294,7 +2275,7 @@ int gethostbyaddr_r (const void *addr, s + addr_list[0] = in; + + sprintf(buf, "%u.%u.%u.%u.in-addr.arpa", +- tmp_addr[3], tmp_addr[2], tmp_addr[1], tmp_addr[0]); ++ tmp_addr[3], tmp_addr[2], tmp_addr[1], tmp_addr[0]); + #ifdef __UCLIBC_HAS_IPV6__ + } else { + memcpy(in6->s6_addr, addr, len); +@@ -2304,7 +2285,7 @@ int gethostbyaddr_r (const void *addr, s + + for (i = len - 1; i >= 0; i--) { + qp += sprintf(qp, "%x.%x.", in6->s6_addr[i] & 0xf, +- (in6->s6_addr[i] >> 4) & 0xf); ++ (in6->s6_addr[i] >> 4) & 0xf); + } + strcpy(qp, "ip6.int"); + #endif /* __UCLIBC_HAS_IPV6__ */ +@@ -2314,10 +2295,10 @@ int gethostbyaddr_r (const void *addr, s + + for (;;) { + +- BIGLOCK; +- __nameserversXX=__nameservers; +- __nameserverXX=__nameserver; +- BIGUNLOCK; ++ __UCLIBC_MUTEX_LOCK(__resolv_lock); ++ __nameserversXX=__nameservers; ++ __nameserverXX=__nameserver; ++ __UCLIBC_MUTEX_UNLOCK(__resolv_lock); + i = __dns_lookup(buf, T_PTR, __nameserversXX, __nameserverXX, &packet, &a); + + if (i < 0) { +@@ -2381,7 +2362,7 @@ int gethostbyaddr_r (const void *addr, s + * Return size of compressed name or -1 if there was an error. + */ + int __dn_expand(const u_char *msg, const u_char *eom, const u_char *src, +- char *dst, int dstsiz) ++ char *dst, int dstsiz) + { + int n = ns_name_uncompress(msg, eom, src, dst, (size_t)dstsiz); + +@@ -2401,7 +2382,7 @@ int __dn_expand(const u_char *msg, const + */ + static int printable(int ch) + { +- return (ch > 0x20 && ch < 0x7f); ++ return (ch > 0x20 && ch < 0x7f); + } + + /* +@@ -2413,18 +2394,18 @@ static int printable(int ch) + */ + static int special(int ch) + { +- switch (ch) { ++ switch (ch) { + case 0x22: /* '"' */ + case 0x2E: /* '.' */ + case 0x3B: /* ';' */ + case 0x5C: /* '\\' */ +- /* Special modifiers in zone files. */ ++ /* Special modifiers in zone files. */ + case 0x40: /* '@' */ + case 0x24: /* '$' */ +- return (1); ++ return (1); + default: +- return (0); +- } ++ return (0); ++ } + } + + /* +@@ -2436,7 +2417,7 @@ static int special(int ch) + * Root domain returns as "." not "". + */ + int __ns_name_uncompress(const u_char *msg, const u_char *eom, +- const u_char *src, char *dst, size_t dstsiz) ++ const u_char *src, char *dst, size_t dstsiz) + { + u_char tmp[NS_MAXCDNAME]; + int n; +@@ -2525,7 +2506,7 @@ int __ns_name_ntop(const u_char *src, ch + return (-1); + } + *dn++ = '\0'; +- return (dn - dst); ++ return (dn - dst); + } + + /* +@@ -2535,7 +2516,7 @@ int __ns_name_ntop(const u_char *src, ch + * -1 if it fails, or consumed octets if it succeeds. + */ + int __ns_name_unpack(const u_char *msg, const u_char *eom, const u_char *src, +- u_char *dst, size_t dstsiz) ++ u_char *dst, size_t dstsiz) + { + const u_char *srcp, *dstlim; + u_char *dstp; +@@ -2554,46 +2535,46 @@ int __ns_name_unpack(const u_char *msg, + while ((n = *srcp++) != 0) { + /* Check for indirection. */ + switch (n & NS_CMPRSFLGS) { +- case 0: +- /* Limit checks. */ +- if (dstp + n + 1 >= dstlim || srcp + n >= eom) { +- __set_errno (EMSGSIZE); +- return (-1); +- } +- checked += n + 1; +- *dstp++ = n; +- memcpy(dstp, srcp, n); +- dstp += n; +- srcp += n; +- break; ++ case 0: ++ /* Limit checks. */ ++ if (dstp + n + 1 >= dstlim || srcp + n >= eom) { ++ __set_errno (EMSGSIZE); ++ return (-1); ++ } ++ checked += n + 1; ++ *dstp++ = n; ++ memcpy(dstp, srcp, n); ++ dstp += n; ++ srcp += n; ++ break; + +- case NS_CMPRSFLGS: +- if (srcp >= eom) { +- __set_errno (EMSGSIZE); +- return (-1); +- } +- if (len < 0) +- len = srcp - src + 1; +- srcp = msg + (((n & 0x3f) << 8) | (*srcp & 0xff)); +- if (srcp < msg || srcp >= eom) { /* Out of range. */ +- __set_errno (EMSGSIZE); +- return (-1); +- } +- checked += 2; +- /* +- * Check for loops in the compressed name; +- * if we've looked at the whole message, +- * there must be a loop. +- */ +- if (checked >= eom - msg) { +- __set_errno (EMSGSIZE); +- return (-1); +- } +- break; ++ case NS_CMPRSFLGS: ++ if (srcp >= eom) { ++ __set_errno (EMSGSIZE); ++ return (-1); ++ } ++ if (len < 0) ++ len = srcp - src + 1; ++ srcp = msg + (((n & 0x3f) << 8) | (*srcp & 0xff)); ++ if (srcp < msg || srcp >= eom) { /* Out of range. */ ++ __set_errno (EMSGSIZE); ++ return (-1); ++ } ++ checked += 2; ++ /* ++ * Check for loops in the compressed name; ++ * if we've looked at the whole message, ++ * there must be a loop. ++ */ ++ if (checked >= eom - msg) { ++ __set_errno (EMSGSIZE); ++ return (-1); ++ } ++ break; + +- default: +- __set_errno (EMSGSIZE); +- return (-1); /* flag error */ ++ default: ++ __set_errno (EMSGSIZE); ++ return (-1); /* flag error */ + } + } + *dstp = '\0'; +diff --git a/libc/inet/rpc/create_xid.c b/libc/inet/rpc/create_xid.c +index cbb961e..c86cbb4 100644 +--- a/libc/inet/rpc/create_xid.c ++++ b/libc/inet/rpc/create_xid.c +@@ -27,15 +27,7 @@ + + /* The RPC code is not threadsafe, but new code should be threadsafe. */ + +-#ifdef __UCLIBC_HAS_THREADS__ +-#include <pthread.h> +-static pthread_mutex_t createxid_lock = PTHREAD_MUTEX_INITIALIZER; +-# define LOCK __pthread_mutex_lock(&createxid_lock) +-# define UNLOCK __pthread_mutex_unlock(&createxid_lock); +-#else +-# define LOCK +-# define UNLOCK +-#endif ++__UCLIBC_MUTEX_STATIC(mylock, PTHREAD_MUTEX_INITIALIZER); + + static int is_initialized; + static struct drand48_data __rpc_lrand48_data; +@@ -43,22 +35,22 @@ static struct drand48_data __rpc_lrand48 + unsigned long + _create_xid (void) + { +- unsigned long res; ++ unsigned long res; + +- LOCK; ++ __UCLIBC_MUTEX_LOCK(mylock); + +- if (!is_initialized) +- { +- struct timeval now; ++ if (!is_initialized) ++ { ++ struct timeval now; + +- gettimeofday (&now, (struct timezone *) 0); +- srand48_r (now.tv_sec ^ now.tv_usec, &__rpc_lrand48_data); +- is_initialized = 1; +- } ++ gettimeofday (&now, (struct timezone *) 0); ++ srand48_r (now.tv_sec ^ now.tv_usec, &__rpc_lrand48_data); ++ is_initialized = 1; ++ } + +- lrand48_r (&__rpc_lrand48_data, &res); ++ lrand48_r (&__rpc_lrand48_data, &res); + +- UNLOCK; ++ __UCLIBC_MUTEX_UNLOCK(mylock); + +- return res; ++ return res; + } +diff --git a/libc/misc/dirent/closedir.c b/libc/misc/dirent/closedir.c +index 068e2d3..56adb23 100644 +--- a/libc/misc/dirent/closedir.c ++++ b/libc/misc/dirent/closedir.c +@@ -4,7 +4,6 @@ + #include <unistd.h> + #include "dirstream.h" + +- + int closedir(DIR * dir) + { + int fd; +@@ -19,14 +18,10 @@ int closedir(DIR * dir) + __set_errno(EBADF); + return -1; + } +-#ifdef __UCLIBC_HAS_THREADS__ +- __pthread_mutex_lock(&(dir->dd_lock)); +-#endif ++ __UCLIBC_MUTEX_LOCK(dir->dd_lock); + fd = dir->dd_fd; + dir->dd_fd = -1; +-#ifdef __UCLIBC_HAS_THREADS__ +- __pthread_mutex_unlock(&(dir->dd_lock)); +-#endif ++ __UCLIBC_MUTEX_UNLOCK(dir->dd_lock); + free(dir->dd_buf); + free(dir); + return close(fd); +diff --git a/libc/misc/dirent/dirstream.h b/libc/misc/dirent/dirstream.h +index 2dd0264..bd721c5 100644 +--- a/libc/misc/dirent/dirstream.h ++++ b/libc/misc/dirent/dirstream.h +@@ -26,9 +26,8 @@ Cambridge, MA 02139, USA. */ + + #include <features.h> + #include <sys/types.h> +-#ifdef __UCLIBC_HAS_THREADS__ +-#include <pthread.h> +-#endif ++ ++#include <bits/uClibc_mutex.h> + + /* For now, syscall readdir () only supports one entry at a time. It + * will be changed in the future. +@@ -63,11 +62,7 @@ struct __dirstream { + size_t dd_max; + + /* lock */ +-#ifdef __UCLIBC_HAS_THREADS__ +- pthread_mutex_t dd_lock; +-#else +- void *dd_lock; +-#endif ++ __UCLIBC_MUTEX(dd_lock); + }; /* stream data from opendir() */ + + +diff --git a/libc/misc/dirent/readdir.c b/libc/misc/dirent/readdir.c +index 1f196e1..c55317a 100644 +--- a/libc/misc/dirent/readdir.c ++++ b/libc/misc/dirent/readdir.c +@@ -5,7 +5,6 @@ + #include <dirent.h> + #include "dirstream.h" + +- + struct dirent *readdir(DIR * dir) + { + ssize_t bytes; +@@ -16,9 +15,7 @@ struct dirent *readdir(DIR * dir) + return NULL; + } + +-#ifdef __UCLIBC_HAS_THREADS__ +- __pthread_mutex_lock(&(dir->dd_lock)); +-#endif ++ __UCLIBC_MUTEX_LOCK(dir->dd_lock); + + do { + if (dir->dd_size <= dir->dd_nextloc) { +@@ -44,8 +41,6 @@ struct dirent *readdir(DIR * dir) + } while (de->d_ino == 0); + + all_done: +-#ifdef __UCLIBC_HAS_THREADS__ +- __pthread_mutex_unlock(&(dir->dd_lock)); +-#endif ++ __UCLIBC_MUTEX_UNLOCK(dir->dd_lock); + return de; + } +diff --git a/libc/misc/dirent/readdir64.c b/libc/misc/dirent/readdir64.c +index f798c6f..6da3b0d 100644 +--- a/libc/misc/dirent/readdir64.c ++++ b/libc/misc/dirent/readdir64.c +@@ -20,7 +20,6 @@ + #include <dirent.h> + #include "dirstream.h" + +- + struct dirent64 *readdir64(DIR * dir) + { + ssize_t bytes; +@@ -31,9 +30,7 @@ struct dirent64 *readdir64(DIR * dir) + return NULL; + } + +-#ifdef __UCLIBC_HAS_THREADS__ +- __pthread_mutex_lock(&(dir->dd_lock)); +-#endif ++ __UCLIBC_MUTEX_LOCK(dir->dd_lock); + + do { + if (dir->dd_size <= dir->dd_nextloc) { +@@ -59,9 +56,7 @@ struct dirent64 *readdir64(DIR * dir) + } while (de->d_ino == 0); + + all_done: +-#ifdef __UCLIBC_HAS_THREADS__ +- __pthread_mutex_unlock(&(dir->dd_lock)); +-#endif ++ __UCLIBC_MUTEX_UNLOCK(dir->dd_lock); + + return de; + } +diff --git a/libc/misc/dirent/readdir64_r.c b/libc/misc/dirent/readdir64_r.c +index da3564e..cc96eff 100644 +--- a/libc/misc/dirent/readdir64_r.c ++++ b/libc/misc/dirent/readdir64_r.c +@@ -19,7 +19,6 @@ + #include <dirent.h> + #include "dirstream.h" + +- + int readdir64_r(DIR *dir, struct dirent64 *entry, struct dirent64 **result) + { + int ret; +@@ -32,21 +31,19 @@ int readdir64_r(DIR *dir, struct dirent6 + } + de = NULL; + +-#ifdef __UCLIBC_HAS_THREADS__ +- __pthread_mutex_lock(&(dir->dd_lock)); +-#endif ++ __UCLIBC_MUTEX_LOCK(dir->dd_lock); + + do { + if (dir->dd_size <= dir->dd_nextloc) { +- /* read dir->dd_max bytes of directory entries. */ +- bytes = __getdents64(dir->dd_fd, dir->dd_buf, dir->dd_max); +- if (bytes <= 0) { +- *result = NULL; +- ret = errno; +- goto all_done; +- } +- dir->dd_size = bytes; +- dir->dd_nextloc = 0; ++ /* read dir->dd_max bytes of directory entries. */ ++ bytes = __getdents64(dir->dd_fd, dir->dd_buf, dir->dd_max); ++ if (bytes <= 0) { ++ *result = NULL; ++ ret = errno; ++ goto all_done; ++ } ++ dir->dd_size = bytes; ++ dir->dd_nextloc = 0; + } + + de = (struct dirent64 *) (((char *) dir->dd_buf) + dir->dd_nextloc); +@@ -66,12 +63,10 @@ int readdir64_r(DIR *dir, struct dirent6 + } + ret = 0; + +-all_done: ++ all_done: + +-#ifdef __UCLIBC_HAS_THREADS__ +- __pthread_mutex_unlock(&(dir->dd_lock)); +-#endif +- return((de != NULL)? 0 : ret); ++ __UCLIBC_MUTEX_UNLOCK(dir->dd_lock); ++ return((de != NULL)? 0 : ret); + } + #endif /* __UCLIBC_HAS_LFS__ */ + +diff --git a/libc/misc/dirent/readdir_r.c b/libc/misc/dirent/readdir_r.c +index 245dcbd..aeccdd8 100644 +--- a/libc/misc/dirent/readdir_r.c ++++ b/libc/misc/dirent/readdir_r.c +@@ -5,7 +5,6 @@ + #include <dirent.h> + #include "dirstream.h" + +- + int readdir_r(DIR *dir, struct dirent *entry, struct dirent **result) + { + int ret; +@@ -18,21 +17,19 @@ int readdir_r(DIR *dir, struct dirent *e + } + de = NULL; + +-#ifdef __UCLIBC_HAS_THREADS__ +- __pthread_mutex_lock(&(dir->dd_lock)); +-#endif ++ __UCLIBC_MUTEX_LOCK(dir->dd_lock); + + do { + if (dir->dd_size <= dir->dd_nextloc) { +- /* read dir->dd_max bytes of directory entries. */ +- bytes = __getdents(dir->dd_fd, dir->dd_buf, dir->dd_max); +- if (bytes <= 0) { +- *result = NULL; +- ret = errno; +- goto all_done; +- } +- dir->dd_size = bytes; +- dir->dd_nextloc = 0; ++ /* read dir->dd_max bytes of directory entries. */ ++ bytes = __getdents(dir->dd_fd, dir->dd_buf, dir->dd_max); ++ if (bytes <= 0) { ++ *result = NULL; ++ ret = errno; ++ goto all_done; ++ } ++ dir->dd_size = bytes; ++ dir->dd_nextloc = 0; + } + + de = (struct dirent *) (((char *) dir->dd_buf) + dir->dd_nextloc); +@@ -52,10 +49,8 @@ int readdir_r(DIR *dir, struct dirent *e + } + ret = 0; + +-all_done: ++ all_done: + +-#ifdef __UCLIBC_HAS_THREADS__ +- __pthread_mutex_unlock(&(dir->dd_lock)); +-#endif +- return((de != NULL)? 0 : ret); ++ __UCLIBC_MUTEX_UNLOCK(dir->dd_lock); ++ return((de != NULL)? 0 : ret); + } +diff --git a/libc/misc/dirent/rewinddir.c b/libc/misc/dirent/rewinddir.c +index 60ef71d..fe8fc2a 100644 +--- a/libc/misc/dirent/rewinddir.c ++++ b/libc/misc/dirent/rewinddir.c +@@ -3,7 +3,6 @@ + #include <unistd.h> + #include "dirstream.h" + +- + /* rewinddir() just does an lseek(fd,0,0) - see close for comments */ + void rewinddir(DIR * dir) + { +@@ -11,12 +10,8 @@ void rewinddir(DIR * dir) + __set_errno(EBADF); + return; + } +-#ifdef __UCLIBC_HAS_THREADS__ +- __pthread_mutex_lock(&(dir->dd_lock)); +-#endif ++ __UCLIBC_MUTEX_LOCK(dir->dd_lock); + lseek(dir->dd_fd, 0, SEEK_SET); + dir->dd_nextoff = dir->dd_nextloc = dir->dd_size = 0; +-#ifdef __UCLIBC_HAS_THREADS__ +- __pthread_mutex_unlock(&(dir->dd_lock)); +-#endif ++ __UCLIBC_MUTEX_UNLOCK(dir->dd_lock); + } +diff --git a/libc/misc/dirent/seekdir.c b/libc/misc/dirent/seekdir.c +index 139f1e1..6d6f5f0 100644 +--- a/libc/misc/dirent/seekdir.c ++++ b/libc/misc/dirent/seekdir.c +@@ -3,19 +3,14 @@ + #include <unistd.h> + #include "dirstream.h" + +- + void seekdir(DIR * dir, long int offset) + { + if (!dir) { + __set_errno(EBADF); + return; + } +-#ifdef __UCLIBC_HAS_THREADS__ +- __pthread_mutex_lock(&(dir->dd_lock)); +-#endif ++ __UCLIBC_MUTEX_LOCK(dir->dd_lock); + dir->dd_nextoff = lseek(dir->dd_fd, offset, SEEK_SET); + dir->dd_size = dir->dd_nextloc = 0; +-#ifdef __UCLIBC_HAS_THREADS__ +- __pthread_mutex_unlock(&(dir->dd_lock)); +-#endif ++ __UCLIBC_MUTEX_UNLOCK(dir->dd_lock); + } +diff --git a/libc/misc/mntent/mntent.c b/libc/misc/mntent/mntent.c +index d98a687..af6d848 100644 +--- a/libc/misc/mntent/mntent.c ++++ b/libc/misc/mntent/mntent.c +@@ -3,15 +3,9 @@ + #include <string.h> + #include <mntent.h> + +-#ifdef __UCLIBC_HAS_THREADS__ +-#include <pthread.h> +-static pthread_mutex_t mylock = PTHREAD_MUTEX_INITIALIZER; +-# define LOCK __pthread_mutex_lock(&mylock) +-# define UNLOCK __pthread_mutex_unlock(&mylock); +-#else +-# define LOCK +-# define UNLOCK +-#endif ++#include <bits/uClibc_mutex.h> ++ ++__UCLIBC_MUTEX_STATIC(mylock, PTHREAD_MUTEX_INITIALIZER); + + /* Reentrant version of getmntent. */ + struct mntent *getmntent_r (FILE *filep, +@@ -67,7 +61,7 @@ struct mntent *getmntent(FILE * filep) + struct mntent *tmp; + static char *buff = NULL; + static struct mntent mnt; +- LOCK; ++ __UCLIBC_MUTEX_LOCK(mylock); + + if (!buff) { + buff = malloc(BUFSIZ); +@@ -76,7 +70,7 @@ struct mntent *getmntent(FILE * filep) + } + + tmp = getmntent_r(filep, &mnt, buff, BUFSIZ); +- UNLOCK; ++ __UCLIBC_MUTEX_UNLOCK(mylock); + return(tmp); + } + +diff --git a/libc/misc/pthread/weaks.c b/libc/misc/pthread/weaks.c +index 89c2611..c27bd10 100644 +--- a/libc/misc/pthread/weaks.c ++++ b/libc/misc/pthread/weaks.c +@@ -21,6 +21,7 @@ + #include <limits.h> + #include <stdlib.h> + ++static void __pthread_return_void __P ((void)); + static int __pthread_return_0 __P ((void)); + static int __pthread_return_1 __P ((void)); + +@@ -104,8 +105,17 @@ weak_alias (__pthread_return_0, __pthrea + weak_alias (__pthread_return_0, __pthread_mutex_trylock) + weak_alias (__pthread_return_0, __pthread_mutex_unlock) + ++weak_alias (__pthread_return_void, _pthread_cleanup_push_defer) ++weak_alias (__pthread_return_void, _pthread_cleanup_pop_restore) ++ + /**********************************************************************/ + ++static void ++__pthread_return_void (void) ++{ ++ return; ++} ++ + static int + __pthread_return_0 (void) + { +diff --git a/libc/misc/syslog/syslog.c b/libc/misc/syslog/syslog.c +index 2b478e1..9e9ddbf 100644 +--- a/libc/misc/syslog/syslog.c ++++ b/libc/misc/syslog/syslog.c +@@ -80,17 +80,9 @@ + #include <ctype.h> + #include <signal.h> + ++#include <bits/uClibc_mutex.h> + +-#ifdef __UCLIBC_HAS_THREADS__ +-#include <pthread.h> +-static pthread_mutex_t mylock = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP; +-# define LOCK __pthread_mutex_lock(&mylock) +-# define UNLOCK __pthread_mutex_unlock(&mylock); +-#else +-# define LOCK +-# define UNLOCK +-#endif +- ++__UCLIBC_MUTEX_STATIC(mylock, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP); + + static int LogFile = -1; /* fd for log */ + static int connected; /* have done connect */ +@@ -110,26 +102,26 @@ int setlogmask(int pmask); + static void + closelog_intern(int to_default) + { +- LOCK; ++ __UCLIBC_MUTEX_LOCK(mylock); + if (LogFile != -1) { + (void) close(LogFile); + } + LogFile = -1; + connected = 0; + if (to_default) +- { +- LogStat = 0; +- LogTag = "syslog"; +- LogFacility = LOG_USER; +- LogMask = 0xff; +- } +- UNLOCK; ++ { ++ LogStat = 0; ++ LogTag = "syslog"; ++ LogFacility = LOG_USER; ++ LogMask = 0xff; ++ } ++ __UCLIBC_MUTEX_UNLOCK(mylock); + } + + static void + sigpipe_handler (int sig) + { +- closelog_intern (0); ++ closelog_intern (0); + } + + /* +@@ -165,7 +157,7 @@ vsyslog( int pri, const char *fmt, va_li + + saved_errno = errno; + +- LOCK; ++ __UCLIBC_MUTEX_LOCK(mylock); + + /* See if we should just throw out this message. */ + if (!(LogMask & LOG_MASK(LOG_PRI(pri))) || (pri &~ (LOG_PRIMASK|LOG_FACMASK))) +@@ -208,7 +200,7 @@ vsyslog( int pri, const char *fmt, va_li + if (p >= end || p < head_end) { /* Returned -1 in case of error... */ + static const char truncate_msg[12] = "[truncated] "; + memmove(head_end + sizeof(truncate_msg), head_end, +- end - head_end - sizeof(truncate_msg)); ++ end - head_end - sizeof(truncate_msg)); + memcpy(head_end, truncate_msg, sizeof(truncate_msg)); + if (p < head_end) { + while (p < end && *p) { +@@ -261,11 +253,11 @@ vsyslog( int pri, const char *fmt, va_li + (void)close(fd); + } + +-getout: +- UNLOCK; ++ getout: ++ __UCLIBC_MUTEX_UNLOCK(mylock); + if (sigpipe == 0) + sigaction (SIGPIPE, &oldaction, +- (struct sigaction *) NULL); ++ (struct sigaction *) NULL); + } + + /* +@@ -276,48 +268,48 @@ openlog( const char *ident, int logstat, + { + int logType = SOCK_DGRAM; + +- LOCK; ++ __UCLIBC_MUTEX_LOCK(mylock); + + if (ident != NULL) +- LogTag = ident; ++ LogTag = ident; + LogStat = logstat; + if (logfac != 0 && (logfac &~ LOG_FACMASK) == 0) +- LogFacility = logfac; ++ LogFacility = logfac; + if (LogFile == -1) { +- SyslogAddr.sa_family = AF_UNIX; +- (void)strncpy(SyslogAddr.sa_data, _PATH_LOG, +- sizeof(SyslogAddr.sa_data)); +-retry: +- if (LogStat & LOG_NDELAY) { +- if ((LogFile = socket(AF_UNIX, logType, 0)) == -1){ +- UNLOCK; +- return; +- } +- /* fcntl(LogFile, F_SETFD, 1); */ +- } ++ SyslogAddr.sa_family = AF_UNIX; ++ (void)strncpy(SyslogAddr.sa_data, _PATH_LOG, ++ sizeof(SyslogAddr.sa_data)); ++ retry: ++ if (LogStat & LOG_NDELAY) { ++ if ((LogFile = socket(AF_UNIX, logType, 0)) == -1){ ++ goto DONE; ++ } ++ /* fcntl(LogFile, F_SETFD, 1); */ ++ } + } + + if (LogFile != -1 && !connected) { +- if (connect(LogFile, &SyslogAddr, sizeof(SyslogAddr) - +- sizeof(SyslogAddr.sa_data) + strlen(SyslogAddr.sa_data)) != -1) +- { +- connected = 1; +- } else if (logType == SOCK_DGRAM) { +- logType = SOCK_STREAM; +- if (LogFile != -1) { +- close(LogFile); +- LogFile = -1; +- } +- goto retry; +- } else { +- if (LogFile != -1) { +- close(LogFile); +- LogFile = -1; +- } +- } ++ if (connect(LogFile, &SyslogAddr, sizeof(SyslogAddr) - ++ sizeof(SyslogAddr.sa_data) + strlen(SyslogAddr.sa_data)) != -1) ++ { ++ connected = 1; ++ } else if (logType == SOCK_DGRAM) { ++ logType = SOCK_STREAM; ++ if (LogFile != -1) { ++ close(LogFile); ++ LogFile = -1; ++ } ++ goto retry; ++ } else { ++ if (LogFile != -1) { ++ close(LogFile); ++ LogFile = -1; ++ } ++ } + } + +- UNLOCK; ++ DONE: ++ __UCLIBC_MUTEX_UNLOCK(mylock); + } + + /* +@@ -335,10 +327,10 @@ int setlogmask(int pmask) + int omask; + + omask = LogMask; +- LOCK; ++ __UCLIBC_MUTEX_LOCK(mylock); + if (pmask != 0) +- LogMask = pmask; +- UNLOCK; ++ LogMask = pmask; ++ __UCLIBC_MUTEX_UNLOCK(mylock); + return (omask); + } + +diff --git a/libc/misc/time/time.c b/libc/misc/time/time.c +index f43bb8a..6165a52 100644 +--- a/libc/misc/time/time.c ++++ b/libc/misc/time/time.c +@@ -143,6 +143,8 @@ + #include <locale.h> + #include <bits/uClibc_uintmaxtostr.h> + ++#include <bits/uClibc_mutex.h> ++ + #ifdef __UCLIBC_HAS_XLOCALE__ + #include <xlocale.h> + #endif +@@ -191,21 +193,7 @@ typedef struct { + char tzname[TZNAME_MAX+1]; + } rule_struct; + +-#ifdef __UCLIBC_HAS_THREADS__ +- +-#include <pthread.h> +- +-extern pthread_mutex_t _time_tzlock; +- +-#define TZLOCK __pthread_mutex_lock(&_time_tzlock) +-#define TZUNLOCK __pthread_mutex_unlock(&_time_tzlock) +- +-#else +- +-#define TZLOCK ((void) 0) +-#define TZUNLOCK ((void) 0) +- +-#endif ++__UCLIBC_MUTEX_EXTERN(_time_tzlock); + + extern rule_struct _time_tzinfo[2]; + +@@ -542,13 +530,13 @@ struct tm *localtime(const time_t *timer + struct tm *localtime_r(register const time_t *__restrict timer, + register struct tm *__restrict result) + { +- TZLOCK; ++ __UCLIBC_MUTEX_LOCK(_time_tzlock); + + tzset(); + + __time_localtime_tzi(timer, result, _time_tzinfo); + +- TZUNLOCK; ++ __UCLIBC_MUTEX_UNLOCK(_time_tzlock); + + return result; + } +@@ -1037,7 +1025,7 @@ size_t __XL(strftime)(char *__restrict s + goto LOOP; + } + +- o = spec + 26; /* set to "????" */ ++ o = ((const char *) spec) + 26; /* set to "????" */ + if ((code & MASK_SPEC) == CALC_SPEC) { + + if (*p == 's') { +@@ -1073,17 +1061,15 @@ size_t __XL(strftime)(char *__restrict s + + #ifdef __UCLIBC_HAS_TM_EXTENSIONS__ + +-#define RSP_TZUNLOCK ((void) 0) + #define RSP_TZNAME timeptr->tm_zone + #define RSP_GMT_OFFSET (-timeptr->tm_gmtoff) + + #else + +-#define RSP_TZUNLOCK TZUNLOCK + #define RSP_TZNAME rsp->tzname + #define RSP_GMT_OFFSET rsp->gmt_offset + +- TZLOCK; ++ __UCLIBC_MUTEX_LOCK(_time_tzlock); + + rsp = _time_tzinfo; + if (timeptr->tm_isdst > 0) { +@@ -1114,15 +1100,17 @@ size_t __XL(strftime)(char *__restrict s + } + #endif + o_count = SIZE_MAX; +- RSP_TZUNLOCK; ++/* RSP_TZUNLOCK; */ ++#ifdef __UCLIBC_HAS_TM_EXTENSIONS__ + goto OUTPUT; ++#endif + } else { /* z */ + *s = '+'; + if ((tzo = -RSP_GMT_OFFSET) < 0) { + tzo = -tzo; + *s = '-'; + } +- RSP_TZUNLOCK; ++/* RSP_TZUNLOCK; */ + ++s; + --count; + +@@ -1131,7 +1119,13 @@ size_t __XL(strftime)(char *__restrict s + + i = 16 + 6; /* 0-fill, width = 4 */ + } +- ++#ifdef __UCLIBC_HAS_TM_EXTENSIONS__ ++#else ++ __UCLIBC_MUTEX_UNLOCK(_time_tzlock); ++ if (*p == 'Z') { ++ goto OUTPUT; ++ } ++#endif + } else { + /* TODO: don't need year for U, W */ + for (i=0 ; i < 3 ; i++) { +@@ -1664,9 +1658,7 @@ int daylight = 0; + long timezone = 0; + char *tzname[2] = { (char *) UTC, (char *) (UTC-1) }; + +-#ifdef __UCLIBC_HAS_THREADS__ +-pthread_mutex_t _time_tzlock = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP; +-#endif ++__UCLIBC_MUTEX_INIT(_time_tzlock, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP); + + rule_struct _time_tzinfo[2]; + +@@ -1796,7 +1788,7 @@ void tzset(void) + static char oldval[TZ_BUFLEN]; /* BSS-zero'd. */ + #endif /* __UCLIBC_HAS_TZ_CACHING__ */ + +- TZLOCK; ++ __UCLIBC_MUTEX_LOCK(_time_tzlock); + + e = getenv(TZ); /* TZ env var always takes precedence. */ + +@@ -1962,10 +1954,10 @@ void tzset(void) + daylight = !!_time_tzinfo[1].tzname[0]; + timezone = _time_tzinfo[0].gmt_offset; + +-#if defined(__UCLIBC_HAS_TZ_FILE__) ++#if defined(__UCLIBC_HAS_TZ_FILE__) || defined(__UCLIBC_HAS_TZ_CACHING__) + FAST_DONE: + #endif +- TZUNLOCK; ++ __UCLIBC_MUTEX_UNLOCK(_time_tzlock); + } + + #endif +@@ -2167,13 +2159,13 @@ time_t _time_mktime(struct tm *timeptr, + { + time_t t; + +- TZLOCK; ++ __UCLIBC_MUTEX_LOCK(_time_tzlock); + + tzset(); + + t = _time_mktime_tzi(timeptr, store_on_success, _time_tzinfo); + +- TZUNLOCK; ++ __UCLIBC_MUTEX_UNLOCK(_time_tzlock); + + return t; + } +diff --git a/libc/misc/ttyent/getttyent.c b/libc/misc/ttyent/getttyent.c +index 6e2fbd2..c85c73a 100644 +--- a/libc/misc/ttyent/getttyent.c ++++ b/libc/misc/ttyent/getttyent.c +@@ -35,9 +35,6 @@ + #include <ctype.h> + #include <string.h> + #include <stdlib.h> +-#ifdef __UCLIBC_HAS_THREADS__ +-#include <pthread.h> +-#endif + + static char zapchar; + static FILE *tf; +@@ -50,8 +47,8 @@ struct ttyent * getttynam(const char *tt + + setttyent(); + while ((t = getttyent())) +- if (!strcmp(tty, t->ty_name)) +- break; ++ if (!strcmp(tty, t->ty_name)) ++ break; + endttyent(); + return (t); + } +@@ -67,27 +64,27 @@ static char * skip(register char *p) + register int c, q; + + for (q = 0, t = p; (c = *p) != '\0'; p++) { +- if (c == '"') { +- q ^= QUOTED; /* obscure, but nice */ +- continue; +- } +- if (q == QUOTED && *p == '\\' && *(p+1) == '"') +- p++; +- *t++ = *p; +- if (q == QUOTED) +- continue; +- if (c == '#') { +- zapchar = c; +- *p = 0; +- break; +- } +- if (c == '\t' || c == ' ' || c == '\n') { +- zapchar = c; +- *p++ = 0; +- while ((c = *p) == '\t' || c == ' ' || c == '\n') +- p++; +- break; +- } ++ if (c == '"') { ++ q ^= QUOTED; /* obscure, but nice */ ++ continue; ++ } ++ if (q == QUOTED && *p == '\\' && *(p+1) == '"') ++ p++; ++ *t++ = *p; ++ if (q == QUOTED) ++ continue; ++ if (c == '#') { ++ zapchar = c; ++ *p = 0; ++ break; ++ } ++ if (c == '\t' || c == ' ' || c == '\n') { ++ zapchar = c; ++ *p++ = 0; ++ while ((c = *p) == '\t' || c == ' ' || c == '\n') ++ p++; ++ break; ++ } + } + *--t = '\0'; + return (p); +@@ -104,46 +101,46 @@ struct ttyent * getttyent(void) + register int c; + register char *p; + static char *line = NULL; ++ struct ttyent *retval = NULL; + + if (!tf && !setttyent()) +- return (NULL); ++ return (NULL); + + if (!line) { +- line = malloc(BUFSIZ); ++ line = malloc(BUFSIZ); + if (!line) + abort(); + } + +- __STDIO_ALWAYS_THREADLOCK(tf); ++ __STDIO_ALWAYS_THREADLOCK(tf); + + for (;;) { +- if (!fgets_unlocked(p = line, BUFSIZ, tf)) { +- __STDIO_ALWAYS_THREADUNLOCK(tf); +- return (NULL); +- } +- /* skip lines that are too big */ +- if (!index(p, '\n')) { +- while ((c = getc_unlocked(tf)) != '\n' && c != EOF) +- ; +- continue; +- } +- while (isspace(*p)) +- ++p; +- if (*p && *p != '#') +- break; ++ if (!fgets_unlocked(p = line, BUFSIZ, tf)) { ++ goto DONE; ++ } ++ /* skip lines that are too big */ ++ if (!index(p, '\n')) { ++ while ((c = getc_unlocked(tf)) != '\n' && c != EOF) ++ ; ++ continue; ++ } ++ while (isspace(*p)) ++ ++p; ++ if (*p && *p != '#') ++ break; + } + + zapchar = 0; + tty.ty_name = p; + p = skip(p); + if (!*(tty.ty_getty = p)) +- tty.ty_getty = tty.ty_type = NULL; ++ tty.ty_getty = tty.ty_type = NULL; + else { +- p = skip(p); +- if (!*(tty.ty_type = p)) +- tty.ty_type = NULL; +- else +- p = skip(p); ++ p = skip(p); ++ if (!*(tty.ty_type = p)) ++ tty.ty_type = NULL; ++ else ++ p = skip(p); + } + tty.ty_status = 0; + tty.ty_window = NULL; +@@ -151,43 +148,45 @@ struct ttyent * getttyent(void) + #define scmp(e) !strncmp(p, e, sizeof(e) - 1) && isspace(p[sizeof(e) - 1]) + #define vcmp(e) !strncmp(p, e, sizeof(e) - 1) && p[sizeof(e) - 1] == '=' + for (; *p; p = skip(p)) { +- if (scmp(_TTYS_OFF)) +- tty.ty_status &= ~TTY_ON; +- else if (scmp(_TTYS_ON)) +- tty.ty_status |= TTY_ON; +- else if (scmp(_TTYS_SECURE)) +- tty.ty_status |= TTY_SECURE; +- else if (vcmp(_TTYS_WINDOW)) +- tty.ty_window = value(p); +- else +- break; ++ if (scmp(_TTYS_OFF)) ++ tty.ty_status &= ~TTY_ON; ++ else if (scmp(_TTYS_ON)) ++ tty.ty_status |= TTY_ON; ++ else if (scmp(_TTYS_SECURE)) ++ tty.ty_status |= TTY_SECURE; ++ else if (vcmp(_TTYS_WINDOW)) ++ tty.ty_window = value(p); ++ else ++ break; + } +- /* We can release the lock only here since `zapchar' is global. */ +- __STDIO_ALWAYS_THREADUNLOCK(tf); + + if (zapchar == '#' || *p == '#') +- while ((c = *++p) == ' ' || c == '\t') +- ; ++ while ((c = *++p) == ' ' || c == '\t') ++ ; + tty.ty_comment = p; + if (*p == 0) +- tty.ty_comment = 0; ++ tty.ty_comment = 0; + if ((p = index(p, '\n'))) +- *p = '\0'; +- return (&tty); ++ *p = '\0'; ++ retval = &tty; ++ ++ DONE: ++ __STDIO_ALWAYS_THREADUNLOCK(tf); ++ return retval; + } + + int setttyent(void) + { + + if (tf) { +- rewind(tf); +- return (1); ++ rewind(tf); ++ return (1); + } else if ((tf = fopen(_PATH_TTYS, "r"))) { +- /* We do the locking ourselves. */ ++ /* We do the locking ourselves. */ + #ifdef __UCLIBC_HAS_THREADS__ +- __fsetlocking (tf, FSETLOCKING_BYCALLER); ++ __fsetlocking (tf, FSETLOCKING_BYCALLER); + #endif +- return (1); ++ return (1); + } + return (0); + } +@@ -197,9 +196,9 @@ int endttyent(void) + int rval; + + if (tf) { +- rval = !(fclose(tf) == EOF); +- tf = NULL; +- return (rval); ++ rval = !(fclose(tf) == EOF); ++ tf = NULL; ++ return (rval); + } + return (1); + } +diff --git a/libc/misc/utmp/utent.c b/libc/misc/utmp/utent.c +index c1d8d6f..0fc6df4 100644 +--- a/libc/misc/utmp/utent.c ++++ b/libc/misc/utmp/utent.c +@@ -20,19 +20,9 @@ + #include <string.h> + #include <utmp.h> + ++#include <bits/uClibc_mutex.h> + +- +-#ifdef __UCLIBC_HAS_THREADS__ +-#include <pthread.h> +-static pthread_mutex_t utmplock = PTHREAD_MUTEX_INITIALIZER; +-# define LOCK __pthread_mutex_lock(&utmplock) +-# define UNLOCK __pthread_mutex_unlock(&utmplock) +-#else +-# define LOCK +-# define UNLOCK +-#endif +- +- ++__UCLIBC_MUTEX_STATIC(utmplock, PTHREAD_MUTEX_INITIALIZER); + + /* Some global crap */ + static int static_fd = -1; +@@ -46,19 +36,19 @@ static struct utmp *__getutent(int utmp_ + + { + if (utmp_fd == -1) { +- setutent(); ++ setutent(); + } + if (utmp_fd == -1) { +- return NULL; ++ return NULL; + } + +- LOCK; ++ __UCLIBC_MUTEX_LOCK(utmplock); + if (read(utmp_fd, (char *) &static_utmp, sizeof(struct utmp)) != sizeof(struct utmp)) +- { +- return NULL; +- } ++ { ++ return NULL; ++ } + +- UNLOCK; ++ __UCLIBC_MUTEX_UNLOCK(utmplock); + return &static_utmp; + } + +@@ -66,39 +56,39 @@ void setutent(void) + { + int ret; + +- LOCK; ++ __UCLIBC_MUTEX_LOCK(utmplock); + if (static_fd == -1) { +- if ((static_fd = open(static_ut_name, O_RDWR)) < 0) { +- if ((static_fd = open(static_ut_name, O_RDONLY)) < 0) { +- goto bummer; +- } +- } +- /* Make sure the file will be closed on exec() */ +- ret = fcntl(static_fd, F_GETFD, 0); +- if (ret >= 0) { +- ret = fcntl(static_fd, F_GETFD, 0); +- } +- if (ret < 0) { +-bummer: +- UNLOCK; +- static_fd = -1; +- close(static_fd); +- return; +- } ++ if ((static_fd = open(static_ut_name, O_RDWR)) < 0) { ++ if ((static_fd = open(static_ut_name, O_RDONLY)) < 0) { ++ goto bummer; ++ } ++ } ++ /* Make sure the file will be closed on exec() */ ++ ret = fcntl(static_fd, F_GETFD, 0); ++ if (ret >= 0) { ++ ret = fcntl(static_fd, F_GETFD, 0); ++ } ++ if (ret < 0) { ++ bummer: ++ close(static_fd); ++ static_fd = -1; ++ goto DONE; ++ } + } + lseek(static_fd, 0, SEEK_SET); +- UNLOCK; ++ DONE: ++ __UCLIBC_MUTEX_UNLOCK(utmplock); + return; + } + + void endutent(void) + { +- LOCK; ++ __UCLIBC_MUTEX_LOCK(utmplock); + if (static_fd != -1) { +- close(static_fd); ++ close(static_fd); + } + static_fd = -1; +- UNLOCK; ++ __UCLIBC_MUTEX_UNLOCK(utmplock); + } + + /* Locking is done in __getutent */ +@@ -113,22 +103,22 @@ struct utmp *getutid (const struct utmp + struct utmp *lutmp; + + while ((lutmp = __getutent(static_fd)) != NULL) { +- if ( (utmp_entry->ut_type == RUN_LVL || +- utmp_entry->ut_type == BOOT_TIME || +- utmp_entry->ut_type == NEW_TIME || +- utmp_entry->ut_type == OLD_TIME) && +- lutmp->ut_type == utmp_entry->ut_type) +- { +- return lutmp; +- } +- if ( (utmp_entry->ut_type == INIT_PROCESS || +- utmp_entry->ut_type == DEAD_PROCESS || +- utmp_entry->ut_type == LOGIN_PROCESS || +- utmp_entry->ut_type == USER_PROCESS) && +- !strncmp(lutmp->ut_id, utmp_entry->ut_id, sizeof(lutmp->ut_id))) +- { +- return lutmp; +- } ++ if ( (utmp_entry->ut_type == RUN_LVL || ++ utmp_entry->ut_type == BOOT_TIME || ++ utmp_entry->ut_type == NEW_TIME || ++ utmp_entry->ut_type == OLD_TIME) && ++ lutmp->ut_type == utmp_entry->ut_type) ++ { ++ return lutmp; ++ } ++ if ( (utmp_entry->ut_type == INIT_PROCESS || ++ utmp_entry->ut_type == DEAD_PROCESS || ++ utmp_entry->ut_type == LOGIN_PROCESS || ++ utmp_entry->ut_type == USER_PROCESS) && ++ !strncmp(lutmp->ut_id, utmp_entry->ut_id, sizeof(lutmp->ut_id))) ++ { ++ return lutmp; ++ } + } + + return NULL; +@@ -140,11 +130,11 @@ struct utmp *getutline(const struct utmp + struct utmp *lutmp; + + while ((lutmp = __getutent(static_fd)) != NULL) { +- if ((lutmp->ut_type == USER_PROCESS || lutmp->ut_type == LOGIN_PROCESS) && +- !strcmp(lutmp->ut_line, utmp_entry->ut_line)) +- { +- return lutmp; +- } ++ if ((lutmp->ut_type == USER_PROCESS || lutmp->ut_type == LOGIN_PROCESS) && ++ !strcmp(lutmp->ut_line, utmp_entry->ut_line)) ++ { ++ return lutmp; ++ } + } + + return NULL; +@@ -152,42 +142,42 @@ struct utmp *getutline(const struct utmp + + struct utmp *pututline (const struct utmp *utmp_entry) + { +- LOCK; ++ __UCLIBC_MUTEX_LOCK(utmplock); + /* Ignore the return value. That way, if they've already positioned + the file pointer where they want it, everything will work out. */ + lseek(static_fd, (off_t) - sizeof(struct utmp), SEEK_CUR); + + if (getutid(utmp_entry) != NULL) { +- lseek(static_fd, (off_t) - sizeof(struct utmp), SEEK_CUR); +- if (write(static_fd, utmp_entry, sizeof(struct utmp)) != sizeof(struct utmp)) +- return NULL; ++ lseek(static_fd, (off_t) - sizeof(struct utmp), SEEK_CUR); ++ if (write(static_fd, utmp_entry, sizeof(struct utmp)) != sizeof(struct utmp)) ++ return NULL; + } else { +- lseek(static_fd, (off_t) 0, SEEK_END); +- if (write(static_fd, utmp_entry, sizeof(struct utmp)) != sizeof(struct utmp)) +- return NULL; ++ lseek(static_fd, (off_t) 0, SEEK_END); ++ if (write(static_fd, utmp_entry, sizeof(struct utmp)) != sizeof(struct utmp)) ++ return NULL; + } + +- UNLOCK; ++ __UCLIBC_MUTEX_UNLOCK(utmplock); + return (struct utmp *)utmp_entry; + } + + int utmpname (const char *new_ut_name) + { +- LOCK; ++ __UCLIBC_MUTEX_LOCK(utmplock); + if (new_ut_name != NULL) { +- if (static_ut_name != default_file_name) +- free((char *)static_ut_name); +- static_ut_name = strdup(new_ut_name); +- if (static_ut_name == NULL) { +- /* We should probably whine about out-of-memory +- * errors here... Instead just reset to the default */ +- static_ut_name = default_file_name; +- } ++ if (static_ut_name != default_file_name) ++ free((char *)static_ut_name); ++ static_ut_name = strdup(new_ut_name); ++ if (static_ut_name == NULL) { ++ /* We should probably whine about out-of-memory ++ * errors here... Instead just reset to the default */ ++ static_ut_name = default_file_name; ++ } + } + + if (static_fd != -1) +- close(static_fd); +- UNLOCK; ++ close(static_fd); ++ __UCLIBC_MUTEX_UNLOCK(utmplock); + return 0; + } + +diff --git a/libc/misc/wchar/wstdio.c b/libc/misc/wchar/wstdio.c +index b49494f..408c57a 100644 +--- a/libc/misc/wchar/wstdio.c ++++ b/libc/misc/wchar/wstdio.c +@@ -82,9 +82,6 @@ strong_alias(NAME,NAME##_unlocked) \ + void NAME PARAMS + #endif + +-#define __STDIO_THREADLOCK_OPENLIST +-#define __STDIO_THREADUNLOCK_OPENLIST +- + #else /* __UCLIBC_HAS_THREADS__ */ + + #include <pthread.h> +@@ -112,15 +109,6 @@ void NAME PARAMS \ + } \ + void NAME##_unlocked PARAMS + +-#define __STDIO_THREADLOCK_OPENLIST \ +- __pthread_mutex_lock(&_stdio_openlist_lock) +- +-#define __STDIO_THREADUNLOCK_OPENLIST \ +- __pthread_mutex_unlock(&_stdio_openlist_lock) +- +-#define __STDIO_THREADTRYLOCK_OPENLIST \ +- __pthread_mutex_trylock(&_stdio_openlist_lock) +- + #endif /* __UCLIBC_HAS_THREADS__ */ + + #ifndef __STDIO_BUFFERS +diff --git a/libc/pwd_grp/lckpwdf.c b/libc/pwd_grp/lckpwdf.c +index 6b9c251..063fed4 100644 +--- a/libc/pwd_grp/lckpwdf.c ++++ b/libc/pwd_grp/lckpwdf.c +@@ -27,15 +27,9 @@ + #include <sys/file.h> + #include <paths.h> + +-#ifdef __UCLIBC_HAS_THREADS__ +-#include <pthread.h> +-static pthread_mutex_t mylock = PTHREAD_MUTEX_INITIALIZER; +-# define LOCK __pthread_mutex_lock(&mylock) +-# define UNLOCK __pthread_mutex_unlock(&mylock); +-#else +-# define LOCK +-# define UNLOCK +-#endif ++#include <bits/uClibc_mutex.h> ++ ++__UCLIBC_MUTEX_STATIC(mylock, PTHREAD_MUTEX_INITIALIZER); + + /* How long to wait for getting the lock before returning with an + error. */ +@@ -57,18 +51,18 @@ int lckpwdf (void) + struct sigaction new_act; /* New signal action. */ + struct flock fl; /* Information struct for locking. */ + int result; ++ int rv = -1; + + if (lock_fd != -1) + /* Still locked by own process. */ + return -1; + +- LOCK; ++ __UCLIBC_MUTEX_LOCK(mylock); + + lock_fd = open (_PATH_PASSWD, O_WRONLY); + if (lock_fd == -1) { + /* Cannot create lock file. */ +- UNLOCK; +- return -1; ++ goto DONE; + } + + /* Make sure file gets correctly closed when process finished. */ +@@ -77,16 +71,14 @@ int lckpwdf (void) + /* Cannot get file flags. */ + close(lock_fd); + lock_fd = -1; +- UNLOCK; +- return -1; ++ goto DONE; + } + flags |= FD_CLOEXEC; /* Close on exit. */ + if (fcntl (lock_fd, F_SETFD, flags) < 0) { + /* Cannot set new flags. */ + close(lock_fd); + lock_fd = -1; +- UNLOCK; +- return -1; ++ goto DONE; + } + + /* Now we have to get exclusive write access. Since multiple +@@ -107,8 +99,7 @@ int lckpwdf (void) + /* Cannot install signal handler. */ + close(lock_fd); + lock_fd = -1; +- UNLOCK; +- return -1; ++ goto DONE; + } + + /* Now make sure the alarm signal is not blocked. */ +@@ -118,8 +109,7 @@ int lckpwdf (void) + sigaction (SIGALRM, &saved_act, NULL); + close(lock_fd); + lock_fd = -1; +- UNLOCK; +- return -1; ++ goto DONE; + } + + /* Start timer. If we cannot get the lock in the specified time we +@@ -146,12 +136,14 @@ int lckpwdf (void) + if (result < 0) { + close(lock_fd); + lock_fd = -1; +- UNLOCK; +- return -1; ++ goto DONE; + } + +- UNLOCK; +- return 0; ++ rv = 0; ++ ++ DONE: ++ __UCLIBC_MUTEX_UNLOCK(mylock); ++ return rv; + } + + +@@ -164,11 +156,11 @@ int ulckpwdf (void) + result = -1; + } + else { +- LOCK; ++ __UCLIBC_MUTEX_LOCK(mylock); + result = close (lock_fd); + /* Mark descriptor as unused. */ + lock_fd = -1; +- UNLOCK; ++ __UCLIBC_MUTEX_UNLOCK(mylock); + } + + return result; +diff --git a/libc/pwd_grp/pwd_grp.c b/libc/pwd_grp/pwd_grp.c +index 91c0d83..a302c7c 100644 +--- a/libc/pwd_grp/pwd_grp.c ++++ b/libc/pwd_grp/pwd_grp.c +@@ -42,9 +42,8 @@ + #include <pwd.h> + #include <grp.h> + #include <shadow.h> +-#ifdef __UCLIBC_HAS_THREADS__ +-#include <pthread.h> +-#endif ++ ++#include <bits/uClibc_mutex.h> + + /**********************************************************************/ + /* Sizes for staticly allocated buffers. */ +@@ -445,34 +444,27 @@ int getpw(uid_t uid, char *buf) + /**********************************************************************/ + #ifdef L_getpwent_r + +-#ifdef __UCLIBC_HAS_THREADS__ +-static pthread_mutex_t mylock = PTHREAD_MUTEX_INITIALIZER; +-# define LOCK __pthread_mutex_lock(&mylock) +-# define UNLOCK __pthread_mutex_unlock(&mylock); +-#else +-# define LOCK ((void) 0) +-# define UNLOCK ((void) 0) +-#endif ++__UCLIBC_MUTEX_STATIC(mylock, PTHREAD_MUTEX_INITIALIZER); + + static FILE *pwf /*= NULL*/; + + void setpwent(void) + { +- LOCK; ++ __UCLIBC_MUTEX_LOCK(mylock); + if (pwf) { + rewind(pwf); + } +- UNLOCK; ++ __UCLIBC_MUTEX_UNLOCK(mylock); + } + + void endpwent(void) + { +- LOCK; ++ __UCLIBC_MUTEX_LOCK(mylock); + if (pwf) { + fclose(pwf); + pwf = NULL; + } +- UNLOCK; ++ __UCLIBC_MUTEX_UNLOCK(mylock); + } + + +@@ -482,7 +474,7 @@ int getpwent_r(struct passwd *__restrict + { + int rv; + +- LOCK; ++ __UCLIBC_MUTEX_LOCK(mylock); + + *result = NULL; /* In case of error... */ + +@@ -500,7 +492,7 @@ int getpwent_r(struct passwd *__restrict + } + + ERR: +- UNLOCK; ++ __UCLIBC_MUTEX_UNLOCK(mylock); + + return rv; + } +@@ -509,34 +501,27 @@ int getpwent_r(struct passwd *__restrict + /**********************************************************************/ + #ifdef L_getgrent_r + +-#ifdef __UCLIBC_HAS_THREADS__ +-static pthread_mutex_t mylock = PTHREAD_MUTEX_INITIALIZER; +-# define LOCK __pthread_mutex_lock(&mylock) +-# define UNLOCK __pthread_mutex_unlock(&mylock); +-#else +-# define LOCK ((void) 0) +-# define UNLOCK ((void) 0) +-#endif ++__UCLIBC_MUTEX_STATIC(mylock, PTHREAD_MUTEX_INITIALIZER); + + static FILE *grf /*= NULL*/; + + void setgrent(void) + { +- LOCK; ++ __UCLIBC_MUTEX_LOCK(mylock); + if (grf) { + rewind(grf); + } +- UNLOCK; ++ __UCLIBC_MUTEX_UNLOCK(mylock); + } + + void endgrent(void) + { +- LOCK; ++ __UCLIBC_MUTEX_LOCK(mylock); + if (grf) { + fclose(grf); + grf = NULL; + } +- UNLOCK; ++ __UCLIBC_MUTEX_UNLOCK(mylock); + } + + int getgrent_r(struct group *__restrict resultbuf, +@@ -545,7 +530,7 @@ int getgrent_r(struct group *__restrict + { + int rv; + +- LOCK; ++ __UCLIBC_MUTEX_LOCK(mylock); + + *result = NULL; /* In case of error... */ + +@@ -563,7 +548,7 @@ int getgrent_r(struct group *__restrict + } + + ERR: +- UNLOCK; ++ __UCLIBC_MUTEX_UNLOCK(mylock); + + return rv; + } +@@ -572,34 +557,27 @@ int getgrent_r(struct group *__restrict + /**********************************************************************/ + #ifdef L_getspent_r + +-#ifdef __UCLIBC_HAS_THREADS__ +-static pthread_mutex_t mylock = PTHREAD_MUTEX_INITIALIZER; +-# define LOCK __pthread_mutex_lock(&mylock) +-# define UNLOCK __pthread_mutex_unlock(&mylock); +-#else +-# define LOCK ((void) 0) +-# define UNLOCK ((void) 0) +-#endif ++__UCLIBC_MUTEX_STATIC(mylock, PTHREAD_MUTEX_INITIALIZER); + + static FILE *spf /*= NULL*/; + + void setspent(void) + { +- LOCK; ++ __UCLIBC_MUTEX_LOCK(mylock); + if (spf) { + rewind(spf); + } +- UNLOCK; ++ __UCLIBC_MUTEX_UNLOCK(mylock); + } + + void endspent(void) + { +- LOCK; ++ __UCLIBC_MUTEX_LOCK(mylock); + if (spf) { + fclose(spf); + spf = NULL; + } +- UNLOCK; ++ __UCLIBC_MUTEX_UNLOCK(mylock); + } + + int getspent_r(struct spwd *resultbuf, char *buffer, +@@ -607,7 +585,7 @@ int getspent_r(struct spwd *resultbuf, c + { + int rv; + +- LOCK; ++ __UCLIBC_MUTEX_LOCK(mylock); + + *result = NULL; /* In case of error... */ + +@@ -625,7 +603,7 @@ int getspent_r(struct spwd *resultbuf, c + } + + ERR: +- UNLOCK; ++ __UCLIBC_MUTEX_UNLOCK(mylock); + + return rv; + } +diff --git a/libc/stdio/_READ.c b/libc/stdio/_READ.c +index 7d3c38c..fe1bc91 100644 +--- a/libc/stdio/_READ.c ++++ b/libc/stdio/_READ.c +@@ -41,7 +41,7 @@ size_t __stdio_READ(register FILE *strea + #warning EINTR? + #endif + /* RETRY: */ +- if ((rv = __READ(stream, buf, bufsize)) <= 0) { ++ if ((rv = __READ(stream, (char *) buf, bufsize)) <= 0) { + if (rv == 0) { + __STDIO_STREAM_SET_EOF(stream); + } else { +diff --git a/libc/stdio/_WRITE.c b/libc/stdio/_WRITE.c +index d300d39..4131eb7 100644 +--- a/libc/stdio/_WRITE.c ++++ b/libc/stdio/_WRITE.c +@@ -47,7 +47,7 @@ size_t __stdio_WRITE(register FILE *stre + return bufsize; + } + stodo = (todo <= SSIZE_MAX) ? todo : SSIZE_MAX; +- if ((rv = __WRITE(stream, buf, stodo)) >= 0) { ++ if ((rv = __WRITE(stream, (char *) buf, stodo)) >= 0) { + #ifdef __UCLIBC_MJN3_ONLY__ + #warning TODO: Make custom stream write return check optional. + #endif +diff --git a/libc/stdio/_fopen.c b/libc/stdio/_fopen.c +index f7f5bb6..4984f11 100644 +--- a/libc/stdio/_fopen.c ++++ b/libc/stdio/_fopen.c +@@ -194,10 +194,23 @@ FILE *_stdio_fopen(intptr_t fname_or_mod + #endif + + #ifdef __STDIO_HAS_OPENLIST +- __STDIO_THREADLOCK_OPENLIST; +- stream->__nextopen = _stdio_openlist; /* New files are inserted at */ +- _stdio_openlist = stream; /* the head of the list. */ +- __STDIO_THREADUNLOCK_OPENLIST; ++#if defined(__UCLIBC_HAS_THREADS__) && defined(__STDIO_BUFFERS) ++ if (!(stream->__modeflags & __FLAG_FREEFILE)) ++ { ++ /* An freopen call so the file was never removed from the list. */ ++ } ++ else ++#endif ++ { ++ /* We have to lock the del mutex in case another thread wants to fclose() ++ * the last file. */ ++ __STDIO_THREADLOCK_OPENLIST_DEL; ++ __STDIO_THREADLOCK_OPENLIST_ADD; ++ stream->__nextopen = _stdio_openlist; /* New files are inserted at */ ++ _stdio_openlist = stream; /* the head of the list. */ ++ __STDIO_THREADUNLOCK_OPENLIST_ADD; ++ __STDIO_THREADUNLOCK_OPENLIST_DEL; ++ } + #endif + + __STDIO_STREAM_VALIDATE(stream); +diff --git a/libc/stdio/_stdio.c b/libc/stdio/_stdio.c +index 4aae3c4..9cfe02c 100644 +--- a/libc/stdio/_stdio.c ++++ b/libc/stdio/_stdio.c +@@ -151,8 +151,12 @@ FILE *__stdout = _stdio_streams + 1; /* + FILE *_stdio_openlist = _stdio_streams; + + # ifdef __UCLIBC_HAS_THREADS__ +-pthread_mutex_t _stdio_openlist_lock = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP; +-int _stdio_openlist_delflag = 0; ++__UCLIBC_MUTEX_INIT(_stdio_openlist_add_lock, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP); ++#ifdef __STDIO_BUFFERS ++__UCLIBC_MUTEX_INIT(_stdio_openlist_del_lock, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP); ++volatile int _stdio_openlist_use_count = 0; ++int _stdio_openlist_del_count = 0; ++#endif + # endif + + #endif +@@ -162,10 +166,10 @@ int _stdio_openlist_delflag = 0; + /* 2 if threading not initialized and 0 otherwise; */ + int _stdio_user_locking = 2; + +-void __stdio_init_mutex(pthread_mutex_t *m) ++void __stdio_init_mutex(__UCLIBC_MUTEX_TYPE *m) + { +- static const pthread_mutex_t __stdio_mutex_initializer +- = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP; ++ const __UCLIBC_MUTEX_STATIC(__stdio_mutex_initializer, ++ PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP); + + memcpy(m, &__stdio_mutex_initializer, sizeof(__stdio_mutex_initializer)); + } +@@ -184,7 +188,11 @@ void _stdio_term(void) + * locked, then I suppose there is a chance that a pointer in the + * chain might be corrupt due to a partial store. + */ +- __stdio_init_mutex(&_stdio_openlist_lock); ++ __stdio_init_mutex(&_stdio_openlist_add_lock); ++#warning check ++#ifdef __STDIO_BUFFERS ++ __stdio_init_mutex(&_stdio_openlist_del_lock); ++#endif + + /* Next we need to worry about the streams themselves. If a stream + * is currently locked, then it may be in an invalid state. So we +@@ -192,7 +200,7 @@ void _stdio_term(void) + * Then we reinitialize the locks. + */ + for (ptr = _stdio_openlist ; ptr ; ptr = ptr->__nextopen ) { +- if (__STDIO_ALWAYS_THREADTRYLOCK(ptr)) { ++ if (__STDIO_ALWAYS_THREADTRYLOCK_CANCEL_UNSAFE(ptr)) { + /* The stream is already locked, so we don't want to touch it. + * However, if we have custom streams, we can't just close it + * or leave it locked since a custom stream may be stacked +@@ -258,10 +266,6 @@ void _stdio_init(void) + #error Assumption violated about __MASK_READING and __FLAG_UNGOT + #endif + +-#ifdef __UCLIBC_HAS_THREADS__ +-#include <pthread.h> +-#endif +- + #ifndef NDEBUG + + void _stdio_validate_FILE(const FILE *stream) +diff --git a/libc/stdio/_stdio.h b/libc/stdio/_stdio.h +index e3c2c58..decf57d 100644 +--- a/libc/stdio/_stdio.h ++++ b/libc/stdio/_stdio.h +@@ -22,23 +22,57 @@ + #include <wchar.h> + #endif + +-#ifdef __UCLIBC_HAS_THREADS__ +-#include <pthread.h> ++#include <bits/uClibc_mutex.h> + +-#define __STDIO_THREADLOCK_OPENLIST \ +- __pthread_mutex_lock(&_stdio_openlist_lock) ++#define __STDIO_THREADLOCK_OPENLIST_ADD \ ++ __UCLIBC_MUTEX_LOCK(_stdio_openlist_add_lock) + +-#define __STDIO_THREADUNLOCK_OPENLIST \ +- __pthread_mutex_unlock(&_stdio_openlist_lock) ++#define __STDIO_THREADUNLOCK_OPENLIST_ADD \ ++ __UCLIBC_MUTEX_UNLOCK(_stdio_openlist_add_lock) + +-#define __STDIO_THREADTRYLOCK_OPENLIST \ +- __pthread_mutex_trylock(&_stdio_openlist_lock) ++#ifdef __STDIO_BUFFERS + +-#else ++#define __STDIO_THREADLOCK_OPENLIST_DEL \ ++ __UCLIBC_MUTEX_LOCK(_stdio_openlist_del_lock) ++ ++#define __STDIO_THREADUNLOCK_OPENLIST_DEL \ ++ __UCLIBC_MUTEX_UNLOCK(_stdio_openlist_del_lock) + +-#define __STDIO_THREADLOCK_OPENLIST ((void)0) +-#define __STDIO_THREADUNLOCK_OPENLIST ((void)0) ++#define __STDIO_OPENLIST_INC_USE \ ++do { \ ++ __STDIO_THREADLOCK_OPENLIST_DEL; \ ++ ++_stdio_openlist_use_count; \ ++ __STDIO_THREADUNLOCK_OPENLIST_DEL; \ ++} while (0) ++ ++extern void _stdio_openlist_dec_use(void); ++ ++#define __STDIO_OPENLIST_DEC_USE \ ++ _stdio_openlist_dec_use() ++ ++#define __STDIO_OPENLIST_INC_DEL_CNT \ ++do { \ ++ __STDIO_THREADLOCK_OPENLIST_DEL; \ ++ ++_stdio_openlist_del_count; \ ++ __STDIO_THREADUNLOCK_OPENLIST_DEL; \ ++} while (0) ++ ++#define __STDIO_OPENLIST_DEC_DEL_CNT \ ++do { \ ++ __STDIO_THREADLOCK_OPENLIST_DEL; \ ++ --_stdio_openlist_del_count; \ ++ __STDIO_THREADUNLOCK_OPENLIST_DEL; \ ++} while (0) ++ ++#endif /* __STDIO_BUFFERS */ + ++#ifndef __STDIO_THREADLOCK_OPENLIST_DEL ++#define __STDIO_THREADLOCK_OPENLIST_DEL ((void)0) ++#define __STDIO_THREADUNLOCK_OPENLIST_DEL ((void)0) ++#define __STDIO_OPENLIST_INC_USE ((void)0) ++#define __STDIO_OPENLIST_DEC_USE ((void)0) ++#define __STDIO_OPENLIST_INC_DEL_CNT ((void)0) ++#define __STDIO_OPENLIST_DEC_DEL_CNT ((void)0) + #endif + + #define __UNDEFINED_OR_NONPORTABLE ((void)0) +diff --git a/libc/stdio/fclose.c b/libc/stdio/fclose.c +index 4df2e42..dfababc 100644 +--- a/libc/stdio/fclose.c ++++ b/libc/stdio/fclose.c +@@ -12,30 +12,34 @@ int fclose(register FILE *stream) + int rv = 0; + __STDIO_AUTO_THREADLOCK_VAR; + +- /* First, remove the file from the open file list. */ +-#ifdef __STDIO_HAS_OPENLIST +- { +- register FILE *ptr; +- +- __STDIO_THREADLOCK_OPENLIST; +- if ((ptr = _stdio_openlist) == stream) { +- _stdio_openlist = stream->__nextopen; +- } else { +- while (ptr) { +- if (ptr->__nextopen == stream) { +- ptr->__nextopen = stream->__nextopen; +- break; +- } +- ptr = ptr->__nextopen; +- } +- } +- __STDIO_THREADUNLOCK_OPENLIST; +- +- if (!ptr) { /* Did not find stream in the open file list! */ +- return EOF; +- } +- } +-#endif ++#warning dead code... but may want to simply check and not remove ++/* #ifdef __STDIO_HAS_OPENLIST */ ++/* #if !defined(__UCLIBC_HAS_THREADS__) || !defined(__STDIO_BUFFERS) */ ++/* /\* First, remove the file from the open file list. *\/ */ ++/* { */ ++/* register FILE *ptr; */ ++ ++/* __STDIO_THREADLOCK_OPENLIST; */ ++/* if ((ptr = _stdio_openlist) == stream) { */ ++/* #warning does a mod!!! */ ++/* _stdio_openlist = stream->__nextopen; */ ++/* } else { */ ++/* while (ptr) { */ ++/* if (ptr->__nextopen == stream) { */ ++/* ptr->__nextopen = stream->__nextopen; */ ++/* break; */ ++/* } */ ++/* ptr = ptr->__nextopen; */ ++/* } */ ++/* } */ ++/* __STDIO_THREADUNLOCK_OPENLIST; */ ++ ++/* if (!ptr) { /\* Did not find stream in the open file list! *\/ */ ++/* return EOF; */ ++/* } */ ++/* } */ ++/* #endif */ ++/* #endif */ + + __STDIO_AUTO_THREADLOCK(stream); + +@@ -80,7 +84,15 @@ int fclose(register FILE *stream) + __STDIO_AUTO_THREADUNLOCK(stream); + + __STDIO_STREAM_FREE_BUFFER(stream); ++#warning... inefficient - locks and unlocks twice and walks whole list ++#if defined(__UCLIBC_HAS_THREADS__) && defined(__STDIO_BUFFERS) ++ /* inefficient - locks/unlocks twice and walks whole list */ ++ __STDIO_OPENLIST_INC_USE; ++ __STDIO_OPENLIST_INC_DEL_CNT; ++ __STDIO_OPENLIST_DEC_USE; /* This with free the file if necessary. */ ++#else + __STDIO_STREAM_FREE_FILE(stream); ++#endif + + return rv; + } +diff --git a/libc/stdio/fcloseall.c b/libc/stdio/fcloseall.c +index dbb6000..f62281a 100644 +--- a/libc/stdio/fcloseall.c ++++ b/libc/stdio/fcloseall.c +@@ -19,14 +19,34 @@ int fcloseall (void) + #ifdef __STDIO_HAS_OPENLIST + + int retval = 0; ++ FILE *f; + +- __STDIO_THREADLOCK_OPENLIST; +- while (_stdio_openlist) { +- if (fclose(_stdio_openlist)) { ++#warning remove dead code ++/* __STDIO_THREADLOCK_OPENLIST; */ ++/* while (_stdio_openlist) { */ ++/* if (fclose(_stdio_openlist)) { */ ++/* retval = EOF; */ ++/* } */ ++/* } */ ++/* __STDIO_THREADUNLOCK_OPENLIST; */ ++ ++ __STDIO_OPENLIST_INC_USE; ++ ++#warning should probably have a get_head() operation ++ __STDIO_THREADLOCK_OPENLIST_ADD; ++ f = _stdio_openlist; ++ __STDIO_THREADUNLOCK_OPENLIST_ADD; ++ ++ while (f) { ++#warning should probably have a get_next() operation ++ FILE *n = f->__nextopen; ++ if (fclose(f)) { + retval = EOF; + } ++ f = n; + } +- __STDIO_THREADUNLOCK_OPENLIST; ++ ++ __STDIO_OPENLIST_DEC_USE; + + return retval; + +diff --git a/libc/stdio/fflush.c b/libc/stdio/fflush.c +index 6baa0ec..66b65cd 100644 +--- a/libc/stdio/fflush.c ++++ b/libc/stdio/fflush.c +@@ -20,23 +20,50 @@ weak_alias(__fflush_unlocked,fflush_unlo + weak_alias(__fflush_unlocked,fflush); + #endif + +-#ifdef __UCLIBC_HAS_THREADS__ + /* Even if the stream is set to user-locking, we still need to lock + * when all (lbf) writing streams are flushed. */ +-#define MY_STDIO_THREADLOCK(STREAM) \ +- if (_stdio_user_locking != 2) { \ +- __STDIO_ALWAYS_THREADLOCK(STREAM); \ +- } + +-#define MY_STDIO_THREADUNLOCK(STREAM) \ +- if (_stdio_user_locking != 2) { \ +- __STDIO_ALWAYS_THREADUNLOCK(STREAM); \ +- } +-#else +-#define MY_STDIO_THREADLOCK(STREAM) ((void)0) +-#define MY_STDIO_THREADUNLOCK(STREAM) ((void)0) +-#endif ++#define __MY_STDIO_THREADLOCK(__stream) \ ++ __UCLIBC_MUTEX_CONDITIONAL_LOCK((__stream)->__lock, \ ++ (_stdio_user_locking != 2)) ++ ++#define __MY_STDIO_THREADUNLOCK(__stream) \ ++ __UCLIBC_MUTEX_CONDITIONAL_UNLOCK((__stream)->__lock, \ ++ (_stdio_user_locking != 2)) + ++#if defined(__UCLIBC_HAS_THREADS__) && defined(__STDIO_BUFFERS) ++void _stdio_openlist_dec_use(void) ++{ ++ __STDIO_THREADLOCK_OPENLIST_DEL; ++ if ((_stdio_openlist_use_count == 1) && (_stdio_openlist_del_count > 0)) { ++ FILE *p = NULL; ++ FILE *n; ++ FILE *stream; ++ ++ __STDIO_THREADLOCK_OPENLIST_ADD; ++ for (stream = _stdio_openlist; stream; stream = n) { ++#warning walk the list and clear out all fclosed()d files ++ n = stream->__nextopen; ++#warning fix for nonatomic ++ if ((stream->__modeflags & (__FLAG_READONLY|__FLAG_WRITEONLY)) ++ == (__FLAG_READONLY|__FLAG_WRITEONLY) ++ ) { /* The file was closed so remove from the list. */ ++ if (!p) { ++ _stdio_openlist = n; ++ } else { ++ p->__nextopen = n; ++ } ++ __STDIO_STREAM_FREE_FILE(stream); ++ } else { ++ p = stream; ++ } ++ } ++ __STDIO_THREADUNLOCK_OPENLIST_DEL; ++ } ++ --_stdio_openlist_use_count; ++ __STDIO_THREADUNLOCK_OPENLIST_DEL; ++} ++#endif + + int __fflush_unlocked(register FILE *stream) + { +@@ -60,23 +87,39 @@ int __fflush_unlocked(register FILE *str + } + + if (!stream) { /* Flush all (lbf) writing streams. */ +- __STDIO_THREADLOCK_OPENLIST; +- for (stream = _stdio_openlist; stream ; stream = stream->__nextopen) { +- MY_STDIO_THREADLOCK(stream); +- if (!(((stream->__modeflags | bufmask) +- ^ (__FLAG_WRITING|__FLAG_LBF) +- ) & (__FLAG_WRITING|__MASK_BUFMODE)) +- ) { +- if (!__STDIO_COMMIT_WRITE_BUFFER(stream)) { +- __STDIO_STREAM_DISABLE_PUTC(stream); +- __STDIO_STREAM_CLEAR_WRITING(stream); +- } else { +- retval = EOF; ++ ++ __STDIO_OPENLIST_INC_USE; ++ ++ __STDIO_THREADLOCK_OPENLIST_ADD; ++ stream = _stdio_openlist; ++ __STDIO_THREADUNLOCK_OPENLIST_ADD; ++ ++ while(stream) { ++ /* We only care about currently writing streams and do not want to ++ * block trying to obtain mutexes on non-writing streams. */ ++#warning fix for nonatomic ++#warning unnecessary check if no threads ++ if (__STDIO_STREAM_IS_WRITING(stream)) { /* ONLY IF ATOMIC!!! */ ++ __MY_STDIO_THREADLOCK(stream); ++ /* Need to check again once we have the lock. */ ++ if (!(((stream->__modeflags | bufmask) ++ ^ (__FLAG_WRITING|__FLAG_LBF) ++ ) & (__FLAG_WRITING|__MASK_BUFMODE)) ++ ) { ++ if (!__STDIO_COMMIT_WRITE_BUFFER(stream)) { ++ __STDIO_STREAM_DISABLE_PUTC(stream); ++ __STDIO_STREAM_CLEAR_WRITING(stream); ++ } else { ++ retval = EOF; ++ } + } ++ __MY_STDIO_THREADUNLOCK(stream); + } +- MY_STDIO_THREADUNLOCK(stream); ++ stream = stream->__nextopen; + } +- __STDIO_THREADUNLOCK_OPENLIST; ++ ++ __STDIO_OPENLIST_DEC_USE; ++ + } else if (__STDIO_STREAM_IS_WRITING(stream)) { + if (!__STDIO_COMMIT_WRITE_BUFFER(stream)) { + __STDIO_STREAM_DISABLE_PUTC(stream); +diff --git a/libc/stdio/flockfile.c b/libc/stdio/flockfile.c +index 0dcc7c2..3fad711 100644 +--- a/libc/stdio/flockfile.c ++++ b/libc/stdio/flockfile.c +@@ -11,6 +11,6 @@ void flockfile(FILE *stream) + { + __STDIO_STREAM_VALIDATE(stream); + +- __STDIO_ALWAYS_THREADLOCK(stream); ++ __STDIO_ALWAYS_THREADLOCK_CANCEL_UNSAFE(stream); + } + +diff --git a/libc/stdio/freopen.c b/libc/stdio/freopen.c +index 0eccaac..36b8488 100644 +--- a/libc/stdio/freopen.c ++++ b/libc/stdio/freopen.c +@@ -42,6 +42,8 @@ FILE *freopen(const char * __restrict fi + + __STDIO_STREAM_VALIDATE(stream); + ++ __STDIO_OPENLIST_INC_USE; /* Do not remove the file from the list. */ ++ + /* First, flush and close, but don't deallocate, the stream. */ + /* This also removes the stream for the open file list. */ + dynmode = (stream->__modeflags & (__FLAG_FREEBUF|__FLAG_FREEFILE)); +@@ -57,9 +59,16 @@ FILE *freopen(const char * __restrict fi + + fp = _stdio_fopen(((intptr_t) filename), mode, stream, FILEDES_ARG); + ++#warning if fp is NULL, then we do not free file (but beware stdin,stdout,stderr) ++ if (fp) { ++ __STDIO_OPENLIST_DEC_DEL_CNT; ++ } ++ + /* Reset the allocation flags. */ + stream->__modeflags |= dynmode; + ++ __STDIO_OPENLIST_DEC_USE; ++ + __STDIO_AUTO_THREADUNLOCK(stream); + + return fp; +diff --git a/libc/stdio/ftello.c b/libc/stdio/ftello.c +index 7092f34..69385ce 100644 +--- a/libc/stdio/ftello.c ++++ b/libc/stdio/ftello.c +@@ -48,7 +48,10 @@ OFFSET_TYPE FTELL(register FILE *stream) + + __STDIO_STREAM_VALIDATE(stream); + +- if ((__SEEK(stream, &pos, SEEK_CUR) < 0) ++ if ((__SEEK(stream, &pos, ++ ((__STDIO_STREAM_IS_WRITING(stream) ++ && (stream->__modeflags & __FLAG_APPEND)) ++ ? SEEK_END : SEEK_CUR)) < 0) + || (__stdio_adjust_position(stream, &pos) < 0)) { + pos = -1; + } +diff --git a/libc/stdio/ftrylockfile.c b/libc/stdio/ftrylockfile.c +index d85b8ff..0d2e156 100644 +--- a/libc/stdio/ftrylockfile.c ++++ b/libc/stdio/ftrylockfile.c +@@ -15,5 +15,5 @@ int ftrylockfile(FILE *stream) + { + __STDIO_STREAM_VALIDATE(stream); + +- return __STDIO_ALWAYS_THREADTRYLOCK(stream); ++ return __STDIO_ALWAYS_THREADTRYLOCK_CANCEL_UNSAFE(stream); + } +diff --git a/libc/stdio/funlockfile.c b/libc/stdio/funlockfile.c +index 048c093..2ddf097 100644 +--- a/libc/stdio/funlockfile.c ++++ b/libc/stdio/funlockfile.c +@@ -11,5 +11,5 @@ void funlockfile(FILE *stream) + { + __STDIO_STREAM_VALIDATE(stream); + +- __STDIO_ALWAYS_THREADUNLOCK(stream); ++ __STDIO_ALWAYS_THREADUNLOCK_CANCEL_UNSAFE(stream); + } +diff --git a/libc/stdio/popen.c b/libc/stdio/popen.c +index c7887ad..ab8d296 100644 +--- a/libc/stdio/popen.c ++++ b/libc/stdio/popen.c +@@ -14,6 +14,7 @@ + * Fix failure exit code for failed execve(). + */ + ++#warning hmm... susv3 says "Pipe streams are byte-oriented." + + #include <stdio.h> + #include <stdlib.h> +@@ -21,6 +22,8 @@ + #include <unistd.h> + #include <sys/wait.h> + ++#include <bits/uClibc_mutex.h> ++ + /* uClinux-2.0 has vfork, but Linux 2.0 doesn't */ + #include <sys/syscall.h> + #if ! defined __NR_vfork +@@ -29,19 +32,11 @@ + # define VFORK_UNLOCK ((void) 0) + #endif + +-#ifdef __UCLIBC_HAS_THREADS__ +-#include <pthread.h> +-static pthread_mutex_t mylock = PTHREAD_MUTEX_INITIALIZER; +-# define LOCK __pthread_mutex_lock(&mylock) +-# define UNLOCK __pthread_mutex_unlock(&mylock); +-#else +-# define LOCK ((void) 0) +-# define UNLOCK ((void) 0) +-#endif ++__UCLIBC_MUTEX_STATIC(mylock, PTHREAD_MUTEX_INITIALIZER); + + #ifndef VFORK_LOCK +-# define VFORK_LOCK LOCK +-# define VFORK_UNLOCK UNLOCK ++# define VFORK_LOCK __UCLIBC_MUTEX_LOCK(mylock) ++# define VFORK_UNLOCK __UCLIBC_MUTEX_UNLOCK(mylock) + #endif + + struct popen_list_item { +@@ -118,10 +113,10 @@ FILE *popen(const char *command, const c + if (pid > 0) { /* Parent of vfork... */ + pi->pid = pid; + pi->f = fp; +- LOCK; ++ __UCLIBC_MUTEX_LOCK(mylock); + pi->next = popen_list; + popen_list = pi; +- UNLOCK; ++ __UCLIBC_MUTEX_UNLOCK(mylock); + + return fp; + } +@@ -136,6 +131,8 @@ FILE *popen(const char *command, const c + return NULL; + } + ++#warning is pclose correct wrt the new mutex semantics? ++ + int pclose(FILE *stream) + { + struct popen_list_item *p; +@@ -144,7 +141,7 @@ int pclose(FILE *stream) + + /* First, find the list entry corresponding to stream and remove it + * from the list. Set p to the list item (NULL if not found). */ +- LOCK; ++ __UCLIBC_MUTEX_LOCK(mylock); + if ((p = popen_list) != NULL) { + if (p->f == stream) { + popen_list = p->next; +@@ -163,7 +160,7 @@ int pclose(FILE *stream) + } while (1); + } + } +- UNLOCK; ++ __UCLIBC_MUTEX_UNLOCK(mylock); + + if (p) { + pid = p->pid; /* Save the pid we need */ +diff --git a/libc/stdio/setvbuf.c b/libc/stdio/setvbuf.c +index 3fe62c6..6d53ab1 100644 +--- a/libc/stdio/setvbuf.c ++++ b/libc/stdio/setvbuf.c +@@ -75,8 +75,8 @@ int setvbuf(register FILE * __restrict s + } + + stream->__modeflags |= alloc_flag; +- stream->__bufstart = buf; +- stream->__bufend = buf + size; ++ stream->__bufstart = (unsigned char *) buf; ++ stream->__bufend = (unsigned char *) buf + size; + __STDIO_STREAM_INIT_BUFREAD_BUFPOS(stream); + __STDIO_STREAM_DISABLE_GETC(stream); + __STDIO_STREAM_DISABLE_PUTC(stream); +diff --git a/libc/stdio/vasprintf.c b/libc/stdio/vasprintf.c +index 688ab7c..6d7664d 100644 +--- a/libc/stdio/vasprintf.c ++++ b/libc/stdio/vasprintf.c +@@ -63,6 +63,8 @@ int vasprintf(char **__restrict buf, con + free(*buf); + *buf = NULL; + } ++ } else { ++ rv = -1; + } + } + +diff --git a/libc/stdio/vdprintf.c b/libc/stdio/vdprintf.c +index de8362c..7cb707f 100644 +--- a/libc/stdio/vdprintf.c ++++ b/libc/stdio/vdprintf.c +@@ -15,8 +15,8 @@ int vdprintf(int filedes, const char * _ + #ifdef __STDIO_BUFFERS + char buf[64]; /* TODO: provide _optional_ buffering? */ + +- f.__bufend = buf + sizeof(buf); +- f.__bufstart = buf; ++ f.__bufend = (unsigned char *) buf + sizeof(buf); ++ f.__bufstart = (unsigned char *) buf; + __STDIO_STREAM_DISABLE_GETC(&f); + __STDIO_STREAM_DISABLE_PUTC(&f); + __STDIO_STREAM_INIT_BUFREAD_BUFPOS(&f); +diff --git a/libc/stdio/vfprintf.c b/libc/stdio/vfprintf.c +index 10114f0..9214e3b 100644 +--- a/libc/stdio/vfprintf.c ++++ b/libc/stdio/vfprintf.c +@@ -569,7 +569,7 @@ int _ppfs_init(register ppfs_t *ppfs, co + ppfs->fmtpos = fmt0; /* rewind */ + } + +-#ifdef NL_MAX_ARG ++#ifdef NL_ARGMAX + /* If we have positional args, make sure we know all the types. */ + { + register int *p = ppfs->argtype; +@@ -581,7 +581,7 @@ int _ppfs_init(register ppfs_t *ppfs, co + ++p; + } + } +-#endif /* NL_MAX_ARG */ ++#endif /* NL_ARGMAX */ + + return 0; + } +@@ -1214,7 +1214,7 @@ static size_t _fp_out_narrow(FILE *fp, i + } + len = buflen; + } +- return r + OUTNSTR(fp, (const char *) buf, len); ++ return r + OUTNSTR(fp, (const unsigned char *) buf, len); + } + + #endif /* __STDIO_PRINTF_FLOAT */ +diff --git a/libc/stdlib/abort.c b/libc/stdlib/abort.c +index 77c2cdc..9f69918 100644 +--- a/libc/stdlib/abort.c ++++ b/libc/stdlib/abort.c +@@ -70,16 +70,9 @@ extern void _exit __P((int __status)) __ + static int been_there_done_that = 0; + + /* Be prepared in case multiple threads try to abort() */ +-#ifdef __UCLIBC_HAS_THREADS__ +-# include <pthread.h> +-static pthread_mutex_t mylock = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP; +-# define LOCK __pthread_mutex_lock(&mylock) +-# define UNLOCK __pthread_mutex_unlock(&mylock) +-#else +-# define LOCK +-# define UNLOCK +-#endif ++#include <bits/uClibc_mutex.h> + ++__UCLIBC_MUTEX_STATIC(mylock, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP); + + /* Cause an abnormal program termination with core-dump */ + void abort(void) +@@ -87,7 +80,7 @@ void abort(void) + sigset_t sigset; + + /* Make sure we acquire the lock before proceeding */ +- LOCK; ++ __UCLIBC_MUTEX_LOCK_CANCEL_UNSAFE(mylock); + + /* Unmask SIGABRT to be sure we can get it */ + if (__sigemptyset(&sigset) == 0 && __sigaddset(&sigset, SIGABRT) == 0) { +@@ -110,9 +103,9 @@ void abort(void) + #endif + + abort_it: +- UNLOCK; ++ __UCLIBC_MUTEX_UNLOCK_CANCEL_UNSAFE(mylock); + raise(SIGABRT); +- LOCK; ++ __UCLIBC_MUTEX_LOCK_CANCEL_UNSAFE(mylock); + } + + /* Still here? Try to remove any signal handlers */ +diff --git a/libc/stdlib/atexit.c b/libc/stdlib/atexit.c +index 280f42c..b028068 100644 +--- a/libc/stdlib/atexit.c ++++ b/libc/stdlib/atexit.c +@@ -40,17 +40,9 @@ + #include <stdlib.h> + #include <errno.h> + ++#include <bits/uClibc_mutex.h> + +-#ifdef __UCLIBC_HAS_THREADS__ +-#include <pthread.h> +-extern pthread_mutex_t mylock; +-# define LOCK __pthread_mutex_lock(&mylock) +-# define UNLOCK __pthread_mutex_unlock(&mylock); +-#else +-# define LOCK +-# define UNLOCK +-#endif +- ++__UCLIBC_MUTEX_EXTERN(__atexit_lock); + + typedef void (*aefuncp) (void); /* atexit function pointer */ + typedef void (*oefuncp) (int, void *); /* on_exit function pointer */ +@@ -90,8 +82,9 @@ extern struct exit_function __exit_funct + int atexit(aefuncp func) + { + struct exit_function *efp; ++ int rv = -1; + +- LOCK; ++ __UCLIBC_MUTEX_LOCK(__atexit_lock); + if (func) { + #ifdef __UCLIBC_DYNAMIC_ATEXIT__ + /* If we are out of function table slots, make some more */ +@@ -99,18 +92,16 @@ int atexit(aefuncp func) + efp=realloc(__exit_function_table, + (__exit_slots+20)*sizeof(struct exit_function)); + if (efp==NULL) { +- UNLOCK; + __set_errno(ENOMEM); +- return -1; ++ goto DONE; + } + __exit_function_table = efp; + __exit_slots+=20; + } + #else + if (__exit_count >= __UCLIBC_MAX_ATEXIT) { +- UNLOCK; + __set_errno(ENOMEM); +- return -1; ++ goto DONE; + } + #endif + __exit_cleanup = __exit_handler; /* enable cleanup */ +@@ -118,8 +109,12 @@ int atexit(aefuncp func) + efp->type = ef_atexit; + efp->funcs.atexit = func; + } +- UNLOCK; +- return 0; ++ ++ rv = 0; ++ ++ DONE: ++ __UCLIBC_MUTEX_UNLOCK(__atexit_lock); ++ return rv; + } + #endif + +@@ -133,8 +128,9 @@ int atexit(aefuncp func) + int on_exit(oefuncp func, void *arg) + { + struct exit_function *efp; ++ int rv = -1; + +- LOCK; ++ __UCLIBC_MUTEX_LOCK(__atexit_lock); + if (func) { + #ifdef __UCLIBC_DYNAMIC_ATEXIT__ + /* If we are out of function table slots, make some more */ +@@ -142,18 +138,16 @@ int on_exit(oefuncp func, void *arg) + efp=realloc(__exit_function_table, + (__exit_slots+20)*sizeof(struct exit_function)); + if (efp==NULL) { +- UNLOCK; + __set_errno(ENOMEM); +- return -1; ++ goto DONE; + } + __exit_function_table=efp; + __exit_slots+=20; + } + #else + if (__exit_count >= __UCLIBC_MAX_ATEXIT) { +- UNLOCK; + __set_errno(ENOMEM); +- return -1; ++ goto DONE; + } + #endif + +@@ -163,8 +157,12 @@ int on_exit(oefuncp func, void *arg) + efp->funcs.on_exit.func = func; + efp->funcs.on_exit.arg = arg; + } +- UNLOCK; +- return 0; ++ ++ rv = 0; ++ ++ DONE: ++ __UCLIBC_MUTEX_UNLOCK(__atexit_lock); ++ return rv; + } + #endif + +@@ -214,9 +212,8 @@ void __exit_handler(int status) + #ifdef L_exit + extern void weak_function _stdio_term(void); + void (*__exit_cleanup) (int) = 0; +-#ifdef __UCLIBC_HAS_THREADS__ +-pthread_mutex_t mylock = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP; +-#endif ++ ++__UCLIBC_MUTEX_INIT(__atexit_lock, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP); + + #ifdef __UCLIBC_CTOR_DTOR__ + extern void (*__app_fini)(void); +@@ -229,11 +226,11 @@ extern void (*__rtld_fini)(void); + void exit(int rv) + { + /* Perform exit-specific cleanup (atexit and on_exit) */ +- LOCK; ++ __UCLIBC_MUTEX_LOCK(__atexit_lock); + if (__exit_cleanup) { + __exit_cleanup(rv); + } +- UNLOCK; ++ __UCLIBC_MUTEX_UNLOCK(__atexit_lock); + + #ifdef __UCLIBC_CTOR_DTOR__ + if (__app_fini != NULL) +diff --git a/libc/stdlib/malloc-simple/alloc.c b/libc/stdlib/malloc-simple/alloc.c +index ed14c37..519a875 100644 +--- a/libc/stdlib/malloc-simple/alloc.c ++++ b/libc/stdlib/malloc-simple/alloc.c +@@ -108,15 +108,14 @@ void free(void *ptr) + #endif + + #ifdef L_memalign +-#ifdef __UCLIBC_HAS_THREADS__ +-#include <pthread.h> +-pthread_mutex_t __malloc_lock = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP; +-# define LOCK __pthread_mutex_lock(&__malloc_lock) +-# define UNLOCK __pthread_mutex_unlock(&__malloc_lock); +-#else +-# define LOCK +-# define UNLOCK +-#endif ++ ++#include <bits/uClibc_mutex.h> ++ ++__UCLIBC_MUTEX_EXTERN(__malloc_lock); ++ ++#define __MALLOC_LOCK __UCLIBC_MUTEX_LOCK(__malloc_lock) ++#define __MALLOC_UNLOCK __UCLIBC_MUTEX_UNLOCK(__malloc_lock) ++ + + /* List of blocks allocated with memalign or valloc */ + struct alignlist +@@ -135,7 +134,7 @@ int __libc_free_aligned(void *ptr) + if (ptr == NULL) + return 0; + +- LOCK; ++ __MALLOC_LOCK; + for (l = _aligned_blocks; l != NULL; l = l->next) { + if (l->aligned == ptr) { + /* Mark the block as free */ +@@ -146,7 +145,7 @@ int __libc_free_aligned(void *ptr) + return 1; + } + } +- UNLOCK; ++ __MALLOC_UNLOCK; + return 0; + } + void * memalign (size_t alignment, size_t size) +@@ -159,10 +158,10 @@ void * memalign (size_t alignment, size_ + return NULL; + + adj = (unsigned long int) ((unsigned long int) ((char *) result - +- (char *) NULL)) % alignment; ++ (char *) NULL)) % alignment; + if (adj != 0) { + struct alignlist *l; +- LOCK; ++ __MALLOC_LOCK; + for (l = _aligned_blocks; l != NULL; l = l->next) + if (l->aligned == NULL) + /* This slot is free. Use it. */ +@@ -171,15 +170,16 @@ void * memalign (size_t alignment, size_ + l = (struct alignlist *) malloc (sizeof (struct alignlist)); + if (l == NULL) { + free(result); +- UNLOCK; +- return NULL; ++ result = NULL; ++ goto DONE; + } + l->next = _aligned_blocks; + _aligned_blocks = l; + } + l->exact = result; + result = l->aligned = (char *) result + alignment - adj; +- UNLOCK; ++ DONE: ++ __MALLOC_UNLOCK; + } + + return result; +diff --git a/libc/stdlib/malloc-standard/calloc.c b/libc/stdlib/malloc-standard/calloc.c +index a67dad7..4277954 100644 +--- a/libc/stdlib/malloc-standard/calloc.c ++++ b/libc/stdlib/malloc-standard/calloc.c +@@ -8,7 +8,7 @@ + VERSION 2.7.2 Sat Aug 17 09:07:30 2002 Doug Lea (dl at gee) + + Note: There may be an updated version of this malloc obtainable at +- ftp://gee.cs.oswego.edu/pub/misc/malloc.c ++ ftp://gee.cs.oswego.edu/pub/misc/malloc.c + Check before installing! + + Hacked up for uClibc by Erik Andersen <andersen@codepoet.org> +@@ -31,63 +31,63 @@ void* calloc(size_t n_elements, size_t e + * to fall through and call malloc(0) */ + size = n_elements * elem_size; + if (n_elements && elem_size != (size / n_elements)) { +- __set_errno(ENOMEM); +- return NULL; ++ __set_errno(ENOMEM); ++ return NULL; + } + +- LOCK; ++ __MALLOC_LOCK; + mem = malloc(size); + if (mem != 0) { +- p = mem2chunk(mem); ++ p = mem2chunk(mem); + +- if (!chunk_is_mmapped(p)) +- { +- /* +- Unroll clear of <= 36 bytes (72 if 8byte sizes) +- We know that contents have an odd number of +- size_t-sized words; minimally 3. +- */ +- +- d = (size_t*)mem; +- clearsize = chunksize(p) - (sizeof(size_t)); +- nclears = clearsize / sizeof(size_t); +- assert(nclears >= 3); +- +- if (nclears > 9) +- memset(d, 0, clearsize); +- +- else { +- *(d+0) = 0; +- *(d+1) = 0; +- *(d+2) = 0; +- if (nclears > 4) { +- *(d+3) = 0; +- *(d+4) = 0; +- if (nclears > 6) { +- *(d+5) = 0; +- *(d+6) = 0; +- if (nclears > 8) { +- *(d+7) = 0; +- *(d+8) = 0; ++ if (!chunk_is_mmapped(p)) ++ { ++ /* ++ Unroll clear of <= 36 bytes (72 if 8byte sizes) ++ We know that contents have an odd number of ++ size_t-sized words; minimally 3. ++ */ ++ ++ d = (size_t*)mem; ++ clearsize = chunksize(p) - (sizeof(size_t)); ++ nclears = clearsize / sizeof(size_t); ++ assert(nclears >= 3); ++ ++ if (nclears > 9) ++ memset(d, 0, clearsize); ++ ++ else { ++ *(d+0) = 0; ++ *(d+1) = 0; ++ *(d+2) = 0; ++ if (nclears > 4) { ++ *(d+3) = 0; ++ *(d+4) = 0; ++ if (nclears > 6) { ++ *(d+5) = 0; ++ *(d+6) = 0; ++ if (nclears > 8) { ++ *(d+7) = 0; ++ *(d+8) = 0; ++ } ++ } ++ } ++ } + } +- } +- } +- } +- } + #if 0 +- else +- { +- /* Standard unix mmap using /dev/zero clears memory so calloc +- * doesn't need to actually zero anything.... +- */ +- d = (size_t*)mem; +- /* Note the additional (sizeof(size_t)) */ +- clearsize = chunksize(p) - 2*(sizeof(size_t)); +- memset(d, 0, clearsize); +- } ++ else ++ { ++ /* Standard unix mmap using /dev/zero clears memory so calloc ++ * doesn't need to actually zero anything.... ++ */ ++ d = (size_t*)mem; ++ /* Note the additional (sizeof(size_t)) */ ++ clearsize = chunksize(p) - 2*(sizeof(size_t)); ++ memset(d, 0, clearsize); ++ } + #endif + } +- UNLOCK; ++ __MALLOC_UNLOCK; + return mem; + } + +diff --git a/libc/stdlib/malloc-standard/free.c b/libc/stdlib/malloc-standard/free.c +index 94e1d65..4e08ef7 100644 +--- a/libc/stdlib/malloc-standard/free.c ++++ b/libc/stdlib/malloc-standard/free.c +@@ -8,7 +8,7 @@ + VERSION 2.7.2 Sat Aug 17 09:07:30 2002 Doug Lea (dl at gee) + + Note: There may be an updated version of this malloc obtainable at +- ftp://gee.cs.oswego.edu/pub/misc/malloc.c ++ ftp://gee.cs.oswego.edu/pub/misc/malloc.c + Check before installing! + + Hacked up for uClibc by Erik Andersen <andersen@codepoet.org> +@@ -42,71 +42,71 @@ static int __malloc_trim(size_t pad, mst + + if (extra > 0) { + +- /* +- Only proceed if end of memory is where we last set it. +- This avoids problems if there were foreign sbrk calls. +- */ +- current_brk = (char*)(MORECORE(0)); +- if (current_brk == (char*)(av->top) + top_size) { +- +- /* +- Attempt to release memory. We ignore MORECORE return value, +- and instead call again to find out where new end of memory is. +- This avoids problems if first call releases less than we asked, +- of if failure somehow altered brk value. (We could still +- encounter problems if it altered brk in some very bad way, +- but the only thing we can do is adjust anyway, which will cause +- some downstream failure.) +- */ +- +- MORECORE(-extra); +- new_brk = (char*)(MORECORE(0)); +- +- if (new_brk != (char*)MORECORE_FAILURE) { +- released = (long)(current_brk - new_brk); +- +- if (released != 0) { +- /* Success. Adjust top. */ +- av->sbrked_mem -= released; +- set_head(av->top, (top_size - released) | PREV_INUSE); +- check_malloc_state(); +- return 1; ++ /* ++ Only proceed if end of memory is where we last set it. ++ This avoids problems if there were foreign sbrk calls. ++ */ ++ current_brk = (char*)(MORECORE(0)); ++ if (current_brk == (char*)(av->top) + top_size) { ++ ++ /* ++ Attempt to release memory. We ignore MORECORE return value, ++ and instead call again to find out where new end of memory is. ++ This avoids problems if first call releases less than we asked, ++ of if failure somehow altered brk value. (We could still ++ encounter problems if it altered brk in some very bad way, ++ but the only thing we can do is adjust anyway, which will cause ++ some downstream failure.) ++ */ ++ ++ MORECORE(-extra); ++ new_brk = (char*)(MORECORE(0)); ++ ++ if (new_brk != (char*)MORECORE_FAILURE) { ++ released = (long)(current_brk - new_brk); ++ ++ if (released != 0) { ++ /* Success. Adjust top. */ ++ av->sbrked_mem -= released; ++ set_head(av->top, (top_size - released) | PREV_INUSE); ++ check_malloc_state(); ++ return 1; ++ } ++ } + } +- } +- } + } + return 0; + } + + /* ------------------------- malloc_trim ------------------------- +- malloc_trim(size_t pad); ++ malloc_trim(size_t pad); + +- If possible, gives memory back to the system (via negative +- arguments to sbrk) if there is unused memory at the `high' end of +- the malloc pool. You can call this after freeing large blocks of +- memory to potentially reduce the system-level memory requirements +- of a program. However, it cannot guarantee to reduce memory. Under +- some allocation patterns, some large free blocks of memory will be +- locked between two used chunks, so they cannot be given back to +- the system. +- +- The `pad' argument to malloc_trim represents the amount of free +- trailing space to leave untrimmed. If this argument is zero, +- only the minimum amount of memory to maintain internal data +- structures will be left (one page or less). Non-zero arguments +- can be supplied to maintain enough trailing space to service +- future expected allocations without having to re-obtain memory +- from the system. +- +- Malloc_trim returns 1 if it actually released any memory, else 0. +- On systems that do not support "negative sbrks", it will always +- return 0. ++ If possible, gives memory back to the system (via negative ++ arguments to sbrk) if there is unused memory at the `high' end of ++ the malloc pool. You can call this after freeing large blocks of ++ memory to potentially reduce the system-level memory requirements ++ of a program. However, it cannot guarantee to reduce memory. Under ++ some allocation patterns, some large free blocks of memory will be ++ locked between two used chunks, so they cannot be given back to ++ the system. ++ ++ The `pad' argument to malloc_trim represents the amount of free ++ trailing space to leave untrimmed. If this argument is zero, ++ only the minimum amount of memory to maintain internal data ++ structures will be left (one page or less). Non-zero arguments ++ can be supplied to maintain enough trailing space to service ++ future expected allocations without having to re-obtain memory ++ from the system. ++ ++ Malloc_trim returns 1 if it actually released any memory, else 0. ++ On systems that do not support "negative sbrks", it will always ++ return 0. + */ + int malloc_trim(size_t pad) + { +- mstate av = get_malloc_state(); +- __malloc_consolidate(av); +- return __malloc_trim(pad, av); ++ mstate av = get_malloc_state(); ++ __malloc_consolidate(av); ++ return __malloc_trim(pad, av); + } + + /* +@@ -125,8 +125,8 @@ static void malloc_init_state(mstate av) + + /* Establish circular links for normal bins */ + for (i = 1; i < NBINS; ++i) { +- bin = bin_at(av,i); +- bin->fd = bin->bk = bin; ++ bin = bin_at(av,i); ++ bin->fd = bin->bk = bin; + } + + av->top_pad = DEFAULT_TOP_PAD; +@@ -157,15 +157,15 @@ static void malloc_init_state(mstate av) + + /* ------------------------- __malloc_consolidate ------------------------- + +- __malloc_consolidate is a specialized version of free() that tears +- down chunks held in fastbins. Free itself cannot be used for this +- purpose since, among other things, it might place chunks back onto +- fastbins. So, instead, we need to use a minor variant of the same +- code. +- +- Also, because this routine needs to be called the first time through +- malloc anyway, it turns out to be the perfect place to trigger +- initialization code. ++__malloc_consolidate is a specialized version of free() that tears ++down chunks held in fastbins. Free itself cannot be used for this ++purpose since, among other things, it might place chunks back onto ++fastbins. So, instead, we need to use a minor variant of the same ++code. ++ ++Also, because this routine needs to be called the first time through ++malloc anyway, it turns out to be the perfect place to trigger ++initialization code. + */ + void __malloc_consolidate(mstate av) + { +@@ -186,78 +186,78 @@ void __malloc_consolidate(mstate av) + mchunkptr fwd; + + /* +- If max_fast is 0, we know that av hasn't +- yet been initialized, in which case do so below +- */ ++ If max_fast is 0, we know that av hasn't ++ yet been initialized, in which case do so below ++ */ + + if (av->max_fast != 0) { +- clear_fastchunks(av); ++ clear_fastchunks(av); + +- unsorted_bin = unsorted_chunks(av); ++ unsorted_bin = unsorted_chunks(av); + +- /* +- Remove each chunk from fast bin and consolidate it, placing it +- then in unsorted bin. Among other reasons for doing this, +- placing in unsorted bin avoids needing to calculate actual bins +- until malloc is sure that chunks aren't immediately going to be +- reused anyway. +- */ +- +- maxfb = &(av->fastbins[fastbin_index(av->max_fast)]); +- fb = &(av->fastbins[0]); +- do { +- if ( (p = *fb) != 0) { +- *fb = 0; ++ /* ++ Remove each chunk from fast bin and consolidate it, placing it ++ then in unsorted bin. Among other reasons for doing this, ++ placing in unsorted bin avoids needing to calculate actual bins ++ until malloc is sure that chunks aren't immediately going to be ++ reused anyway. ++ */ + ++ maxfb = &(av->fastbins[fastbin_index(av->max_fast)]); ++ fb = &(av->fastbins[0]); + do { +- check_inuse_chunk(p); +- nextp = p->fd; ++ if ( (p = *fb) != 0) { ++ *fb = 0; + +- /* Slightly streamlined version of consolidation code in free() */ +- size = p->size & ~PREV_INUSE; +- nextchunk = chunk_at_offset(p, size); +- nextsize = chunksize(nextchunk); ++ do { ++ check_inuse_chunk(p); ++ nextp = p->fd; ++ ++ /* Slightly streamlined version of consolidation code in free() */ ++ size = p->size & ~PREV_INUSE; ++ nextchunk = chunk_at_offset(p, size); ++ nextsize = chunksize(nextchunk); ++ ++ if (!prev_inuse(p)) { ++ prevsize = p->prev_size; ++ size += prevsize; ++ p = chunk_at_offset(p, -((long) prevsize)); ++ unlink(p, bck, fwd); ++ } ++ ++ if (nextchunk != av->top) { ++ nextinuse = inuse_bit_at_offset(nextchunk, nextsize); ++ set_head(nextchunk, nextsize); ++ ++ if (!nextinuse) { ++ size += nextsize; ++ unlink(nextchunk, bck, fwd); ++ } ++ ++ first_unsorted = unsorted_bin->fd; ++ unsorted_bin->fd = p; ++ first_unsorted->bk = p; ++ ++ set_head(p, size | PREV_INUSE); ++ p->bk = unsorted_bin; ++ p->fd = first_unsorted; ++ set_foot(p, size); ++ } ++ ++ else { ++ size += nextsize; ++ set_head(p, size | PREV_INUSE); ++ av->top = p; ++ } + +- if (!prev_inuse(p)) { +- prevsize = p->prev_size; +- size += prevsize; +- p = chunk_at_offset(p, -((long) prevsize)); +- unlink(p, bck, fwd); +- } ++ } while ( (p = nextp) != 0); + +- if (nextchunk != av->top) { +- nextinuse = inuse_bit_at_offset(nextchunk, nextsize); +- set_head(nextchunk, nextsize); +- +- if (!nextinuse) { +- size += nextsize; +- unlink(nextchunk, bck, fwd); + } +- +- first_unsorted = unsorted_bin->fd; +- unsorted_bin->fd = p; +- first_unsorted->bk = p; +- +- set_head(p, size | PREV_INUSE); +- p->bk = unsorted_bin; +- p->fd = first_unsorted; +- set_foot(p, size); +- } +- +- else { +- size += nextsize; +- set_head(p, size | PREV_INUSE); +- av->top = p; +- } +- +- } while ( (p = nextp) != 0); +- +- } +- } while (fb++ != maxfb); ++ } while (fb++ != maxfb); + } + else { +- malloc_init_state(av); +- check_malloc_state(); ++ malloc_init_state(av); ++ check_malloc_state(); + } + } + +@@ -279,9 +279,9 @@ void free(void* mem) + + /* free(0) has no effect */ + if (mem == NULL) +- return; ++ return; + +- LOCK; ++ __MALLOC_LOCK; + av = get_malloc_state(); + p = mem2chunk(mem); + size = chunksize(p); +@@ -289,9 +289,9 @@ void free(void* mem) + check_inuse_chunk(p); + + /* +- If eligible, place chunk on a fastbin so it can be found +- and used quickly in malloc. +- */ ++ If eligible, place chunk on a fastbin so it can be found ++ and used quickly in malloc. ++ */ + + if ((unsigned long)(size) <= (unsigned long)(av->max_fast) + +@@ -300,114 +300,114 @@ void free(void* mem) + bordering top into fastbins */ + && (chunk_at_offset(p, size) != av->top) + #endif +- ) { ++ ) { + +- set_fastchunks(av); +- fb = &(av->fastbins[fastbin_index(size)]); +- p->fd = *fb; +- *fb = p; ++ set_fastchunks(av); ++ fb = &(av->fastbins[fastbin_index(size)]); ++ p->fd = *fb; ++ *fb = p; + } + + /* +- Consolidate other non-mmapped chunks as they arrive. +- */ ++ Consolidate other non-mmapped chunks as they arrive. ++ */ + + else if (!chunk_is_mmapped(p)) { +- set_anychunks(av); ++ set_anychunks(av); ++ ++ nextchunk = chunk_at_offset(p, size); ++ nextsize = chunksize(nextchunk); ++ ++ /* consolidate backward */ ++ if (!prev_inuse(p)) { ++ prevsize = p->prev_size; ++ size += prevsize; ++ p = chunk_at_offset(p, -((long) prevsize)); ++ unlink(p, bck, fwd); ++ } ++ ++ if (nextchunk != av->top) { ++ /* get and clear inuse bit */ ++ nextinuse = inuse_bit_at_offset(nextchunk, nextsize); ++ set_head(nextchunk, nextsize); ++ ++ /* consolidate forward */ ++ if (!nextinuse) { ++ unlink(nextchunk, bck, fwd); ++ size += nextsize; ++ } ++ ++ /* ++ Place the chunk in unsorted chunk list. Chunks are ++ not placed into regular bins until after they have ++ been given one chance to be used in malloc. ++ */ ++ ++ bck = unsorted_chunks(av); ++ fwd = bck->fd; ++ p->bk = bck; ++ p->fd = fwd; ++ bck->fd = p; ++ fwd->bk = p; + +- nextchunk = chunk_at_offset(p, size); +- nextsize = chunksize(nextchunk); ++ set_head(p, size | PREV_INUSE); ++ set_foot(p, size); ++ ++ check_free_chunk(p); ++ } ++ ++ /* ++ If the chunk borders the current high end of memory, ++ consolidate into top ++ */ + +- /* consolidate backward */ +- if (!prev_inuse(p)) { +- prevsize = p->prev_size; +- size += prevsize; +- p = chunk_at_offset(p, -((long) prevsize)); +- unlink(p, bck, fwd); +- } +- +- if (nextchunk != av->top) { +- /* get and clear inuse bit */ +- nextinuse = inuse_bit_at_offset(nextchunk, nextsize); +- set_head(nextchunk, nextsize); +- +- /* consolidate forward */ +- if (!nextinuse) { +- unlink(nextchunk, bck, fwd); +- size += nextsize; +- } +- +- /* +- Place the chunk in unsorted chunk list. Chunks are +- not placed into regular bins until after they have +- been given one chance to be used in malloc. +- */ +- +- bck = unsorted_chunks(av); +- fwd = bck->fd; +- p->bk = bck; +- p->fd = fwd; +- bck->fd = p; +- fwd->bk = p; +- +- set_head(p, size | PREV_INUSE); +- set_foot(p, size); +- +- check_free_chunk(p); +- } +- +- /* +- If the chunk borders the current high end of memory, +- consolidate into top +- */ +- +- else { +- size += nextsize; +- set_head(p, size | PREV_INUSE); +- av->top = p; +- check_chunk(p); +- } +- +- /* +- If freeing a large space, consolidate possibly-surrounding +- chunks. Then, if the total unused topmost memory exceeds trim +- threshold, ask malloc_trim to reduce top. +- +- Unless max_fast is 0, we don't know if there are fastbins +- bordering top, so we cannot tell for sure whether threshold +- has been reached unless fastbins are consolidated. But we +- don't want to consolidate on each free. As a compromise, +- consolidation is performed if FASTBIN_CONSOLIDATION_THRESHOLD +- is reached. +- */ +- +- if ((unsigned long)(size) >= FASTBIN_CONSOLIDATION_THRESHOLD) { +- if (have_fastchunks(av)) +- __malloc_consolidate(av); +- +- if ((unsigned long)(chunksize(av->top)) >= +- (unsigned long)(av->trim_threshold)) +- __malloc_trim(av->top_pad, av); +- } ++ else { ++ size += nextsize; ++ set_head(p, size | PREV_INUSE); ++ av->top = p; ++ check_chunk(p); ++ } ++ ++ /* ++ If freeing a large space, consolidate possibly-surrounding ++ chunks. Then, if the total unused topmost memory exceeds trim ++ threshold, ask malloc_trim to reduce top. ++ ++ Unless max_fast is 0, we don't know if there are fastbins ++ bordering top, so we cannot tell for sure whether threshold ++ has been reached unless fastbins are consolidated. But we ++ don't want to consolidate on each free. As a compromise, ++ consolidation is performed if FASTBIN_CONSOLIDATION_THRESHOLD ++ is reached. ++ */ ++ ++ if ((unsigned long)(size) >= FASTBIN_CONSOLIDATION_THRESHOLD) { ++ if (have_fastchunks(av)) ++ __malloc_consolidate(av); ++ ++ if ((unsigned long)(chunksize(av->top)) >= ++ (unsigned long)(av->trim_threshold)) ++ __malloc_trim(av->top_pad, av); ++ } + + } + /* +- If the chunk was allocated via mmap, release via munmap() +- Note that if HAVE_MMAP is false but chunk_is_mmapped is +- true, then user must have overwritten memory. There's nothing +- we can do to catch this error unless DEBUG is set, in which case +- check_inuse_chunk (above) will have triggered error. +- */ ++ If the chunk was allocated via mmap, release via munmap() ++ Note that if HAVE_MMAP is false but chunk_is_mmapped is ++ true, then user must have overwritten memory. There's nothing ++ we can do to catch this error unless DEBUG is set, in which case ++ check_inuse_chunk (above) will have triggered error. ++ */ + + else { +- int ret; +- size_t offset = p->prev_size; +- av->n_mmaps--; +- av->mmapped_mem -= (size + offset); +- ret = munmap((char*)p - offset, size + offset); +- /* munmap returns non-zero on failure */ +- assert(ret == 0); ++ int ret; ++ size_t offset = p->prev_size; ++ av->n_mmaps--; ++ av->mmapped_mem -= (size + offset); ++ ret = munmap((char*)p - offset, size + offset); ++ /* munmap returns non-zero on failure */ ++ assert(ret == 0); + } +- UNLOCK; ++ __MALLOC_UNLOCK; + } + +diff --git a/libc/stdlib/malloc-standard/mallinfo.c b/libc/stdlib/malloc-standard/mallinfo.c +index 51ac423..1e0875c 100644 +--- a/libc/stdlib/malloc-standard/mallinfo.c ++++ b/libc/stdlib/malloc-standard/mallinfo.c +@@ -8,7 +8,7 @@ + VERSION 2.7.2 Sat Aug 17 09:07:30 2002 Doug Lea (dl at gee) + + Note: There may be an updated version of this malloc obtainable at +- ftp://gee.cs.oswego.edu/pub/misc/malloc.c ++ ftp://gee.cs.oswego.edu/pub/misc/malloc.c + Check before installing! + + Hacked up for uClibc by Erik Andersen <andersen@codepoet.org> +@@ -30,11 +30,11 @@ struct mallinfo mallinfo(void) + int nblocks; + int nfastblocks; + +- LOCK; ++ __MALLOC_LOCK; + av = get_malloc_state(); + /* Ensure initialization */ + if (av->top == 0) { +- __malloc_consolidate(av); ++ __malloc_consolidate(av); + } + + check_malloc_state(); +@@ -48,21 +48,21 @@ struct mallinfo mallinfo(void) + fastavail = 0; + + for (i = 0; i < NFASTBINS; ++i) { +- for (p = av->fastbins[i]; p != 0; p = p->fd) { +- ++nfastblocks; +- fastavail += chunksize(p); +- } ++ for (p = av->fastbins[i]; p != 0; p = p->fd) { ++ ++nfastblocks; ++ fastavail += chunksize(p); ++ } + } + + avail += fastavail; + + /* traverse regular bins */ + for (i = 1; i < NBINS; ++i) { +- b = bin_at(av, i); +- for (p = last(b); p != b; p = p->bk) { +- ++nblocks; +- avail += chunksize(p); +- } ++ b = bin_at(av, i); ++ for (p = last(b); p != b; p = p->bk) { ++ ++nblocks; ++ avail += chunksize(p); ++ } + } + + mi.smblks = nfastblocks; +@@ -75,7 +75,7 @@ struct mallinfo mallinfo(void) + mi.fsmblks = fastavail; + mi.keepcost = chunksize(av->top); + mi.usmblks = av->max_total_mem; +- UNLOCK; ++ __MALLOC_UNLOCK; + return mi; + } + +@@ -84,23 +84,40 @@ void malloc_stats(FILE *file) + struct mallinfo mi; + + if (file==NULL) { +- file = stderr; ++ file = stderr; + } + + mi = mallinfo(); +- fprintf(file, "total bytes allocated = %10u\n", (unsigned int)(mi.arena + mi.hblkhd)); +- fprintf(file, "total bytes in use bytes = %10u\n", (unsigned int)(mi.uordblks + mi.hblkhd)); +- fprintf(file, "total non-mmapped bytes allocated = %10d\n", mi.arena); +- fprintf(file, "number of mmapped regions = %10d\n", mi.hblks); +- fprintf(file, "total allocated mmap space = %10d\n", mi.hblkhd); +- fprintf(file, "total allocated sbrk space = %10d\n", mi.uordblks); ++ fprintf(file, ++ "total bytes allocated = %10u\n" ++ "total bytes in use bytes = %10u\n" ++ "total non-mmapped bytes allocated = %10d\n" ++ "number of mmapped regions = %10d\n" ++ "total allocated mmap space = %10d\n" ++ "total allocated sbrk space = %10d\n" + #if 0 +- fprintf(file, "number of free chunks = %10d\n", mi.ordblks); +- fprintf(file, "number of fastbin blocks = %10d\n", mi.smblks); +- fprintf(file, "space in freed fastbin blocks = %10d\n", mi.fsmblks); ++ "number of free chunks = %10d\n" ++ "number of fastbin blocks = %10d\n" ++ "space in freed fastbin blocks = %10d\n" + #endif +- fprintf(file, "maximum total allocated space = %10d\n", mi.usmblks); +- fprintf(file, "total free space = %10d\n", mi.fordblks); +- fprintf(file, "memory releasable via malloc_trim = %10d\n", mi.keepcost); ++ "maximum total allocated space = %10d\n" ++ "total free space = %10d\n" ++ "memory releasable via malloc_trim = %10d\n", ++ ++ (unsigned int)(mi.arena + mi.hblkhd), ++ (unsigned int)(mi.uordblks + mi.hblkhd), ++ mi.arena, ++ mi.hblks, ++ mi.hblkhd, ++ mi.uordblks, ++#if 0 ++ mi.ordblks, ++ mi.smblks, ++ mi.fsmblks, ++#endif ++ mi.usmblks, ++ mi.fordblks, ++ mi.keepcost ++ ); + } + +diff --git a/libc/stdlib/malloc-standard/malloc.c b/libc/stdlib/malloc-standard/malloc.c +index 7025e83..60494a0 100644 +--- a/libc/stdlib/malloc-standard/malloc.c ++++ b/libc/stdlib/malloc-standard/malloc.c +@@ -8,7 +8,7 @@ + VERSION 2.7.2 Sat Aug 17 09:07:30 2002 Doug Lea (dl at gee) + + Note: There may be an updated version of this malloc obtainable at +- ftp://gee.cs.oswego.edu/pub/misc/malloc.c ++ ftp://gee.cs.oswego.edu/pub/misc/malloc.c + Check before installing! + + Hacked up for uClibc by Erik Andersen <andersen@codepoet.org> +@@ -17,17 +17,14 @@ + #define _GNU_SOURCE + #include "malloc.h" + +- +-#ifdef __UCLIBC_HAS_THREADS__ +-pthread_mutex_t __malloc_lock = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP; +-#endif ++__UCLIBC_MUTEX_INIT(__malloc_lock, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP); + + /* +- There is exactly one instance of this struct in this malloc. +- If you are adapting this malloc in a way that does NOT use a static +- malloc_state, you MUST explicitly zero-fill it before using. This +- malloc relies on the property that malloc_state is initialized to +- all zeroes (as is true of C statics). ++ There is exactly one instance of this struct in this malloc. ++ If you are adapting this malloc in a way that does NOT use a static ++ malloc_state, you MUST explicitly zero-fill it before using. This ++ malloc relies on the property that malloc_state is initialized to ++ all zeroes (as is true of C statics). + */ + struct malloc_state __malloc_state; /* never directly referenced */ + +@@ -77,30 +74,30 @@ void __do_check_chunk(mchunkptr p) + + if (!chunk_is_mmapped(p)) { + +- /* Has legal address ... */ +- if (p != av->top) { +- if (contiguous(av)) { +- assert(((char*)p) >= min_address); +- assert(((char*)p + sz) <= ((char*)(av->top))); +- } +- } +- else { +- /* top size is always at least MINSIZE */ +- assert((unsigned long)(sz) >= MINSIZE); +- /* top predecessor always marked inuse */ +- assert(prev_inuse(p)); +- } ++ /* Has legal address ... */ ++ if (p != av->top) { ++ if (contiguous(av)) { ++ assert(((char*)p) >= min_address); ++ assert(((char*)p + sz) <= ((char*)(av->top))); ++ } ++ } ++ else { ++ /* top size is always at least MINSIZE */ ++ assert((unsigned long)(sz) >= MINSIZE); ++ /* top predecessor always marked inuse */ ++ assert(prev_inuse(p)); ++ } + + } + else { +- /* address is outside main heap */ +- if (contiguous(av) && av->top != initial_top(av)) { +- assert(((char*)p) < min_address || ((char*)p) > max_address); +- } +- /* chunk is page-aligned */ +- assert(((p->prev_size + sz) & (av->pagesize-1)) == 0); +- /* mem is aligned */ +- assert(aligned_OK(chunk2mem(p))); ++ /* address is outside main heap */ ++ if (contiguous(av) && av->top != initial_top(av)) { ++ assert(((char*)p) < min_address || ((char*)p) > max_address); ++ } ++ /* chunk is page-aligned */ ++ assert(((p->prev_size + sz) & (av->pagesize-1)) == 0); ++ /* mem is aligned */ ++ assert(aligned_OK(chunk2mem(p))); + } + } + +@@ -121,21 +118,21 @@ void __do_check_free_chunk(mchunkptr p) + + /* Unless a special marker, must have OK fields */ + if ((unsigned long)(sz) >= MINSIZE) +- { +- assert((sz & MALLOC_ALIGN_MASK) == 0); +- assert(aligned_OK(chunk2mem(p))); +- /* ... matching footer field */ +- assert(next->prev_size == sz); +- /* ... and is fully consolidated */ +- assert(prev_inuse(p)); +- assert (next == av->top || inuse(next)); +- +- /* ... and has minimally sane links */ +- assert(p->fd->bk == p); +- assert(p->bk->fd == p); +- } ++ { ++ assert((sz & MALLOC_ALIGN_MASK) == 0); ++ assert(aligned_OK(chunk2mem(p))); ++ /* ... matching footer field */ ++ assert(next->prev_size == sz); ++ /* ... and is fully consolidated */ ++ assert(prev_inuse(p)); ++ assert (next == av->top || inuse(next)); ++ ++ /* ... and has minimally sane links */ ++ assert(p->fd->bk == p); ++ assert(p->bk->fd == p); ++ } + else /* markers are always of size (sizeof(size_t)) */ +- assert(sz == (sizeof(size_t))); ++ assert(sz == (sizeof(size_t))); + } + + /* Properties of inuse chunks */ +@@ -146,7 +143,7 @@ void __do_check_inuse_chunk(mchunkptr p) + __do_check_chunk(p); + + if (chunk_is_mmapped(p)) +- return; /* mmapped chunks have no next/prev */ ++ return; /* mmapped chunks have no next/prev */ + + /* Check whether it claims to be in use ... */ + assert(inuse(p)); +@@ -156,20 +153,20 @@ void __do_check_inuse_chunk(mchunkptr p) + /* ... and is surrounded by OK chunks. + Since more things can be checked with free chunks than inuse ones, + if an inuse chunk borders them and debug is on, it's worth doing them. +- */ ++ */ + if (!prev_inuse(p)) { +- /* Note that we cannot even look at prev unless it is not inuse */ +- mchunkptr prv = prev_chunk(p); +- assert(next_chunk(prv) == p); +- __do_check_free_chunk(prv); ++ /* Note that we cannot even look at prev unless it is not inuse */ ++ mchunkptr prv = prev_chunk(p); ++ assert(next_chunk(prv) == p); ++ __do_check_free_chunk(prv); + } + + if (next == av->top) { +- assert(prev_inuse(next)); +- assert(chunksize(next) >= MINSIZE); ++ assert(prev_inuse(next)); ++ assert(chunksize(next) >= MINSIZE); + } + else if (!inuse(next)) +- __do_check_free_chunk(next); ++ __do_check_free_chunk(next); + } + + /* Properties of chunks recycled from fastbins */ +@@ -198,14 +195,14 @@ void __do_check_malloced_chunk(mchunkptr + __do_check_remalloced_chunk(p, s); + + /* +- ... plus, must obey implementation invariant that prev_inuse is +- always true of any allocated chunk; i.e., that each allocated +- chunk borders either a previously allocated and still in-use +- chunk, or the base of its memory arena. This is ensured +- by making all allocations from the the `lowest' part of any found +- chunk. This does not necessarily hold however for chunks +- recycled via fastbins. +- */ ++ ... plus, must obey implementation invariant that prev_inuse is ++ always true of any allocated chunk; i.e., that each allocated ++ chunk borders either a previously allocated and still in-use ++ chunk, or the base of its memory arena. This is ensured ++ by making all allocations from the the `lowest' part of any found ++ chunk. This does not necessarily hold however for chunks ++ recycled via fastbins. ++ */ + + assert(prev_inuse(p)); + } +@@ -243,7 +240,7 @@ void __do_check_malloc_state(void) + + /* cannot run remaining checks until fully initialized */ + if (av->top == 0 || av->top == initial_top(av)) +- return; ++ return; + + /* pagesize is a power of 2 */ + assert((av->pagesize & (av->pagesize-1)) == 0); +@@ -256,64 +253,64 @@ void __do_check_malloc_state(void) + max_fast_bin = fastbin_index(av->max_fast); + + for (i = 0; i < NFASTBINS; ++i) { +- p = av->fastbins[i]; ++ p = av->fastbins[i]; + +- /* all bins past max_fast are empty */ +- if (i > max_fast_bin) +- assert(p == 0); +- +- while (p != 0) { +- /* each chunk claims to be inuse */ +- __do_check_inuse_chunk(p); +- total += chunksize(p); +- /* chunk belongs in this bin */ +- assert(fastbin_index(chunksize(p)) == i); +- p = p->fd; +- } ++ /* all bins past max_fast are empty */ ++ if (i > max_fast_bin) ++ assert(p == 0); ++ ++ while (p != 0) { ++ /* each chunk claims to be inuse */ ++ __do_check_inuse_chunk(p); ++ total += chunksize(p); ++ /* chunk belongs in this bin */ ++ assert(fastbin_index(chunksize(p)) == i); ++ p = p->fd; ++ } + } + + if (total != 0) +- assert(have_fastchunks(av)); ++ assert(have_fastchunks(av)); + else if (!have_fastchunks(av)) +- assert(total == 0); ++ assert(total == 0); + + /* check normal bins */ + for (i = 1; i < NBINS; ++i) { +- b = bin_at(av,i); ++ b = bin_at(av,i); + +- /* binmap is accurate (except for bin 1 == unsorted_chunks) */ +- if (i >= 2) { +- binbit = get_binmap(av,i); +- empty = last(b) == b; +- if (!binbit) +- assert(empty); +- else if (!empty) +- assert(binbit); +- } +- +- for (p = last(b); p != b; p = p->bk) { +- /* each chunk claims to be free */ +- __do_check_free_chunk(p); +- size = chunksize(p); +- total += size; +- if (i >= 2) { +- /* chunk belongs in bin */ +- idx = bin_index(size); +- assert(idx == i); +- /* lists are sorted */ +- if ((unsigned long) size >= (unsigned long)(FIRST_SORTED_BIN_SIZE)) { +- assert(p->bk == b || +- (unsigned long)chunksize(p->bk) >= +- (unsigned long)chunksize(p)); +- } +- } +- /* chunk is followed by a legal chain of inuse chunks */ +- for (q = next_chunk(p); +- (q != av->top && inuse(q) && +- (unsigned long)(chunksize(q)) >= MINSIZE); +- q = next_chunk(q)) +- __do_check_inuse_chunk(q); +- } ++ /* binmap is accurate (except for bin 1 == unsorted_chunks) */ ++ if (i >= 2) { ++ binbit = get_binmap(av,i); ++ empty = last(b) == b; ++ if (!binbit) ++ assert(empty); ++ else if (!empty) ++ assert(binbit); ++ } ++ ++ for (p = last(b); p != b; p = p->bk) { ++ /* each chunk claims to be free */ ++ __do_check_free_chunk(p); ++ size = chunksize(p); ++ total += size; ++ if (i >= 2) { ++ /* chunk belongs in bin */ ++ idx = bin_index(size); ++ assert(idx == i); ++ /* lists are sorted */ ++ if ((unsigned long) size >= (unsigned long)(FIRST_SORTED_BIN_SIZE)) { ++ assert(p->bk == b || ++ (unsigned long)chunksize(p->bk) >= ++ (unsigned long)chunksize(p)); ++ } ++ } ++ /* chunk is followed by a legal chain of inuse chunks */ ++ for (q = next_chunk(p); ++ (q != av->top && inuse(q) && ++ (unsigned long)(chunksize(q)) >= MINSIZE); ++ q = next_chunk(q)) ++ __do_check_inuse_chunk(q); ++ } + } + + /* top chunk is OK */ +@@ -326,13 +323,13 @@ void __do_check_malloc_state(void) + assert(av->n_mmaps <= av->max_n_mmaps); + + assert((unsigned long)(av->sbrked_mem) <= +- (unsigned long)(av->max_sbrked_mem)); ++ (unsigned long)(av->max_sbrked_mem)); + + assert((unsigned long)(av->mmapped_mem) <= +- (unsigned long)(av->max_mmapped_mem)); ++ (unsigned long)(av->max_mmapped_mem)); + + assert((unsigned long)(av->max_total_mem) >= +- (unsigned long)(av->mmapped_mem) + (unsigned long)(av->sbrked_mem)); ++ (unsigned long)(av->mmapped_mem) + (unsigned long)(av->sbrked_mem)); + } + #endif + +@@ -370,84 +367,84 @@ static void* __malloc_alloc(size_t nb, m + size_t pagemask = av->pagesize - 1; + + /* +- If there is space available in fastbins, consolidate and retry +- malloc from scratch rather than getting memory from system. This +- can occur only if nb is in smallbin range so we didn't consolidate +- upon entry to malloc. It is much easier to handle this case here +- than in malloc proper. +- */ ++ If there is space available in fastbins, consolidate and retry ++ malloc from scratch rather than getting memory from system. This ++ can occur only if nb is in smallbin range so we didn't consolidate ++ upon entry to malloc. It is much easier to handle this case here ++ than in malloc proper. ++ */ + + if (have_fastchunks(av)) { +- assert(in_smallbin_range(nb)); +- __malloc_consolidate(av); +- return malloc(nb - MALLOC_ALIGN_MASK); ++ assert(in_smallbin_range(nb)); ++ __malloc_consolidate(av); ++ return malloc(nb - MALLOC_ALIGN_MASK); + } + + + /* +- If have mmap, and the request size meets the mmap threshold, and +- the system supports mmap, and there are few enough currently +- allocated mmapped regions, try to directly map this request +- rather than expanding top. +- */ ++ If have mmap, and the request size meets the mmap threshold, and ++ the system supports mmap, and there are few enough currently ++ allocated mmapped regions, try to directly map this request ++ rather than expanding top. ++ */ + + if ((unsigned long)(nb) >= (unsigned long)(av->mmap_threshold) && + (av->n_mmaps < av->n_mmaps_max)) { + +- char* mm; /* return value from mmap call*/ +- +- /* +- Round up size to nearest page. For mmapped chunks, the overhead +- is one (sizeof(size_t)) unit larger than for normal chunks, because there +- is no following chunk whose prev_size field could be used. +- */ +- size = (nb + (sizeof(size_t)) + MALLOC_ALIGN_MASK + pagemask) & ~pagemask; +- +- /* Don't try if size wraps around 0 */ +- if ((unsigned long)(size) > (unsigned long)(nb)) { +- +- mm = (char*)(MMAP(0, size, PROT_READ|PROT_WRITE)); +- +- if (mm != (char*)(MORECORE_FAILURE)) { ++ char* mm; /* return value from mmap call*/ + + /* +- The offset to the start of the mmapped region is stored +- in the prev_size field of the chunk. This allows us to adjust +- returned start address to meet alignment requirements here +- and in memalign(), and still be able to compute proper +- address argument for later munmap in free() and realloc(). +- */ +- +- front_misalign = (size_t)chunk2mem(mm) & MALLOC_ALIGN_MASK; +- if (front_misalign > 0) { +- correction = MALLOC_ALIGNMENT - front_misalign; +- p = (mchunkptr)(mm + correction); +- p->prev_size = correction; +- set_head(p, (size - correction) |IS_MMAPPED); +- } +- else { +- p = (mchunkptr)mm; +- p->prev_size = 0; +- set_head(p, size|IS_MMAPPED); +- } ++ Round up size to nearest page. For mmapped chunks, the overhead ++ is one (sizeof(size_t)) unit larger than for normal chunks, because there ++ is no following chunk whose prev_size field could be used. ++ */ ++ size = (nb + (sizeof(size_t)) + MALLOC_ALIGN_MASK + pagemask) & ~pagemask; ++ ++ /* Don't try if size wraps around 0 */ ++ if ((unsigned long)(size) > (unsigned long)(nb)) { ++ ++ mm = (char*)(MMAP(0, size, PROT_READ|PROT_WRITE)); ++ ++ if (mm != (char*)(MORECORE_FAILURE)) { ++ ++ /* ++ The offset to the start of the mmapped region is stored ++ in the prev_size field of the chunk. This allows us to adjust ++ returned start address to meet alignment requirements here ++ and in memalign(), and still be able to compute proper ++ address argument for later munmap in free() and realloc(). ++ */ ++ ++ front_misalign = (size_t)chunk2mem(mm) & MALLOC_ALIGN_MASK; ++ if (front_misalign > 0) { ++ correction = MALLOC_ALIGNMENT - front_misalign; ++ p = (mchunkptr)(mm + correction); ++ p->prev_size = correction; ++ set_head(p, (size - correction) |IS_MMAPPED); ++ } ++ else { ++ p = (mchunkptr)mm; ++ p->prev_size = 0; ++ set_head(p, size|IS_MMAPPED); ++ } ++ ++ /* update statistics */ ++ ++ if (++av->n_mmaps > av->max_n_mmaps) ++ av->max_n_mmaps = av->n_mmaps; ++ ++ sum = av->mmapped_mem += size; ++ if (sum > (unsigned long)(av->max_mmapped_mem)) ++ av->max_mmapped_mem = sum; ++ sum += av->sbrked_mem; ++ if (sum > (unsigned long)(av->max_total_mem)) ++ av->max_total_mem = sum; + +- /* update statistics */ ++ check_chunk(p); + +- if (++av->n_mmaps > av->max_n_mmaps) +- av->max_n_mmaps = av->n_mmaps; +- +- sum = av->mmapped_mem += size; +- if (sum > (unsigned long)(av->max_mmapped_mem)) +- av->max_mmapped_mem = sum; +- sum += av->sbrked_mem; +- if (sum > (unsigned long)(av->max_total_mem)) +- av->max_total_mem = sum; +- +- check_chunk(p); +- +- return chunk2mem(p); +- } +- } ++ return chunk2mem(p); ++ } ++ } + } + + /* Record incoming configuration of top */ +@@ -462,8 +459,8 @@ static void* __malloc_alloc(size_t nb, m + * be at least MINSIZE and to have prev_inuse set. */ + + assert((old_top == initial_top(av) && old_size == 0) || +- ((unsigned long) (old_size) >= MINSIZE && +- prev_inuse(old_top))); ++ ((unsigned long) (old_size) >= MINSIZE && ++ prev_inuse(old_top))); + + /* Precondition: not enough current space to satisfy nb request */ + assert((unsigned long)(old_size) < (unsigned long)(nb + MINSIZE)); +@@ -477,272 +474,272 @@ static void* __malloc_alloc(size_t nb, m + size = nb + av->top_pad + MINSIZE; + + /* +- If contiguous, we can subtract out existing space that we hope to +- combine with new space. We add it back later only if +- we don't actually get contiguous space. +- */ ++ If contiguous, we can subtract out existing space that we hope to ++ combine with new space. We add it back later only if ++ we don't actually get contiguous space. ++ */ + + if (contiguous(av)) +- size -= old_size; ++ size -= old_size; + + /* +- Round to a multiple of page size. +- If MORECORE is not contiguous, this ensures that we only call it +- with whole-page arguments. And if MORECORE is contiguous and +- this is not first time through, this preserves page-alignment of +- previous calls. Otherwise, we correct to page-align below. +- */ ++ Round to a multiple of page size. ++ If MORECORE is not contiguous, this ensures that we only call it ++ with whole-page arguments. And if MORECORE is contiguous and ++ this is not first time through, this preserves page-alignment of ++ previous calls. Otherwise, we correct to page-align below. ++ */ + + size = (size + pagemask) & ~pagemask; + + /* +- Don't try to call MORECORE if argument is so big as to appear +- negative. Note that since mmap takes size_t arg, it may succeed +- below even if we cannot call MORECORE. +- */ ++ Don't try to call MORECORE if argument is so big as to appear ++ negative. Note that since mmap takes size_t arg, it may succeed ++ below even if we cannot call MORECORE. ++ */ + + if (size > 0) +- brk = (char*)(MORECORE(size)); ++ brk = (char*)(MORECORE(size)); + + /* +- If have mmap, try using it as a backup when MORECORE fails or +- cannot be used. This is worth doing on systems that have "holes" in +- address space, so sbrk cannot extend to give contiguous space, but +- space is available elsewhere. Note that we ignore mmap max count +- and threshold limits, since the space will not be used as a +- segregated mmap region. +- */ ++ If have mmap, try using it as a backup when MORECORE fails or ++ cannot be used. This is worth doing on systems that have "holes" in ++ address space, so sbrk cannot extend to give contiguous space, but ++ space is available elsewhere. Note that we ignore mmap max count ++ and threshold limits, since the space will not be used as a ++ segregated mmap region. ++ */ + + if (brk == (char*)(MORECORE_FAILURE)) { + +- /* Cannot merge with old top, so add its size back in */ +- if (contiguous(av)) +- size = (size + old_size + pagemask) & ~pagemask; +- +- /* If we are relying on mmap as backup, then use larger units */ +- if ((unsigned long)(size) < (unsigned long)(MMAP_AS_MORECORE_SIZE)) +- size = MMAP_AS_MORECORE_SIZE; +- +- /* Don't try if size wraps around 0 */ +- if ((unsigned long)(size) > (unsigned long)(nb)) { +- +- brk = (char*)(MMAP(0, size, PROT_READ|PROT_WRITE)); +- +- if (brk != (char*)(MORECORE_FAILURE)) { +- +- /* We do not need, and cannot use, another sbrk call to find end */ +- snd_brk = brk + size; +- +- /* Record that we no longer have a contiguous sbrk region. +- After the first time mmap is used as backup, we do not +- ever rely on contiguous space since this could incorrectly +- bridge regions. +- */ +- set_noncontiguous(av); +- } +- } ++ /* Cannot merge with old top, so add its size back in */ ++ if (contiguous(av)) ++ size = (size + old_size + pagemask) & ~pagemask; ++ ++ /* If we are relying on mmap as backup, then use larger units */ ++ if ((unsigned long)(size) < (unsigned long)(MMAP_AS_MORECORE_SIZE)) ++ size = MMAP_AS_MORECORE_SIZE; ++ ++ /* Don't try if size wraps around 0 */ ++ if ((unsigned long)(size) > (unsigned long)(nb)) { ++ ++ brk = (char*)(MMAP(0, size, PROT_READ|PROT_WRITE)); ++ ++ if (brk != (char*)(MORECORE_FAILURE)) { ++ ++ /* We do not need, and cannot use, another sbrk call to find end */ ++ snd_brk = brk + size; ++ ++ /* Record that we no longer have a contiguous sbrk region. ++ After the first time mmap is used as backup, we do not ++ ever rely on contiguous space since this could incorrectly ++ bridge regions. ++ */ ++ set_noncontiguous(av); ++ } ++ } + } + + if (brk != (char*)(MORECORE_FAILURE)) { +- av->sbrked_mem += size; ++ av->sbrked_mem += size; + +- /* +- If MORECORE extends previous space, we can likewise extend top size. +- */ +- +- if (brk == old_end && snd_brk == (char*)(MORECORE_FAILURE)) { +- set_head(old_top, (size + old_size) | PREV_INUSE); +- } +- +- /* +- Otherwise, make adjustments: +- +- * If the first time through or noncontiguous, we need to call sbrk +- just to find out where the end of memory lies. +- +- * We need to ensure that all returned chunks from malloc will meet +- MALLOC_ALIGNMENT +- +- * If there was an intervening foreign sbrk, we need to adjust sbrk +- request size to account for fact that we will not be able to +- combine new space with existing space in old_top. +- +- * Almost all systems internally allocate whole pages at a time, in +- which case we might as well use the whole last page of request. +- So we allocate enough more memory to hit a page boundary now, +- which in turn causes future contiguous calls to page-align. +- */ +- +- else { +- front_misalign = 0; +- end_misalign = 0; +- correction = 0; +- aligned_brk = brk; +- +- /* +- If MORECORE returns an address lower than we have seen before, +- we know it isn't really contiguous. This and some subsequent +- checks help cope with non-conforming MORECORE functions and +- the presence of "foreign" calls to MORECORE from outside of +- malloc or by other threads. We cannot guarantee to detect +- these in all cases, but cope with the ones we do detect. +- */ +- if (contiguous(av) && old_size != 0 && brk < old_end) { +- set_noncontiguous(av); +- } +- +- /* handle contiguous cases */ +- if (contiguous(av)) { +- +- /* We can tolerate forward non-contiguities here (usually due +- to foreign calls) but treat them as part of our space for +- stats reporting. */ +- if (old_size != 0) +- av->sbrked_mem += brk - old_end; +- +- /* Guarantee alignment of first new chunk made from this space */ +- +- front_misalign = (size_t)chunk2mem(brk) & MALLOC_ALIGN_MASK; +- if (front_misalign > 0) { +- +- /* +- Skip over some bytes to arrive at an aligned position. +- We don't need to specially mark these wasted front bytes. +- They will never be accessed anyway because +- prev_inuse of av->top (and any chunk created from its start) +- is always true after initialization. +- */ ++ /* ++ If MORECORE extends previous space, we can likewise extend top size. ++ */ + +- correction = MALLOC_ALIGNMENT - front_misalign; +- aligned_brk += correction; ++ if (brk == old_end && snd_brk == (char*)(MORECORE_FAILURE)) { ++ set_head(old_top, (size + old_size) | PREV_INUSE); + } + + /* +- If this isn't adjacent to existing space, then we will not +- be able to merge with old_top space, so must add to 2nd request. +- */ +- +- correction += old_size; +- +- /* Extend the end address to hit a page boundary */ +- end_misalign = (size_t)(brk + size + correction); +- correction += ((end_misalign + pagemask) & ~pagemask) - end_misalign; +- +- assert(correction >= 0); +- snd_brk = (char*)(MORECORE(correction)); +- +- if (snd_brk == (char*)(MORECORE_FAILURE)) { +- /* +- If can't allocate correction, try to at least find out current +- brk. It might be enough to proceed without failing. +- */ +- correction = 0; +- snd_brk = (char*)(MORECORE(0)); +- } +- else if (snd_brk < brk) { +- /* +- If the second call gives noncontiguous space even though +- it says it won't, the only course of action is to ignore +- results of second call, and conservatively estimate where +- the first call left us. Also set noncontiguous, so this +- won't happen again, leaving at most one hole. +- +- Note that this check is intrinsically incomplete. Because +- MORECORE is allowed to give more space than we ask for, +- there is no reliable way to detect a noncontiguity +- producing a forward gap for the second call. +- */ +- snd_brk = brk + size; +- correction = 0; +- set_noncontiguous(av); +- } +- +- } +- +- /* handle non-contiguous cases */ +- else { +- /* MORECORE/mmap must correctly align */ +- assert(aligned_OK(chunk2mem(brk))); +- +- /* Find out current end of memory */ +- if (snd_brk == (char*)(MORECORE_FAILURE)) { +- snd_brk = (char*)(MORECORE(0)); +- av->sbrked_mem += snd_brk - brk - size; +- } +- } +- +- /* Adjust top based on results of second sbrk */ +- if (snd_brk != (char*)(MORECORE_FAILURE)) { +- av->top = (mchunkptr)aligned_brk; +- set_head(av->top, (snd_brk - aligned_brk + correction) | PREV_INUSE); +- av->sbrked_mem += correction; ++ Otherwise, make adjustments: + +- /* +- If not the first time through, we either have a +- gap due to foreign sbrk or a non-contiguous region. Insert a +- double fencepost at old_top to prevent consolidation with space +- we don't own. These fenceposts are artificial chunks that are +- marked as inuse and are in any case too small to use. We need +- two to make sizes and alignments work out. +- */ +- +- if (old_size != 0) { +- /* Shrink old_top to insert fenceposts, keeping size a +- multiple of MALLOC_ALIGNMENT. We know there is at least +- enough space in old_top to do this. +- */ +- old_size = (old_size - 3*(sizeof(size_t))) & ~MALLOC_ALIGN_MASK; +- set_head(old_top, old_size | PREV_INUSE); +- +- /* +- Note that the following assignments completely overwrite +- old_top when old_size was previously MINSIZE. This is +- intentional. We need the fencepost, even if old_top otherwise gets +- lost. +- */ +- chunk_at_offset(old_top, old_size )->size = +- (sizeof(size_t))|PREV_INUSE; +- +- chunk_at_offset(old_top, old_size + (sizeof(size_t)))->size = +- (sizeof(size_t))|PREV_INUSE; +- +- /* If possible, release the rest, suppressing trimming. */ +- if (old_size >= MINSIZE) { +- size_t tt = av->trim_threshold; +- av->trim_threshold = (size_t)(-1); +- free(chunk2mem(old_top)); +- av->trim_threshold = tt; +- } +- } +- } +- } +- +- /* Update statistics */ +- sum = av->sbrked_mem; +- if (sum > (unsigned long)(av->max_sbrked_mem)) +- av->max_sbrked_mem = sum; +- +- sum += av->mmapped_mem; +- if (sum > (unsigned long)(av->max_total_mem)) +- av->max_total_mem = sum; +- +- check_malloc_state(); +- +- /* finally, do the allocation */ +- +- p = av->top; +- size = chunksize(p); +- +- /* check that one of the above allocation paths succeeded */ +- if ((unsigned long)(size) >= (unsigned long)(nb + MINSIZE)) { +- remainder_size = size - nb; +- remainder = chunk_at_offset(p, nb); +- av->top = remainder; +- set_head(p, nb | PREV_INUSE); +- set_head(remainder, remainder_size | PREV_INUSE); +- check_malloced_chunk(p, nb); +- return chunk2mem(p); +- } ++ * If the first time through or noncontiguous, we need to call sbrk ++ just to find out where the end of memory lies. ++ ++ * We need to ensure that all returned chunks from malloc will meet ++ MALLOC_ALIGNMENT ++ ++ * If there was an intervening foreign sbrk, we need to adjust sbrk ++ request size to account for fact that we will not be able to ++ combine new space with existing space in old_top. ++ ++ * Almost all systems internally allocate whole pages at a time, in ++ which case we might as well use the whole last page of request. ++ So we allocate enough more memory to hit a page boundary now, ++ which in turn causes future contiguous calls to page-align. ++ */ ++ ++ else { ++ front_misalign = 0; ++ end_misalign = 0; ++ correction = 0; ++ aligned_brk = brk; ++ ++ /* ++ If MORECORE returns an address lower than we have seen before, ++ we know it isn't really contiguous. This and some subsequent ++ checks help cope with non-conforming MORECORE functions and ++ the presence of "foreign" calls to MORECORE from outside of ++ malloc or by other threads. We cannot guarantee to detect ++ these in all cases, but cope with the ones we do detect. ++ */ ++ if (contiguous(av) && old_size != 0 && brk < old_end) { ++ set_noncontiguous(av); ++ } ++ ++ /* handle contiguous cases */ ++ if (contiguous(av)) { ++ ++ /* We can tolerate forward non-contiguities here (usually due ++ to foreign calls) but treat them as part of our space for ++ stats reporting. */ ++ if (old_size != 0) ++ av->sbrked_mem += brk - old_end; ++ ++ /* Guarantee alignment of first new chunk made from this space */ ++ ++ front_misalign = (size_t)chunk2mem(brk) & MALLOC_ALIGN_MASK; ++ if (front_misalign > 0) { ++ ++ /* ++ Skip over some bytes to arrive at an aligned position. ++ We don't need to specially mark these wasted front bytes. ++ They will never be accessed anyway because ++ prev_inuse of av->top (and any chunk created from its start) ++ is always true after initialization. ++ */ ++ ++ correction = MALLOC_ALIGNMENT - front_misalign; ++ aligned_brk += correction; ++ } ++ ++ /* ++ If this isn't adjacent to existing space, then we will not ++ be able to merge with old_top space, so must add to 2nd request. ++ */ ++ ++ correction += old_size; ++ ++ /* Extend the end address to hit a page boundary */ ++ end_misalign = (size_t)(brk + size + correction); ++ correction += ((end_misalign + pagemask) & ~pagemask) - end_misalign; ++ ++ assert(correction >= 0); ++ snd_brk = (char*)(MORECORE(correction)); ++ ++ if (snd_brk == (char*)(MORECORE_FAILURE)) { ++ /* ++ If can't allocate correction, try to at least find out current ++ brk. It might be enough to proceed without failing. ++ */ ++ correction = 0; ++ snd_brk = (char*)(MORECORE(0)); ++ } ++ else if (snd_brk < brk) { ++ /* ++ If the second call gives noncontiguous space even though ++ it says it won't, the only course of action is to ignore ++ results of second call, and conservatively estimate where ++ the first call left us. Also set noncontiguous, so this ++ won't happen again, leaving at most one hole. ++ ++ Note that this check is intrinsically incomplete. Because ++ MORECORE is allowed to give more space than we ask for, ++ there is no reliable way to detect a noncontiguity ++ producing a forward gap for the second call. ++ */ ++ snd_brk = brk + size; ++ correction = 0; ++ set_noncontiguous(av); ++ } ++ ++ } ++ ++ /* handle non-contiguous cases */ ++ else { ++ /* MORECORE/mmap must correctly align */ ++ assert(aligned_OK(chunk2mem(brk))); ++ ++ /* Find out current end of memory */ ++ if (snd_brk == (char*)(MORECORE_FAILURE)) { ++ snd_brk = (char*)(MORECORE(0)); ++ av->sbrked_mem += snd_brk - brk - size; ++ } ++ } ++ ++ /* Adjust top based on results of second sbrk */ ++ if (snd_brk != (char*)(MORECORE_FAILURE)) { ++ av->top = (mchunkptr)aligned_brk; ++ set_head(av->top, (snd_brk - aligned_brk + correction) | PREV_INUSE); ++ av->sbrked_mem += correction; ++ ++ /* ++ If not the first time through, we either have a ++ gap due to foreign sbrk or a non-contiguous region. Insert a ++ double fencepost at old_top to prevent consolidation with space ++ we don't own. These fenceposts are artificial chunks that are ++ marked as inuse and are in any case too small to use. We need ++ two to make sizes and alignments work out. ++ */ ++ ++ if (old_size != 0) { ++ /* Shrink old_top to insert fenceposts, keeping size a ++ multiple of MALLOC_ALIGNMENT. We know there is at least ++ enough space in old_top to do this. ++ */ ++ old_size = (old_size - 3*(sizeof(size_t))) & ~MALLOC_ALIGN_MASK; ++ set_head(old_top, old_size | PREV_INUSE); ++ ++ /* ++ Note that the following assignments completely overwrite ++ old_top when old_size was previously MINSIZE. This is ++ intentional. We need the fencepost, even if old_top otherwise gets ++ lost. ++ */ ++ chunk_at_offset(old_top, old_size )->size = ++ (sizeof(size_t))|PREV_INUSE; ++ ++ chunk_at_offset(old_top, old_size + (sizeof(size_t)))->size = ++ (sizeof(size_t))|PREV_INUSE; ++ ++ /* If possible, release the rest, suppressing trimming. */ ++ if (old_size >= MINSIZE) { ++ size_t tt = av->trim_threshold; ++ av->trim_threshold = (size_t)(-1); ++ free(chunk2mem(old_top)); ++ av->trim_threshold = tt; ++ } ++ } ++ } ++ } ++ ++ /* Update statistics */ ++ sum = av->sbrked_mem; ++ if (sum > (unsigned long)(av->max_sbrked_mem)) ++ av->max_sbrked_mem = sum; ++ ++ sum += av->mmapped_mem; ++ if (sum > (unsigned long)(av->max_total_mem)) ++ av->max_total_mem = sum; ++ ++ check_malloc_state(); ++ ++ /* finally, do the allocation */ ++ ++ p = av->top; ++ size = chunksize(p); ++ ++ /* check that one of the above allocation paths succeeded */ ++ if ((unsigned long)(size) >= (unsigned long)(nb + MINSIZE)) { ++ remainder_size = size - nb; ++ remainder = chunk_at_offset(p, nb); ++ av->top = remainder; ++ set_head(p, nb | PREV_INUSE); ++ set_head(remainder, remainder_size | PREV_INUSE); ++ check_malloced_chunk(p, nb); ++ return chunk2mem(p); ++ } + + } + +@@ -767,25 +764,25 @@ static int __malloc_largebin_index(unsig + #if defined(__GNUC__) && defined(i386) + + __asm__("bsrl %1,%0\n\t" +- : "=r" (m) +- : "g" (x)); ++ : "=r" (m) ++ : "g" (x)); + + #else + { +- /* +- Based on branch-free nlz algorithm in chapter 5 of Henry +- S. Warren Jr's book "Hacker's Delight". +- */ +- +- unsigned int n = ((x - 0x100) >> 16) & 8; +- x <<= n; +- m = ((x - 0x1000) >> 16) & 4; +- n += m; +- x <<= m; +- m = ((x - 0x4000) >> 16) & 2; +- n += m; +- x = (x << m) >> 14; +- m = 13 - n + (x & ~(x>>1)); ++ /* ++ Based on branch-free nlz algorithm in chapter 5 of Henry ++ S. Warren Jr's book "Hacker's Delight". ++ */ ++ ++ unsigned int n = ((x - 0x100) >> 16) & 8; ++ x <<= n; ++ m = ((x - 0x1000) >> 16) & 4; ++ n += m; ++ x <<= m; ++ m = ((x - 0x4000) >> 16) & 2; ++ n += m; ++ x = (x << m) >> 14; ++ m = 13 - n + (x & ~(x>>1)); + } + #endif + +@@ -826,69 +823,70 @@ void* malloc(size_t bytes) + mchunkptr fwd; /* misc temp for linking */ + mchunkptr bck; /* misc temp for linking */ + void * sysmem; ++ void * retval; + + #if !defined(__MALLOC_GLIBC_COMPAT__) + if (!bytes) return NULL; + #endif + +- LOCK; ++ __MALLOC_LOCK; + av = get_malloc_state(); + /* +- Convert request size to internal form by adding (sizeof(size_t)) bytes +- overhead plus possibly more to obtain necessary alignment and/or +- to obtain a size of at least MINSIZE, the smallest allocatable +- size. Also, checked_request2size traps (returning 0) request sizes +- that are so large that they wrap around zero when padded and +- aligned. +- */ ++ Convert request size to internal form by adding (sizeof(size_t)) bytes ++ overhead plus possibly more to obtain necessary alignment and/or ++ to obtain a size of at least MINSIZE, the smallest allocatable ++ size. Also, checked_request2size traps (returning 0) request sizes ++ that are so large that they wrap around zero when padded and ++ aligned. ++ */ + + checked_request2size(bytes, nb); + + /* +- Bypass search if no frees yet +- */ ++ Bypass search if no frees yet ++ */ + if (!have_anychunks(av)) { +- if (av->max_fast == 0) /* initialization check */ +- __malloc_consolidate(av); +- goto use_top; ++ if (av->max_fast == 0) /* initialization check */ ++ __malloc_consolidate(av); ++ goto use_top; + } + + /* +- If the size qualifies as a fastbin, first check corresponding bin. +- */ ++ If the size qualifies as a fastbin, first check corresponding bin. ++ */ + + if ((unsigned long)(nb) <= (unsigned long)(av->max_fast)) { +- fb = &(av->fastbins[(fastbin_index(nb))]); +- if ( (victim = *fb) != 0) { +- *fb = victim->fd; +- check_remalloced_chunk(victim, nb); +- UNLOCK; +- return chunk2mem(victim); +- } ++ fb = &(av->fastbins[(fastbin_index(nb))]); ++ if ( (victim = *fb) != 0) { ++ *fb = victim->fd; ++ check_remalloced_chunk(victim, nb); ++ retval = chunk2mem(victim); ++ goto DONE; ++ } + } + + /* +- If a small request, check regular bin. Since these "smallbins" +- hold one size each, no searching within bins is necessary. +- (For a large request, we need to wait until unsorted chunks are +- processed to find best fit. But for small ones, fits are exact +- anyway, so we can check now, which is faster.) +- */ ++ If a small request, check regular bin. Since these "smallbins" ++ hold one size each, no searching within bins is necessary. ++ (For a large request, we need to wait until unsorted chunks are ++ processed to find best fit. But for small ones, fits are exact ++ anyway, so we can check now, which is faster.) ++ */ + + if (in_smallbin_range(nb)) { +- idx = smallbin_index(nb); +- bin = bin_at(av,idx); ++ idx = smallbin_index(nb); ++ bin = bin_at(av,idx); + +- if ( (victim = last(bin)) != bin) { +- bck = victim->bk; +- set_inuse_bit_at_offset(victim, nb); +- bin->bk = bck; +- bck->fd = bin; +- +- check_malloced_chunk(victim, nb); +- UNLOCK; +- return chunk2mem(victim); +- } ++ if ( (victim = last(bin)) != bin) { ++ bck = victim->bk; ++ set_inuse_bit_at_offset(victim, nb); ++ bin->bk = bck; ++ bck->fd = bin; ++ ++ check_malloced_chunk(victim, nb); ++ retval = chunk2mem(victim); ++ goto DONE; ++ } + } + + /* If this is a large request, consolidate fastbins before continuing. +@@ -899,154 +897,154 @@ void* malloc(size_t bytes) + large requests, but less often mixtures, so consolidation is not + invoked all that often in most programs. And the programs that + it is called frequently in otherwise tend to fragment. +- */ ++ */ + + else { +- idx = __malloc_largebin_index(nb); +- if (have_fastchunks(av)) +- __malloc_consolidate(av); ++ idx = __malloc_largebin_index(nb); ++ if (have_fastchunks(av)) ++ __malloc_consolidate(av); + } + + /* +- Process recently freed or remaindered chunks, taking one only if +- it is exact fit, or, if this a small request, the chunk is remainder from +- the most recent non-exact fit. Place other traversed chunks in +- bins. Note that this step is the only place in any routine where +- chunks are placed in bins. +- */ ++ Process recently freed or remaindered chunks, taking one only if ++ it is exact fit, or, if this a small request, the chunk is remainder from ++ the most recent non-exact fit. Place other traversed chunks in ++ bins. Note that this step is the only place in any routine where ++ chunks are placed in bins. ++ */ + + while ( (victim = unsorted_chunks(av)->bk) != unsorted_chunks(av)) { +- bck = victim->bk; +- size = chunksize(victim); ++ bck = victim->bk; ++ size = chunksize(victim); ++ ++ /* If a small request, try to use last remainder if it is the ++ only chunk in unsorted bin. This helps promote locality for ++ runs of consecutive small requests. This is the only ++ exception to best-fit, and applies only when there is ++ no exact fit for a small chunk. ++ */ ++ ++ if (in_smallbin_range(nb) && ++ bck == unsorted_chunks(av) && ++ victim == av->last_remainder && ++ (unsigned long)(size) > (unsigned long)(nb + MINSIZE)) { ++ ++ /* split and reattach remainder */ ++ remainder_size = size - nb; ++ remainder = chunk_at_offset(victim, nb); ++ unsorted_chunks(av)->bk = unsorted_chunks(av)->fd = remainder; ++ av->last_remainder = remainder; ++ remainder->bk = remainder->fd = unsorted_chunks(av); ++ ++ set_head(victim, nb | PREV_INUSE); ++ set_head(remainder, remainder_size | PREV_INUSE); ++ set_foot(remainder, remainder_size); ++ ++ check_malloced_chunk(victim, nb); ++ retval = chunk2mem(victim); ++ goto DONE; ++ } ++ ++ /* remove from unsorted list */ ++ unsorted_chunks(av)->bk = bck; ++ bck->fd = unsorted_chunks(av); ++ ++ /* Take now instead of binning if exact fit */ ++ ++ if (size == nb) { ++ set_inuse_bit_at_offset(victim, size); ++ check_malloced_chunk(victim, nb); ++ retval = chunk2mem(victim); ++ goto DONE; ++ } ++ ++ /* place chunk in bin */ + +- /* If a small request, try to use last remainder if it is the +- only chunk in unsorted bin. This helps promote locality for +- runs of consecutive small requests. This is the only +- exception to best-fit, and applies only when there is +- no exact fit for a small chunk. +- */ +- +- if (in_smallbin_range(nb) && +- bck == unsorted_chunks(av) && +- victim == av->last_remainder && +- (unsigned long)(size) > (unsigned long)(nb + MINSIZE)) { +- +- /* split and reattach remainder */ +- remainder_size = size - nb; +- remainder = chunk_at_offset(victim, nb); +- unsorted_chunks(av)->bk = unsorted_chunks(av)->fd = remainder; +- av->last_remainder = remainder; +- remainder->bk = remainder->fd = unsorted_chunks(av); +- +- set_head(victim, nb | PREV_INUSE); +- set_head(remainder, remainder_size | PREV_INUSE); +- set_foot(remainder, remainder_size); +- +- check_malloced_chunk(victim, nb); +- UNLOCK; +- return chunk2mem(victim); +- } +- +- /* remove from unsorted list */ +- unsorted_chunks(av)->bk = bck; +- bck->fd = unsorted_chunks(av); +- +- /* Take now instead of binning if exact fit */ +- +- if (size == nb) { +- set_inuse_bit_at_offset(victim, size); +- check_malloced_chunk(victim, nb); +- UNLOCK; +- return chunk2mem(victim); +- } +- +- /* place chunk in bin */ +- +- if (in_smallbin_range(size)) { +- victim_index = smallbin_index(size); +- bck = bin_at(av, victim_index); +- fwd = bck->fd; +- } +- else { +- victim_index = __malloc_largebin_index(size); +- bck = bin_at(av, victim_index); +- fwd = bck->fd; +- +- if (fwd != bck) { +- /* if smaller than smallest, place first */ +- if ((unsigned long)(size) < (unsigned long)(bck->bk->size)) { +- fwd = bck; +- bck = bck->bk; +- } +- else if ((unsigned long)(size) >= +- (unsigned long)(FIRST_SORTED_BIN_SIZE)) { +- +- /* maintain large bins in sorted order */ +- size |= PREV_INUSE; /* Or with inuse bit to speed comparisons */ +- while ((unsigned long)(size) < (unsigned long)(fwd->size)) +- fwd = fwd->fd; +- bck = fwd->bk; +- } +- } +- } +- +- mark_bin(av, victim_index); +- victim->bk = bck; +- victim->fd = fwd; +- fwd->bk = victim; +- bck->fd = victim; ++ if (in_smallbin_range(size)) { ++ victim_index = smallbin_index(size); ++ bck = bin_at(av, victim_index); ++ fwd = bck->fd; ++ } ++ else { ++ victim_index = __malloc_largebin_index(size); ++ bck = bin_at(av, victim_index); ++ fwd = bck->fd; ++ ++ if (fwd != bck) { ++ /* if smaller than smallest, place first */ ++ if ((unsigned long)(size) < (unsigned long)(bck->bk->size)) { ++ fwd = bck; ++ bck = bck->bk; ++ } ++ else if ((unsigned long)(size) >= ++ (unsigned long)(FIRST_SORTED_BIN_SIZE)) { ++ ++ /* maintain large bins in sorted order */ ++ size |= PREV_INUSE; /* Or with inuse bit to speed comparisons */ ++ while ((unsigned long)(size) < (unsigned long)(fwd->size)) ++ fwd = fwd->fd; ++ bck = fwd->bk; ++ } ++ } ++ } ++ ++ mark_bin(av, victim_index); ++ victim->bk = bck; ++ victim->fd = fwd; ++ fwd->bk = victim; ++ bck->fd = victim; + } + + /* +- If a large request, scan through the chunks of current bin to +- find one that fits. (This will be the smallest that fits unless +- FIRST_SORTED_BIN_SIZE has been changed from default.) This is +- the only step where an unbounded number of chunks might be +- scanned without doing anything useful with them. However the +- lists tend to be short. +- */ ++ If a large request, scan through the chunks of current bin to ++ find one that fits. (This will be the smallest that fits unless ++ FIRST_SORTED_BIN_SIZE has been changed from default.) This is ++ the only step where an unbounded number of chunks might be ++ scanned without doing anything useful with them. However the ++ lists tend to be short. ++ */ + + if (!in_smallbin_range(nb)) { +- bin = bin_at(av, idx); +- +- for (victim = last(bin); victim != bin; victim = victim->bk) { +- size = chunksize(victim); ++ bin = bin_at(av, idx); + +- if ((unsigned long)(size) >= (unsigned long)(nb)) { +- remainder_size = size - nb; +- unlink(victim, bck, fwd); ++ for (victim = last(bin); victim != bin; victim = victim->bk) { ++ size = chunksize(victim); + +- /* Exhaust */ +- if (remainder_size < MINSIZE) { +- set_inuse_bit_at_offset(victim, size); +- check_malloced_chunk(victim, nb); +- UNLOCK; +- return chunk2mem(victim); +- } +- /* Split */ +- else { +- remainder = chunk_at_offset(victim, nb); +- unsorted_chunks(av)->bk = unsorted_chunks(av)->fd = remainder; +- remainder->bk = remainder->fd = unsorted_chunks(av); +- set_head(victim, nb | PREV_INUSE); +- set_head(remainder, remainder_size | PREV_INUSE); +- set_foot(remainder, remainder_size); +- check_malloced_chunk(victim, nb); +- UNLOCK; +- return chunk2mem(victim); ++ if ((unsigned long)(size) >= (unsigned long)(nb)) { ++ remainder_size = size - nb; ++ unlink(victim, bck, fwd); ++ ++ /* Exhaust */ ++ if (remainder_size < MINSIZE) { ++ set_inuse_bit_at_offset(victim, size); ++ check_malloced_chunk(victim, nb); ++ retval = chunk2mem(victim); ++ goto DONE; ++ } ++ /* Split */ ++ else { ++ remainder = chunk_at_offset(victim, nb); ++ unsorted_chunks(av)->bk = unsorted_chunks(av)->fd = remainder; ++ remainder->bk = remainder->fd = unsorted_chunks(av); ++ set_head(victim, nb | PREV_INUSE); ++ set_head(remainder, remainder_size | PREV_INUSE); ++ set_foot(remainder, remainder_size); ++ check_malloced_chunk(victim, nb); ++ retval = chunk2mem(victim); ++ goto DONE; ++ } ++ } + } +- } +- } + } + + /* +- Search for a chunk by scanning bins, starting with next largest +- bin. This search is strictly by best-fit; i.e., the smallest +- (with ties going to approximately the least recently used) chunk +- that fits is selected. ++ Search for a chunk by scanning bins, starting with next largest ++ bin. This search is strictly by best-fit; i.e., the smallest ++ (with ties going to approximately the least recently used) chunk ++ that fits is selected. + +- The bitmap avoids needing to check that most blocks are nonempty. +- */ ++ The bitmap avoids needing to check that most blocks are nonempty. ++ */ + + ++idx; + bin = bin_at(av,idx); +@@ -1056,109 +1054,111 @@ void* malloc(size_t bytes) + + for (;;) { + +- /* Skip rest of block if there are no more set bits in this block. */ +- if (bit > map || bit == 0) { +- do { +- if (++block >= BINMAPSIZE) /* out of bins */ +- goto use_top; +- } while ( (map = av->binmap[block]) == 0); +- +- bin = bin_at(av, (block << BINMAPSHIFT)); +- bit = 1; +- } +- +- /* Advance to bin with set bit. There must be one. */ +- while ((bit & map) == 0) { +- bin = next_bin(bin); +- bit <<= 1; +- assert(bit != 0); +- } +- +- /* Inspect the bin. It is likely to be non-empty */ +- victim = last(bin); +- +- /* If a false alarm (empty bin), clear the bit. */ +- if (victim == bin) { +- av->binmap[block] = map &= ~bit; /* Write through */ +- bin = next_bin(bin); +- bit <<= 1; +- } +- +- else { +- size = chunksize(victim); +- +- /* We know the first chunk in this bin is big enough to use. */ +- assert((unsigned long)(size) >= (unsigned long)(nb)); +- +- remainder_size = size - nb; +- +- /* unlink */ +- bck = victim->bk; +- bin->bk = bck; +- bck->fd = bin; +- +- /* Exhaust */ +- if (remainder_size < MINSIZE) { +- set_inuse_bit_at_offset(victim, size); +- check_malloced_chunk(victim, nb); +- UNLOCK; +- return chunk2mem(victim); +- } ++ /* Skip rest of block if there are no more set bits in this block. */ ++ if (bit > map || bit == 0) { ++ do { ++ if (++block >= BINMAPSIZE) /* out of bins */ ++ goto use_top; ++ } while ( (map = av->binmap[block]) == 0); + +- /* Split */ +- else { +- remainder = chunk_at_offset(victim, nb); ++ bin = bin_at(av, (block << BINMAPSHIFT)); ++ bit = 1; ++ } + +- unsorted_chunks(av)->bk = unsorted_chunks(av)->fd = remainder; +- remainder->bk = remainder->fd = unsorted_chunks(av); +- /* advertise as last remainder */ +- if (in_smallbin_range(nb)) +- av->last_remainder = remainder; ++ /* Advance to bin with set bit. There must be one. */ ++ while ((bit & map) == 0) { ++ bin = next_bin(bin); ++ bit <<= 1; ++ assert(bit != 0); ++ } + +- set_head(victim, nb | PREV_INUSE); +- set_head(remainder, remainder_size | PREV_INUSE); +- set_foot(remainder, remainder_size); +- check_malloced_chunk(victim, nb); +- UNLOCK; +- return chunk2mem(victim); +- } +- } ++ /* Inspect the bin. It is likely to be non-empty */ ++ victim = last(bin); ++ ++ /* If a false alarm (empty bin), clear the bit. */ ++ if (victim == bin) { ++ av->binmap[block] = map &= ~bit; /* Write through */ ++ bin = next_bin(bin); ++ bit <<= 1; ++ } ++ ++ else { ++ size = chunksize(victim); ++ ++ /* We know the first chunk in this bin is big enough to use. */ ++ assert((unsigned long)(size) >= (unsigned long)(nb)); ++ ++ remainder_size = size - nb; ++ ++ /* unlink */ ++ bck = victim->bk; ++ bin->bk = bck; ++ bck->fd = bin; ++ ++ /* Exhaust */ ++ if (remainder_size < MINSIZE) { ++ set_inuse_bit_at_offset(victim, size); ++ check_malloced_chunk(victim, nb); ++ retval = chunk2mem(victim); ++ goto DONE; ++ } ++ ++ /* Split */ ++ else { ++ remainder = chunk_at_offset(victim, nb); ++ ++ unsorted_chunks(av)->bk = unsorted_chunks(av)->fd = remainder; ++ remainder->bk = remainder->fd = unsorted_chunks(av); ++ /* advertise as last remainder */ ++ if (in_smallbin_range(nb)) ++ av->last_remainder = remainder; ++ ++ set_head(victim, nb | PREV_INUSE); ++ set_head(remainder, remainder_size | PREV_INUSE); ++ set_foot(remainder, remainder_size); ++ check_malloced_chunk(victim, nb); ++ retval = chunk2mem(victim); ++ goto DONE; ++ } ++ } + } + +-use_top: ++ use_top: + /* +- If large enough, split off the chunk bordering the end of memory +- (held in av->top). Note that this is in accord with the best-fit +- search rule. In effect, av->top is treated as larger (and thus +- less well fitting) than any other available chunk since it can +- be extended to be as large as necessary (up to system +- limitations). +- +- We require that av->top always exists (i.e., has size >= +- MINSIZE) after initialization, so if it would otherwise be +- exhuasted by current request, it is replenished. (The main +- reason for ensuring it exists is that we may need MINSIZE space +- to put in fenceposts in sysmalloc.) +- */ ++ If large enough, split off the chunk bordering the end of memory ++ (held in av->top). Note that this is in accord with the best-fit ++ search rule. In effect, av->top is treated as larger (and thus ++ less well fitting) than any other available chunk since it can ++ be extended to be as large as necessary (up to system ++ limitations). ++ ++ We require that av->top always exists (i.e., has size >= ++ MINSIZE) after initialization, so if it would otherwise be ++ exhuasted by current request, it is replenished. (The main ++ reason for ensuring it exists is that we may need MINSIZE space ++ to put in fenceposts in sysmalloc.) ++ */ + + victim = av->top; + size = chunksize(victim); + + if ((unsigned long)(size) >= (unsigned long)(nb + MINSIZE)) { +- remainder_size = size - nb; +- remainder = chunk_at_offset(victim, nb); +- av->top = remainder; +- set_head(victim, nb | PREV_INUSE); +- set_head(remainder, remainder_size | PREV_INUSE); +- +- check_malloced_chunk(victim, nb); +- UNLOCK; +- return chunk2mem(victim); ++ remainder_size = size - nb; ++ remainder = chunk_at_offset(victim, nb); ++ av->top = remainder; ++ set_head(victim, nb | PREV_INUSE); ++ set_head(remainder, remainder_size | PREV_INUSE); ++ ++ check_malloced_chunk(victim, nb); ++ retval = chunk2mem(victim); ++ goto DONE; + } + + /* If no space in top, relay to handle system-dependent cases */ + sysmem = __malloc_alloc(nb, av); +- UNLOCK; +- return sysmem; ++ retval = sysmem; ++ DONE: ++ __MALLOC_UNLOCK; ++ return retval; + } + +diff --git a/libc/stdlib/malloc-standard/malloc.h b/libc/stdlib/malloc-standard/malloc.h +index fbc1492..14a0dd9 100644 +--- a/libc/stdlib/malloc-standard/malloc.h ++++ b/libc/stdlib/malloc-standard/malloc.h +@@ -22,16 +22,12 @@ + #include <malloc.h> + #include <stdlib.h> + ++#include <bits/uClibc_mutex.h> + +-#ifdef __UCLIBC_HAS_THREADS__ +-#include <pthread.h> +-extern pthread_mutex_t __malloc_lock; +-# define LOCK __pthread_mutex_lock(&__malloc_lock) +-# define UNLOCK __pthread_mutex_unlock(&__malloc_lock); +-#else +-# define LOCK +-# define UNLOCK +-#endif ++__UCLIBC_MUTEX_EXTERN(__malloc_lock); ++ ++#define __MALLOC_LOCK __UCLIBC_MUTEX_LOCK(__malloc_lock) ++#define __MALLOC_UNLOCK __UCLIBC_MUTEX_UNLOCK(__malloc_lock) + + + +diff --git a/libc/stdlib/malloc-standard/mallopt.c b/libc/stdlib/malloc-standard/mallopt.c +index e287920..41aa614 100644 +--- a/libc/stdlib/malloc-standard/mallopt.c ++++ b/libc/stdlib/malloc-standard/mallopt.c +@@ -8,7 +8,7 @@ + VERSION 2.7.2 Sat Aug 17 09:07:30 2002 Doug Lea (dl at gee) + + Note: There may be an updated version of this malloc obtainable at +- ftp://gee.cs.oswego.edu/pub/misc/malloc.c ++ ftp://gee.cs.oswego.edu/pub/misc/malloc.c + Check before installing! + + Hacked up for uClibc by Erik Andersen <andersen@codepoet.org> +@@ -25,40 +25,40 @@ int mallopt(int param_number, int value) + + ret = 0; + +- LOCK; ++ __MALLOC_LOCK; + av = get_malloc_state(); + /* Ensure initialization/consolidation */ + __malloc_consolidate(av); + + switch(param_number) { +- case M_MXFAST: +- if (value >= 0 && value <= MAX_FAST_SIZE) { +- set_max_fast(av, value); +- ret = 1; +- } +- break; +- +- case M_TRIM_THRESHOLD: +- av->trim_threshold = value; +- ret = 1; +- break; +- +- case M_TOP_PAD: +- av->top_pad = value; +- ret = 1; +- break; +- +- case M_MMAP_THRESHOLD: +- av->mmap_threshold = value; +- ret = 1; +- break; +- +- case M_MMAP_MAX: +- av->n_mmaps_max = value; +- ret = 1; +- break; ++ case M_MXFAST: ++ if (value >= 0 && value <= MAX_FAST_SIZE) { ++ set_max_fast(av, value); ++ ret = 1; ++ } ++ break; ++ ++ case M_TRIM_THRESHOLD: ++ av->trim_threshold = value; ++ ret = 1; ++ break; ++ ++ case M_TOP_PAD: ++ av->top_pad = value; ++ ret = 1; ++ break; ++ ++ case M_MMAP_THRESHOLD: ++ av->mmap_threshold = value; ++ ret = 1; ++ break; ++ ++ case M_MMAP_MAX: ++ av->n_mmaps_max = value; ++ ret = 1; ++ break; + } +- UNLOCK; ++ __MALLOC_UNLOCK; + return ret; + } + +diff --git a/libc/stdlib/malloc-standard/memalign.c b/libc/stdlib/malloc-standard/memalign.c +index bd95362..e78d752 100644 +--- a/libc/stdlib/malloc-standard/memalign.c ++++ b/libc/stdlib/malloc-standard/memalign.c +@@ -8,7 +8,7 @@ + VERSION 2.7.2 Sat Aug 17 09:07:30 2002 Doug Lea (dl at gee) + + Note: There may be an updated version of this malloc obtainable at +- ftp://gee.cs.oswego.edu/pub/misc/malloc.c ++ ftp://gee.cs.oswego.edu/pub/misc/malloc.c + Check before installing! + + Hacked up for uClibc by Erik Andersen <andersen@codepoet.org> +@@ -35,6 +35,7 @@ void* memalign(size_t alignment, size_t + mchunkptr remainder; /* spare room at end to split off */ + unsigned long remainder_size; /* its size */ + size_t size; ++ void *retval; + + /* If need less alignment than we give anyway, just relay to malloc */ + +@@ -46,12 +47,12 @@ void* memalign(size_t alignment, size_t + + /* Make sure alignment is power of 2 (in case MINSIZE is not). */ + if ((alignment & (alignment - 1)) != 0) { +- size_t a = MALLOC_ALIGNMENT * 2; +- while ((unsigned long)a < (unsigned long)alignment) a <<= 1; +- alignment = a; ++ size_t a = MALLOC_ALIGNMENT * 2; ++ while ((unsigned long)a < (unsigned long)alignment) a <<= 1; ++ alignment = a; + } + +- LOCK; ++ __MALLOC_LOCK; + checked_request2size(bytes, nb); + + /* Strategy: find a spot within that chunk that meets the alignment +@@ -63,64 +64,67 @@ void* memalign(size_t alignment, size_t + m = (char*)(malloc(nb + alignment + MINSIZE)); + + if (m == 0) { +- UNLOCK; +- return 0; /* propagate failure */ ++ retval = 0; /* propagate failure */ ++ goto DONE; + } + + p = mem2chunk(m); + + if ((((unsigned long)(m)) % alignment) != 0) { /* misaligned */ + +- /* +- Find an aligned spot inside chunk. Since we need to give back +- leading space in a chunk of at least MINSIZE, if the first +- calculation places us at a spot with less than MINSIZE leader, +- we can move to the next aligned spot -- we've allocated enough +- total room so that this is always possible. +- */ +- +- brk = (char*)mem2chunk((unsigned long)(((unsigned long)(m + alignment - 1)) & +- -((signed long) alignment))); +- if ((unsigned long)(brk - (char*)(p)) < MINSIZE) +- brk += alignment; +- +- newp = (mchunkptr)brk; +- leadsize = brk - (char*)(p); +- newsize = chunksize(p) - leadsize; +- +- /* For mmapped chunks, just adjust offset */ +- if (chunk_is_mmapped(p)) { +- newp->prev_size = p->prev_size + leadsize; +- set_head(newp, newsize|IS_MMAPPED); +- UNLOCK; +- return chunk2mem(newp); +- } +- +- /* Otherwise, give back leader, use the rest */ +- set_head(newp, newsize | PREV_INUSE); +- set_inuse_bit_at_offset(newp, newsize); +- set_head_size(p, leadsize); +- free(chunk2mem(p)); +- p = newp; ++ /* ++ Find an aligned spot inside chunk. Since we need to give back ++ leading space in a chunk of at least MINSIZE, if the first ++ calculation places us at a spot with less than MINSIZE leader, ++ we can move to the next aligned spot -- we've allocated enough ++ total room so that this is always possible. ++ */ ++ ++ brk = (char*)mem2chunk((unsigned long)(((unsigned long)(m + alignment - 1)) & ++ -((signed long) alignment))); ++ if ((unsigned long)(brk - (char*)(p)) < MINSIZE) ++ brk += alignment; ++ ++ newp = (mchunkptr)brk; ++ leadsize = brk - (char*)(p); ++ newsize = chunksize(p) - leadsize; ++ ++ /* For mmapped chunks, just adjust offset */ ++ if (chunk_is_mmapped(p)) { ++ newp->prev_size = p->prev_size + leadsize; ++ set_head(newp, newsize|IS_MMAPPED); ++ retval = chunk2mem(newp); ++ goto DONE; ++ } ++ ++ /* Otherwise, give back leader, use the rest */ ++ set_head(newp, newsize | PREV_INUSE); ++ set_inuse_bit_at_offset(newp, newsize); ++ set_head_size(p, leadsize); ++ free(chunk2mem(p)); ++ p = newp; + +- assert (newsize >= nb && +- (((unsigned long)(chunk2mem(p))) % alignment) == 0); ++ assert (newsize >= nb && ++ (((unsigned long)(chunk2mem(p))) % alignment) == 0); + } + + /* Also give back spare room at the end */ + if (!chunk_is_mmapped(p)) { +- size = chunksize(p); +- if ((unsigned long)(size) > (unsigned long)(nb + MINSIZE)) { +- remainder_size = size - nb; +- remainder = chunk_at_offset(p, nb); +- set_head(remainder, remainder_size | PREV_INUSE); +- set_head_size(p, nb); +- free(chunk2mem(remainder)); +- } ++ size = chunksize(p); ++ if ((unsigned long)(size) > (unsigned long)(nb + MINSIZE)) { ++ remainder_size = size - nb; ++ remainder = chunk_at_offset(p, nb); ++ set_head(remainder, remainder_size | PREV_INUSE); ++ set_head_size(p, nb); ++ free(chunk2mem(remainder)); ++ } + } + + check_inuse_chunk(p); +- UNLOCK; +- return chunk2mem(p); ++ retval = chunk2mem(p); ++ ++ DONE: ++ __MALLOC_UNLOCK; ++ return retval; + } + +diff --git a/libc/stdlib/malloc-standard/realloc.c b/libc/stdlib/malloc-standard/realloc.c +index 1950130..9ca4b26 100644 +--- a/libc/stdlib/malloc-standard/realloc.c ++++ b/libc/stdlib/malloc-standard/realloc.c +@@ -8,7 +8,7 @@ + VERSION 2.7.2 Sat Aug 17 09:07:30 2002 Doug Lea (dl at gee) + + Note: There may be an updated version of this malloc obtainable at +- ftp://gee.cs.oswego.edu/pub/misc/malloc.c ++ ftp://gee.cs.oswego.edu/pub/misc/malloc.c + Check before installing! + + Hacked up for uClibc by Erik Andersen <andersen@codepoet.org> +@@ -23,14 +23,14 @@ void* realloc(void* oldmem, size_t bytes + { + mstate av; + +- size_t nb; /* padded request size */ ++ size_t nb; /* padded request size */ + + mchunkptr oldp; /* chunk corresponding to oldmem */ +- size_t oldsize; /* its size */ ++ size_t oldsize; /* its size */ + + mchunkptr newp; /* chunk to return */ +- size_t newsize; /* its size */ +- void* newmem; /* corresponding user mem */ ++ size_t newsize; /* its size */ ++ void* newmem; /* corresponding user mem */ + + mchunkptr next; /* next contiguous chunk after oldp */ + +@@ -40,21 +40,23 @@ void* realloc(void* oldmem, size_t bytes + mchunkptr bck; /* misc temp for linking */ + mchunkptr fwd; /* misc temp for linking */ + +- unsigned long copysize; /* bytes to copy */ ++ unsigned long copysize; /* bytes to copy */ + unsigned int ncopies; /* size_t words to copy */ +- size_t* s; /* copy source */ +- size_t* d; /* copy destination */ ++ size_t* s; /* copy source */ ++ size_t* d; /* copy destination */ ++ ++ void *retval; + + + /* Check for special cases. */ + if (! oldmem) +- return malloc(bytes); ++ return malloc(bytes); + if (! bytes) { +- free (oldmem); +- return malloc(bytes); ++ free (oldmem); ++ return malloc(bytes); + } + +- LOCK; ++ __MALLOC_LOCK; + av = get_malloc_state(); + checked_request2size(bytes, nb); + +@@ -65,173 +67,176 @@ void* realloc(void* oldmem, size_t bytes + + if (!chunk_is_mmapped(oldp)) { + +- if ((unsigned long)(oldsize) >= (unsigned long)(nb)) { +- /* already big enough; split below */ +- newp = oldp; +- newsize = oldsize; +- } +- +- else { +- next = chunk_at_offset(oldp, oldsize); +- +- /* Try to expand forward into top */ +- if (next == av->top && +- (unsigned long)(newsize = oldsize + chunksize(next)) >= +- (unsigned long)(nb + MINSIZE)) { +- set_head_size(oldp, nb); +- av->top = chunk_at_offset(oldp, nb); +- set_head(av->top, (newsize - nb) | PREV_INUSE); +- UNLOCK; +- return chunk2mem(oldp); +- } +- +- /* Try to expand forward into next chunk; split off remainder below */ +- else if (next != av->top && +- !inuse(next) && +- (unsigned long)(newsize = oldsize + chunksize(next)) >= +- (unsigned long)(nb)) { +- newp = oldp; +- unlink(next, bck, fwd); +- } +- +- /* allocate, copy, free */ +- else { +- newmem = malloc(nb - MALLOC_ALIGN_MASK); +- if (newmem == 0) { +- UNLOCK; +- return 0; /* propagate failure */ +- } +- +- newp = mem2chunk(newmem); +- newsize = chunksize(newp); +- +- /* +- Avoid copy if newp is next chunk after oldp. +- */ +- if (newp == next) { +- newsize += oldsize; +- newp = oldp; ++ if ((unsigned long)(oldsize) >= (unsigned long)(nb)) { ++ /* already big enough; split below */ ++ newp = oldp; ++ newsize = oldsize; + } ++ + else { +- /* +- Unroll copy of <= 36 bytes (72 if 8byte sizes) +- We know that contents have an odd number of +- size_t-sized words; minimally 3. +- */ +- +- copysize = oldsize - (sizeof(size_t)); +- s = (size_t*)(oldmem); +- d = (size_t*)(newmem); +- ncopies = copysize / sizeof(size_t); +- assert(ncopies >= 3); +- +- if (ncopies > 9) +- memcpy(d, s, copysize); +- +- else { +- *(d+0) = *(s+0); +- *(d+1) = *(s+1); +- *(d+2) = *(s+2); +- if (ncopies > 4) { +- *(d+3) = *(s+3); +- *(d+4) = *(s+4); +- if (ncopies > 6) { +- *(d+5) = *(s+5); +- *(d+6) = *(s+6); +- if (ncopies > 8) { +- *(d+7) = *(s+7); +- *(d+8) = *(s+8); ++ next = chunk_at_offset(oldp, oldsize); ++ ++ /* Try to expand forward into top */ ++ if (next == av->top && ++ (unsigned long)(newsize = oldsize + chunksize(next)) >= ++ (unsigned long)(nb + MINSIZE)) { ++ set_head_size(oldp, nb); ++ av->top = chunk_at_offset(oldp, nb); ++ set_head(av->top, (newsize - nb) | PREV_INUSE); ++ retval = chunk2mem(oldp); ++ goto DONE; ++ } ++ ++ /* Try to expand forward into next chunk; split off remainder below */ ++ else if (next != av->top && ++ !inuse(next) && ++ (unsigned long)(newsize = oldsize + chunksize(next)) >= ++ (unsigned long)(nb)) { ++ newp = oldp; ++ unlink(next, bck, fwd); ++ } ++ ++ /* allocate, copy, free */ ++ else { ++ newmem = malloc(nb - MALLOC_ALIGN_MASK); ++ if (newmem == 0) { ++ retval = 0; /* propagate failure */ ++ goto DONE; ++ } ++ ++ newp = mem2chunk(newmem); ++ newsize = chunksize(newp); ++ ++ /* ++ Avoid copy if newp is next chunk after oldp. ++ */ ++ if (newp == next) { ++ newsize += oldsize; ++ newp = oldp; ++ } ++ else { ++ /* ++ Unroll copy of <= 36 bytes (72 if 8byte sizes) ++ We know that contents have an odd number of ++ size_t-sized words; minimally 3. ++ */ ++ ++ copysize = oldsize - (sizeof(size_t)); ++ s = (size_t*)(oldmem); ++ d = (size_t*)(newmem); ++ ncopies = copysize / sizeof(size_t); ++ assert(ncopies >= 3); ++ ++ if (ncopies > 9) ++ memcpy(d, s, copysize); ++ ++ else { ++ *(d+0) = *(s+0); ++ *(d+1) = *(s+1); ++ *(d+2) = *(s+2); ++ if (ncopies > 4) { ++ *(d+3) = *(s+3); ++ *(d+4) = *(s+4); ++ if (ncopies > 6) { ++ *(d+5) = *(s+5); ++ *(d+6) = *(s+6); ++ if (ncopies > 8) { ++ *(d+7) = *(s+7); ++ *(d+8) = *(s+8); ++ } ++ } ++ } ++ } ++ ++ free(oldmem); ++ check_inuse_chunk(newp); ++ retval = chunk2mem(newp); ++ goto DONE; + } +- } + } +- } ++ } ++ ++ /* If possible, free extra space in old or extended chunk */ ++ ++ assert((unsigned long)(newsize) >= (unsigned long)(nb)); ++ ++ remainder_size = newsize - nb; + +- free(oldmem); +- check_inuse_chunk(newp); +- UNLOCK; +- return chunk2mem(newp); +- } +- } +- } +- +- /* If possible, free extra space in old or extended chunk */ +- +- assert((unsigned long)(newsize) >= (unsigned long)(nb)); +- +- remainder_size = newsize - nb; +- +- if (remainder_size < MINSIZE) { /* not enough extra to split off */ +- set_head_size(newp, newsize); +- set_inuse_bit_at_offset(newp, newsize); +- } +- else { /* split remainder */ +- remainder = chunk_at_offset(newp, nb); +- set_head_size(newp, nb); +- set_head(remainder, remainder_size | PREV_INUSE); +- /* Mark remainder as inuse so free() won't complain */ +- set_inuse_bit_at_offset(remainder, remainder_size); +- free(chunk2mem(remainder)); +- } +- +- check_inuse_chunk(newp); +- UNLOCK; +- return chunk2mem(newp); ++ if (remainder_size < MINSIZE) { /* not enough extra to split off */ ++ set_head_size(newp, newsize); ++ set_inuse_bit_at_offset(newp, newsize); ++ } ++ else { /* split remainder */ ++ remainder = chunk_at_offset(newp, nb); ++ set_head_size(newp, nb); ++ set_head(remainder, remainder_size | PREV_INUSE); ++ /* Mark remainder as inuse so free() won't complain */ ++ set_inuse_bit_at_offset(remainder, remainder_size); ++ free(chunk2mem(remainder)); ++ } ++ ++ check_inuse_chunk(newp); ++ retval = chunk2mem(newp); ++ goto DONE; + } + + /* +- Handle mmap cases +- */ ++ Handle mmap cases ++ */ + + else { +- size_t offset = oldp->prev_size; +- size_t pagemask = av->pagesize - 1; +- char *cp; +- unsigned long sum; +- +- /* Note the extra (sizeof(size_t)) overhead */ +- newsize = (nb + offset + (sizeof(size_t)) + pagemask) & ~pagemask; +- +- /* don't need to remap if still within same page */ +- if (oldsize == newsize - offset) { +- UNLOCK; +- return oldmem; +- } +- +- cp = (char*)mremap((char*)oldp - offset, oldsize + offset, newsize, 1); +- +- if (cp != (char*)MORECORE_FAILURE) { +- +- newp = (mchunkptr)(cp + offset); +- set_head(newp, (newsize - offset)|IS_MMAPPED); +- +- assert(aligned_OK(chunk2mem(newp))); +- assert((newp->prev_size == offset)); +- +- /* update statistics */ +- sum = av->mmapped_mem += newsize - oldsize; +- if (sum > (unsigned long)(av->max_mmapped_mem)) +- av->max_mmapped_mem = sum; +- sum += av->sbrked_mem; +- if (sum > (unsigned long)(av->max_total_mem)) +- av->max_total_mem = sum; +- +- UNLOCK; +- return chunk2mem(newp); +- } +- +- /* Note the extra (sizeof(size_t)) overhead. */ +- if ((unsigned long)(oldsize) >= (unsigned long)(nb + (sizeof(size_t)))) +- newmem = oldmem; /* do nothing */ +- else { +- /* Must alloc, copy, free. */ +- newmem = malloc(nb - MALLOC_ALIGN_MASK); +- if (newmem != 0) { +- memcpy(newmem, oldmem, oldsize - 2*(sizeof(size_t))); +- free(oldmem); +- } +- } +- UNLOCK; +- return newmem; ++ size_t offset = oldp->prev_size; ++ size_t pagemask = av->pagesize - 1; ++ char *cp; ++ unsigned long sum; ++ ++ /* Note the extra (sizeof(size_t)) overhead */ ++ newsize = (nb + offset + (sizeof(size_t)) + pagemask) & ~pagemask; ++ ++ /* don't need to remap if still within same page */ ++ if (oldsize == newsize - offset) { ++ retval = oldmem; ++ goto DONE; ++ } ++ ++ cp = (char*)mremap((char*)oldp - offset, oldsize + offset, newsize, 1); ++ ++ if (cp != (char*)MORECORE_FAILURE) { ++ ++ newp = (mchunkptr)(cp + offset); ++ set_head(newp, (newsize - offset)|IS_MMAPPED); ++ ++ assert(aligned_OK(chunk2mem(newp))); ++ assert((newp->prev_size == offset)); ++ ++ /* update statistics */ ++ sum = av->mmapped_mem += newsize - oldsize; ++ if (sum > (unsigned long)(av->max_mmapped_mem)) ++ av->max_mmapped_mem = sum; ++ sum += av->sbrked_mem; ++ if (sum > (unsigned long)(av->max_total_mem)) ++ av->max_total_mem = sum; ++ ++ retval = chunk2mem(newp); ++ goto DONE; ++ } ++ ++ /* Note the extra (sizeof(size_t)) overhead. */ ++ if ((unsigned long)(oldsize) >= (unsigned long)(nb + (sizeof(size_t)))) ++ newmem = oldmem; /* do nothing */ ++ else { ++ /* Must alloc, copy, free. */ ++ newmem = malloc(nb - MALLOC_ALIGN_MASK); ++ if (newmem != 0) { ++ memcpy(newmem, oldmem, oldsize - 2*(sizeof(size_t))); ++ free(oldmem); ++ } ++ } ++ retval = newmem; + } ++ ++ DONE: ++ __MALLOC_UNLOCK; ++ return retval; + } + +diff --git a/libc/stdlib/random.c b/libc/stdlib/random.c +index b0a00e1..1bd63bc 100644 +--- a/libc/stdlib/random.c ++++ b/libc/stdlib/random.c +@@ -27,16 +27,14 @@ + #include <limits.h> + #include <stddef.h> + #include <stdlib.h> +-#ifdef __UCLIBC_HAS_THREADS__ +-#include <pthread.h> ++ + /* POSIX.1c requires that there is mutual exclusion for the `rand' and + `srand' functions to prevent concurrent calls from modifying common + data. */ +-static pthread_mutex_t lock = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP; +-#else +-#define __pthread_mutex_lock(x) +-#define __pthread_mutex_unlock(x) +-#endif ++ ++#include <bits/uClibc_mutex.h> ++ ++__UCLIBC_MUTEX_STATIC(mylock, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP); + + /* An improved random number generation package. In addition to the standard + rand()/srand() like interface, this package also has a special state info +@@ -184,9 +182,9 @@ static struct random_data unsafe_state = + for default usage relies on values produced by this routine. */ + void srandom (unsigned int x) + { +- __pthread_mutex_lock(&lock); ++ __UCLIBC_MUTEX_LOCK(mylock); + srandom_r (x, &unsafe_state); +- __pthread_mutex_unlock(&lock); ++ __UCLIBC_MUTEX_UNLOCK(mylock); + } + weak_alias (srandom, srand) + +@@ -205,10 +203,10 @@ char * initstate (unsigned int seed, cha + { + int32_t *ostate; + +- __pthread_mutex_lock(&lock); ++ __UCLIBC_MUTEX_LOCK(mylock); + ostate = &unsafe_state.state[-1]; + initstate_r (seed, arg_state, n, &unsafe_state); +- __pthread_mutex_unlock(&lock); ++ __UCLIBC_MUTEX_UNLOCK(mylock); + return (char *) ostate; + } + +@@ -224,11 +222,11 @@ char * setstate (char *arg_state) + { + int32_t *ostate; + +- __pthread_mutex_lock(&lock); ++ __UCLIBC_MUTEX_LOCK(mylock); + ostate = &unsafe_state.state[-1]; + if (setstate_r (arg_state, &unsafe_state) < 0) + ostate = NULL; +- __pthread_mutex_unlock(&lock); ++ __UCLIBC_MUTEX_UNLOCK(mylock); + return (char *) ostate; + } + +@@ -247,9 +245,9 @@ long int random () + { + int32_t retval; + +- __pthread_mutex_lock(&lock); ++ __UCLIBC_MUTEX_LOCK(mylock); + random_r (&unsafe_state, &retval); +- __pthread_mutex_unlock(&lock); ++ __UCLIBC_MUTEX_UNLOCK(mylock); + return retval; + } + +diff --git a/libc/stdlib/setenv.c b/libc/stdlib/setenv.c +index d0cfe52..2d899cc 100644 +--- a/libc/stdlib/setenv.c ++++ b/libc/stdlib/setenv.c +@@ -17,7 +17,7 @@ + 02111-1307 USA. + + modified for uClibc by Erik Andersen <andersen@codepoet.org> +- */ ++*/ + + #define _GNU_SOURCE + #include <features.h> +@@ -26,16 +26,9 @@ + #include <string.h> + #include <unistd.h> + +-#ifdef __UCLIBC_HAS_THREADS__ +-#include <pthread.h> +-static pthread_mutex_t mylock = PTHREAD_MUTEX_INITIALIZER; +-# define LOCK __pthread_mutex_lock(&mylock) +-# define UNLOCK __pthread_mutex_unlock(&mylock); +-#else +-# define LOCK +-# define UNLOCK +-#endif ++#include <bits/uClibc_mutex.h> + ++__UCLIBC_MUTEX_STATIC(mylock, PTHREAD_MUTEX_INITIALIZER); + + /* If this variable is not a null pointer we allocated the current + environment. */ +@@ -49,14 +42,15 @@ static char **last_environ; + to reuse values once generated for a `setenv' call since we can never + free the strings. */ + int __add_to_environ (const char *name, const char *value, +- const char *combined, int replace) ++ const char *combined, int replace) + { + register char **ep; + register size_t size; + const size_t namelen = strlen (name); + const size_t vallen = value != NULL ? strlen (value) + 1 : 0; ++ int rv = -1; + +- LOCK; ++ __UCLIBC_MUTEX_LOCK(mylock); + + /* We have to get the pointer now that we have the lock and not earlier + since another thread might have created a new environment. */ +@@ -64,72 +58,72 @@ int __add_to_environ (const char *name, + + size = 0; + if (ep != NULL) { +- for (; *ep != NULL; ++ep) { +- if (!strncmp (*ep, name, namelen) && (*ep)[namelen] == '=') +- break; +- else +- ++size; +- } ++ for (; *ep != NULL; ++ep) { ++ if (!strncmp (*ep, name, namelen) && (*ep)[namelen] == '=') ++ break; ++ else ++ ++size; ++ } + } + + if (ep == NULL || *ep == NULL) { +- char **new_environ; ++ char **new_environ; + +- /* We allocated this space; we can extend it. */ +- new_environ = (char **) realloc (last_environ, +- (size + 2) * sizeof (char *)); +- if (new_environ == NULL) { +- UNLOCK; +- return -1; +- } +- +- /* If the whole entry is given add it. */ +- if (combined != NULL) { +- /* We must not add the string to the search tree since it belongs +- to the user. */ +- new_environ[size] = (char *) combined; +- } else { +- /* See whether the value is already known. */ +- new_environ[size] = (char *) malloc (namelen + 1 + vallen); +- if (new_environ[size] == NULL) { +- __set_errno (ENOMEM); +- UNLOCK; +- return -1; +- } +- +- memcpy (new_environ[size], name, namelen); +- new_environ[size][namelen] = '='; +- memcpy (&new_environ[size][namelen + 1], value, vallen); +- } +- +- if (__environ != last_environ) { +- memcpy ((char *) new_environ, (char *) __environ, +- size * sizeof (char *)); +- } ++ /* We allocated this space; we can extend it. */ ++ new_environ = (char **) realloc (last_environ, ++ (size + 2) * sizeof (char *)); ++ if (new_environ == NULL) { ++ goto DONE; ++ } ++ ++ /* If the whole entry is given add it. */ ++ if (combined != NULL) { ++ /* We must not add the string to the search tree since it belongs ++ to the user. */ ++ new_environ[size] = (char *) combined; ++ } else { ++ /* See whether the value is already known. */ ++ new_environ[size] = (char *) malloc (namelen + 1 + vallen); ++ if (new_environ[size] == NULL) { ++ __set_errno (ENOMEM); ++ goto DONE; ++ } ++ ++ memcpy (new_environ[size], name, namelen); ++ new_environ[size][namelen] = '='; ++ memcpy (&new_environ[size][namelen + 1], value, vallen); ++ } ++ ++ if (__environ != last_environ) { ++ memcpy ((char *) new_environ, (char *) __environ, ++ size * sizeof (char *)); ++ } + +- new_environ[size + 1] = NULL; +- last_environ = __environ = new_environ; ++ new_environ[size + 1] = NULL; ++ last_environ = __environ = new_environ; + } else if (replace) { +- char *np; ++ char *np; + +- /* Use the user string if given. */ +- if (combined != NULL) { +- np = (char *) combined; +- } else { +- np = malloc (namelen + 1 + vallen); +- if (np == NULL) { +- UNLOCK; +- return -1; +- } +- memcpy (np, name, namelen); +- np[namelen] = '='; +- memcpy (&np[namelen + 1], value, vallen); +- } +- *ep = np; +- } +- +- UNLOCK; +- return 0; ++ /* Use the user string if given. */ ++ if (combined != NULL) { ++ np = (char *) combined; ++ } else { ++ np = malloc (namelen + 1 + vallen); ++ if (np == NULL) { ++ goto DONE; ++ } ++ memcpy (np, name, namelen); ++ np[namelen] = '='; ++ memcpy (&np[namelen + 1], value, vallen); ++ } ++ *ep = np; ++ } ++ ++ rv = 0; ++ ++ DONE: ++ __UCLIBC_MUTEX_UNLOCK(mylock); ++ return rv; + } + + int setenv (const char *name, const char *value, int replace) +@@ -143,26 +137,26 @@ int unsetenv (const char *name) + char **ep; + + if (name == NULL || *name == '\0' || strchr (name, '=') != NULL) { +- __set_errno (EINVAL); +- return -1; ++ __set_errno (EINVAL); ++ return -1; + } + + len = strlen (name); +- LOCK; ++ __UCLIBC_MUTEX_LOCK(mylock); + ep = __environ; + while (*ep != NULL) { +- if (!strncmp (*ep, name, len) && (*ep)[len] == '=') { +- /* Found it. Remove this pointer by moving later ones back. */ +- char **dp = ep; +- do { +- dp[0] = dp[1]; +- } while (*dp++); +- /* Continue the loop in case NAME appears again. */ +- } else { +- ++ep; +- } ++ if (!strncmp (*ep, name, len) && (*ep)[len] == '=') { ++ /* Found it. Remove this pointer by moving later ones back. */ ++ char **dp = ep; ++ do { ++ dp[0] = dp[1]; ++ } while (*dp++); ++ /* Continue the loop in case NAME appears again. */ ++ } else { ++ ++ep; ++ } + } +- UNLOCK; ++ __UCLIBC_MUTEX_UNLOCK(mylock); + return 0; + } + +@@ -171,15 +165,15 @@ int unsetenv (const char *name) + for Fortran 77) requires this function. */ + int clearenv (void) + { +- LOCK; ++ __UCLIBC_MUTEX_LOCK(mylock); + if (__environ == last_environ && __environ != NULL) { +- /* We allocated this environment so we can free it. */ +- free (__environ); +- last_environ = NULL; ++ /* We allocated this environment so we can free it. */ ++ free (__environ); ++ last_environ = NULL; + } + /* Clear the environment pointer removes the whole environment. */ + __environ = NULL; +- UNLOCK; ++ __UCLIBC_MUTEX_UNLOCK(mylock); + return 0; + } + +@@ -190,10 +184,10 @@ int putenv (char *string) + const char *const name_end = strchr (string, '='); + + if (name_end != NULL) { +- char *name = strndup(string, name_end - string); +- result = __add_to_environ (name, NULL, string, 1); +- free(name); +- return(result); ++ char *name = strndup(string, name_end - string); ++ result = __add_to_environ (name, NULL, string, 1); ++ free(name); ++ return(result); + } + unsetenv (string); + return 0; +diff --git a/libc/sysdeps/linux/common/bits/uClibc_stdio.h b/libc/sysdeps/linux/common/bits/uClibc_stdio.h +index 40cd5fe..3c6911e 100644 +--- a/libc/sysdeps/linux/common/bits/uClibc_stdio.h ++++ b/libc/sysdeps/linux/common/bits/uClibc_stdio.h +@@ -116,9 +116,7 @@ + #endif + + /**********************************************************************/ +-#ifdef __UCLIBC_HAS_THREADS__ +-/* Need this for pthread_mutex_t. */ +-#include <bits/pthreadtypes.h> ++#include <bits/uClibc_mutex.h> + + /* user_locking + * 0 : do auto locking/unlocking +@@ -132,43 +130,37 @@ + * This way, we avoid calling the weak lock/unlock functions. + */ + +-#define __STDIO_AUTO_THREADLOCK_VAR int __infunc_user_locking +- +-#define __STDIO_AUTO_THREADLOCK(__stream) \ +- if ((__infunc_user_locking = (__stream)->__user_locking) == 0) { \ +- __pthread_mutex_lock(&(__stream)->__lock); \ +- } +- +-#define __STDIO_AUTO_THREADUNLOCK(__stream) \ +- if (__infunc_user_locking == 0) { \ +- __pthread_mutex_unlock(&(__stream)->__lock); \ +- } ++#define __STDIO_AUTO_THREADLOCK_VAR \ ++ __UCLIBC_MUTEX_AUTO_LOCK_VAR(__infunc_user_locking) + +-#define __STDIO_SET_USER_LOCKING(__stream) ((__stream)->__user_locking = 1) ++#define __STDIO_AUTO_THREADLOCK(__stream) \ ++ __UCLIBC_MUTEX_AUTO_LOCK((__stream)->__lock, __infunc_user_locking, \ ++ (__stream)->__user_locking) + +-#define __STDIO_ALWAYS_THREADLOCK(__stream) \ +- __pthread_mutex_lock(&(__stream)->__lock) ++#define __STDIO_AUTO_THREADUNLOCK(__stream) \ ++ __UCLIBC_MUTEX_AUTO_UNLOCK((__stream)->__lock, __infunc_user_locking) + +-#define __STDIO_ALWAYS_THREADTRYLOCK(__stream) \ +- __pthread_mutex_trylock(&(__stream)->__lock) ++#define __STDIO_ALWAYS_THREADLOCK(__stream) \ ++ __UCLIBC_MUTEX_LOCK((__stream)->__lock) + +-#define __STDIO_ALWAYS_THREADUNLOCK(__stream) \ +- __pthread_mutex_unlock(&(__stream)->__lock) ++#define __STDIO_ALWAYS_THREADUNLOCK(__stream) \ ++ __UCLIBC_MUTEX_UNLOCK((__stream)->__lock) + +-#else /* __UCLIBC_HAS_THREADS__ */ ++#define __STDIO_ALWAYS_THREADLOCK_CANCEL_UNSAFE(__stream) \ ++ __UCLIBC_MUTEX_LOCK_CANCEL_UNSAFE((__stream)->__lock) + +-#define __STDIO_AUTO_THREADLOCK_VAR ((void)0) ++#define __STDIO_ALWAYS_THREADTRYLOCK_CANCEL_UNSAFE(__stream) \ ++ __UCLIBC_MUTEX_TRYLOCK_CANCEL_UNSAFE((__stream)->__lock) + +-#define __STDIO_AUTO_THREADLOCK(__stream) ((void)0) +-#define __STDIO_AUTO_THREADUNLOCK(__stream) ((void)0) ++#define __STDIO_ALWAYS_THREADUNLOCK_CANCEL_UNSAFE(__stream) \ ++ __UCLIBC_MUTEX_UNLOCK_CANCEL_UNSAFE((__stream)->__lock) + ++#ifdef __UCLIBC_HAS_THREADS__ ++#define __STDIO_SET_USER_LOCKING(__stream) ((__stream)->__user_locking = 1) ++#else + #define __STDIO_SET_USER_LOCKING(__stream) ((void)0) ++#endif + +-#define __STDIO_ALWAYS_THREADLOCK(__stream) ((void)0) +-#define __STDIO_ALWAYS_THREADTRYLOCK(__stream) (0) /* Always succeed. */ +-#define __STDIO_ALWAYS_THREADUNLOCK(__stream) ((void)0) +- +-#endif /* __UCLIBC_HAS_THREADS__ */ + /**********************************************************************/ + + #define __STDIO_IOFBF 0 /* Fully buffered. */ +@@ -283,7 +275,7 @@ struct __STDIO_FILE_STRUCT { + #endif + #ifdef __UCLIBC_HAS_THREADS__ + int __user_locking; +- pthread_mutex_t __lock; ++ __UCLIBC_MUTEX(__lock); + #endif + /* Everything after this is unimplemented... and may be trashed. */ + #if __STDIO_BUILTIN_BUF_SIZE > 0 +@@ -358,10 +350,14 @@ extern void _stdio_term(void); + extern struct __STDIO_FILE_STRUCT *_stdio_openlist; + + #ifdef __UCLIBC_HAS_THREADS__ +-extern pthread_mutex_t _stdio_openlist_lock; +-extern int _stdio_openlist_delflag; ++__UCLIBC_MUTEX_EXTERN(_stdio_openlist_add_lock); ++#ifdef __STDIO_BUFFERS ++__UCLIBC_MUTEX_EXTERN(_stdio_openlist_del_lock); ++extern volatile int _stdio_openlist_use_count; /* _stdio_openlist_del_lock */ ++extern int _stdio_openlist_del_count; /* _stdio_openlist_del_lock */ ++#endif + extern int _stdio_user_locking; +-extern void __stdio_init_mutex(pthread_mutex_t *m); ++extern void __stdio_init_mutex(__UCLIBC_MUTEX_TYPE *m); + #endif + + #endif +diff --git a/libc/sysdeps/linux/common/getdents.c b/libc/sysdeps/linux/common/getdents.c +index ab6a276..23463e5 100644 +--- a/libc/sysdeps/linux/common/getdents.c ++++ b/libc/sysdeps/linux/common/getdents.c +@@ -30,8 +30,6 @@ + #include <sys/syscall.h> + + +-#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) +- + struct kernel_dirent + { + long d_ino; +diff --git a/libc/sysdeps/linux/common/sigprocmask.c b/libc/sysdeps/linux/common/sigprocmask.c +index 70ff366..565318d 100644 +--- a/libc/sysdeps/linux/common/sigprocmask.c ++++ b/libc/sysdeps/linux/common/sigprocmask.c +@@ -23,6 +23,8 @@ int sigprocmask(int how, const sigset_t + if (set && + #if (SIG_BLOCK == 0) && (SIG_UNBLOCK == 1) && (SIG_SETMASK == 2) + (((unsigned int) how) > 2) ++#elif (SIG_BLOCK == 1) && (SIG_UNBLOCK == 2) && (SIG_SETMASK == 3) ++ (((unsigned int)(how-1)) > 2) + #else + #warning "compile time assumption violated.. slow path..." + ((how != SIG_BLOCK) && (how != SIG_UNBLOCK) +@@ -48,6 +50,8 @@ int sigprocmask(int how, const sigset_t + if (set && + #if (SIG_BLOCK == 0) && (SIG_UNBLOCK == 1) && (SIG_SETMASK == 2) + (((unsigned int) how) > 2) ++#elif (SIG_BLOCK == 1) && (SIG_UNBLOCK == 2) && (SIG_SETMASK == 3) ++ (((unsigned int)(how-1)) > 2) + #else + #warning "compile time assumption violated.. slow path..." + ((how != SIG_BLOCK) && (how != SIG_UNBLOCK) +diff --git a/libc/sysdeps/linux/mips/bits/kernel_sigaction.h b/libc/sysdeps/linux/mips/bits/kernel_sigaction.h +index b6f52cc..317e5b3 100644 +--- a/libc/sysdeps/linux/mips/bits/kernel_sigaction.h ++++ b/libc/sysdeps/linux/mips/bits/kernel_sigaction.h +@@ -38,3 +38,6 @@ struct kernel_sigaction { + void (*sa_restorer)(void); + int s_resv[1]; /* reserved */ + }; ++ ++extern int __syscall_rt_sigaction (int, const struct kernel_sigaction *__unbounded, ++ struct kernel_sigaction *__unbounded, size_t); +diff --git a/libc/sysdeps/linux/mips/pipe.S b/libc/sysdeps/linux/mips/pipe.S +index c3afae5..cd88074 100644 +--- a/libc/sysdeps/linux/mips/pipe.S ++++ b/libc/sysdeps/linux/mips/pipe.S +@@ -7,25 +7,36 @@ + #include <asm/unistd.h> + #include <asm/regdef.h> + +- .globl pipe +- .ent pipe, 0 ++ .globl pipe ++ .ent pipe, 0 + pipe: +- addiu sp,sp,-24 +- sw a0,16(sp) +- li v0,__NR_pipe +- syscall +- beqz a3, 1f +- la t3, errno +- sw v0, (t3) +- li v0, -1 +- b 2f ++ .frame sp, 24, sp ++#ifdef __PIC__ ++ .set noreorder ++ .cpload $25 ++ .set reorder ++ addiu sp,sp,-24 ++ .cprestore 16 ++#else ++ addiu sp,sp,-24 ++#endif ++ sw a0,16(sp) ++ li v0,__NR_pipe ++ syscall ++ beqz a3, 1f ++#ifdef __PIC__ ++ la t0, __syscall_error ++ jr t9 ++#else ++ j __syscall_error ++#endif + 1: +- lw a0, 16(sp) +- sw v0, 0(a0) +- sw v1, 4(a0) +- li v0, 0 ++ lw a0, 16(sp) ++ sw v0, 0(a0) ++ sw v1, 4(a0) ++ li v0, 0 + 2: +- addiu sp,sp,24 +- j ra +- .end pipe +- .size pipe,.-pipe ++ addiu sp,sp,24 ++ j ra ++ .end pipe ++ .size pipe,.-pipe +diff --git a/libcrypt/des.c b/libcrypt/des.c +index 3b49a7a..f7a6be1 100644 +--- a/libcrypt/des.c ++++ b/libcrypt/des.c +@@ -504,7 +504,7 @@ do_des( u_int32_t l_in, u_int32_t r_in, + kl = kl1; + kr = kr1; + round = 16; +- while (round--) { ++ do { + /* + * Expand R to 48 bits (simulate the E-box). + */ +@@ -540,7 +540,7 @@ do_des( u_int32_t l_in, u_int32_t r_in, + f ^= l; + l = r; + r = f; +- } ++ } while (--round); + r = l; + l = f; + } +diff --git a/libpthread/linuxthreads/ptfork.c b/libpthread/linuxthreads/ptfork.c +index eb544f3..cfec2b7 100644 +--- a/libpthread/linuxthreads/ptfork.c ++++ b/libpthread/linuxthreads/ptfork.c +@@ -26,6 +26,15 @@ + #include "pthread.h" + #include "internals.h" + ++#warning hack alert... should be sufficent for system(), but what about other libc mutexes? ++#include <bits/uClibc_mutex.h> ++ ++__UCLIBC_MUTEX_EXTERN(__malloc_lock); ++ ++#define __MALLOC_LOCK __UCLIBC_MUTEX_LOCK(__malloc_lock) ++#define __MALLOC_UNLOCK __UCLIBC_MUTEX_UNLOCK(__malloc_lock) ++#warning hack alert block end ++ + struct handler_list { + void (*handler)(void); + struct handler_list * next; +@@ -91,9 +100,18 @@ pid_t __fork(void) + parent = pthread_atfork_parent; + pthread_mutex_unlock(&pthread_atfork_lock); + pthread_call_handlers(prepare); ++ ++#warning hack alert ++ __MALLOC_LOCK; ++ + pid = __libc_fork(); ++ ++#warning hack alert ++ __MALLOC_UNLOCK; ++ + if (pid == 0) { + __pthread_reset_main_thread(); ++#warning need to reconsider __fresetlockfiles! + __fresetlockfiles(); + pthread_call_handlers(child); + } else { +diff -urN -x .git uClibc-0.9.28/libc/sysdeps/linux/common/bits/uClibc_mutex.h uClibc-mjn3/libc/sysdeps/linux/common/bits/uClibc_mutex.h +--- uClibc-0.9.28/libc/sysdeps/linux/common/bits/uClibc_mutex.h 1969-12-31 17:00:00.000000000 -0700 ++++ uClibc-mjn3/libc/sysdeps/linux/common/bits/uClibc_mutex.h 2006-03-08 11:21:58.000000000 -0700 +@@ -0,0 +1,87 @@ ++/* Copyright (C) 2006 Manuel Novoa III <mjn3@codepoet.org> ++ * ++ * GNU Library General Public License (LGPL) version 2 or later. ++ * ++ * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. ++ */ ++ ++#ifndef _UCLIBC_MUTEX_H ++#define _UCLIBC_MUTEX_H ++ ++#include <features.h> ++ ++#ifdef __UCLIBC_HAS_THREADS__ ++ ++#include <pthread.h> ++ ++#define __UCLIBC_MUTEX_TYPE pthread_mutex_t ++ ++#define __UCLIBC_MUTEX(M) pthread_mutex_t M ++#define __UCLIBC_MUTEX_INIT(M,I) pthread_mutex_t M = I ++#define __UCLIBC_MUTEX_STATIC(M,I) static pthread_mutex_t M = I ++#define __UCLIBC_MUTEX_EXTERN(M) extern pthread_mutex_t M ++ ++#define __UCLIBC_MUTEX_LOCK_CANCEL_UNSAFE(M) \ ++ __pthread_mutex_lock(&(M)) ++ ++#define __UCLIBC_MUTEX_UNLOCK_CANCEL_UNSAFE(M) \ ++ __pthread_mutex_unlock(&(M)) ++ ++#define __UCLIBC_MUTEX_TRYLOCK_CANCEL_UNSAFE(M) \ ++ __pthread_mutex_trylock(&(M)) ++ ++#define __UCLIBC_MUTEX_CONDITIONAL_LOCK(M,C) \ ++ do { \ ++ struct _pthread_cleanup_buffer __infunc_pthread_cleanup_buffer; \ ++ if (C) { \ ++ _pthread_cleanup_push_defer(&__infunc_pthread_cleanup_buffer, \ ++ __pthread_mutex_unlock, \ ++ &(M)); \ ++ __pthread_mutex_lock(&(M)); \ ++ } \ ++ ((void)0) ++ ++#define __UCLIBC_MUTEX_CONDITIONAL_UNLOCK(M,C) \ ++ if (C) { \ ++ _pthread_cleanup_pop_restore(&__infunc_pthread_cleanup_buffer,1);\ ++ } \ ++ } while (0) ++ ++#define __UCLIBC_MUTEX_AUTO_LOCK_VAR(A) int A ++ ++#define __UCLIBC_MUTEX_AUTO_LOCK(M,A,V) \ ++ __UCLIBC_MUTEX_CONDITIONAL_LOCK(M,((A=(V)) == 0)) ++ ++#define __UCLIBC_MUTEX_AUTO_UNLOCK(M,A) \ ++ __UCLIBC_MUTEX_CONDITIONAL_UNLOCK(M,(A == 0)) ++ ++#define __UCLIBC_MUTEX_LOCK(M) \ ++ __UCLIBC_MUTEX_CONDITIONAL_LOCK(M, 1) ++ ++#define __UCLIBC_MUTEX_UNLOCK(M) \ ++ __UCLIBC_MUTEX_CONDITIONAL_UNLOCK(M, 1) ++ ++#else ++ ++#define __UCLIBC_MUTEX(M) void *__UCLIBC_MUTEX_DUMMY_ ## M ++#define __UCLIBC_MUTEX_INIT(M,I) extern void *__UCLIBC_MUTEX_DUMMY_ ## M ++#define __UCLIBC_MUTEX_STATIC(M) extern void *__UCLIBC_MUTEX_DUMMY_ ## M ++#define __UCLIBC_MUTEX_EXTERN(M) extern void *__UCLIBC_MUTEX_DUMMY_ ## M ++ ++#define __UCLIBC_MUTEX_LOCK_CANCEL_UNSAFE(M) ((void)0) ++#define __UCLIBC_MUTEX_UNLOCK_CANCEL_UNSAFE(M) ((void)0) ++#define __UCLIBC_MUTEX_TRYLOCK_CANCEL_UNSAFE(M) (0) /* Always succeed? */ ++ ++#define __UCLIBC_MUTEX_CONDITIONAL_LOCK(M,C) ((void)0) ++#define __UCLIBC_MUTEX_CONDITIONAL_UNLOCK(M,C) ((void)0) ++ ++#define __UCLIBC_MUTEX_AUTO_LOCK_VAR(A) ((void)0) ++#define __UCLIBC_MUTEX_AUTO_LOCK(M,A,V) ((void)0) ++#define __UCLIBC_MUTEX_AUTO_UNLOCK(M,A) ((void)0) ++ ++#define __UCLIBC_MUTEX_LOCK(M) ((void)0) ++#define __UCLIBC_MUTEX_UNLOCK(M) ((void)0) ++ ++#endif ++ ++#endif /* _UCLIBC_MUTEX_H */ +diff -urN -x .git uClibc-0.9.28/libc/sysdeps/linux/mips/pipe.c uClibc-mjn3/libc/sysdeps/linux/mips/pipe.c +--- uClibc-0.9.28/libc/sysdeps/linux/mips/pipe.c 2005-08-17 16:49:44.000000000 -0600 ++++ uClibc-mjn3/libc/sysdeps/linux/mips/pipe.c 1969-12-31 17:00:00.000000000 -0700 +@@ -1,23 +0,0 @@ +-/* pipe system call for Linux/MIPS */ +- +-/*see uClibc's sh/pipe.c and glibc-2.2.4's mips/pipe.S */ +- +-#include <errno.h> +-#include <unistd.h> +-#include <syscall.h> +- +-int pipe(int *fd) +-{ +- register long int res __asm__ ("$2"); // v0 +- register long int res2 __asm__ ("$3"); // v1 +- +- asm ("move\t$4,%2\n\t" // $4 = a0 +- "syscall" /* Perform the system call. */ +- : "=r" (res) +- : "0" (__NR_pipe), "r" (fd) +- : "$4", "$7"); +- +- fd[0] = res; +- fd[1] = res2; +- return(0); +-} |