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 #include +#include -#ifdef __UCLIBC_HAS_THREADS__ -#include -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 #include -#ifdef __UCLIBC_HAS_THREADS__ -#include -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 +__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 #include +#include - -#ifdef __UCLIBC_HAS_THREADS__ -#include -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 #include +#include + +__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 -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;jbuf; - 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:"", class, type); + name, domain?domain:"", 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 -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 #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 #include -#ifdef __UCLIBC_HAS_THREADS__ -#include -#endif + +#include /* 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 #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 #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 #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 #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 #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 #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 #include -#ifdef __UCLIBC_HAS_THREADS__ -#include -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 + +__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 #include +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 #include +#include -#ifdef __UCLIBC_HAS_THREADS__ -#include -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 #include +#include + #ifdef __UCLIBC_HAS_XLOCALE__ #include #endif @@ -191,21 +193,7 @@ typedef struct { char tzname[TZNAME_MAX+1]; } rule_struct; -#ifdef __UCLIBC_HAS_THREADS__ - -#include - -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 #include #include -#ifdef __UCLIBC_HAS_THREADS__ -#include -#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 #include +#include - -#ifdef __UCLIBC_HAS_THREADS__ -#include -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 @@ -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 #include -#ifdef __UCLIBC_HAS_THREADS__ -#include -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 + +__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 #include #include -#ifdef __UCLIBC_HAS_THREADS__ -#include -#endif + +#include /**********************************************************************/ /* 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 -#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 #endif -#ifdef __UCLIBC_HAS_THREADS__ -#include +#include -#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 #include @@ -21,6 +22,8 @@ #include #include +#include + /* uClinux-2.0 has vfork, but Linux 2.0 doesn't */ #include #if ! defined __NR_vfork @@ -29,19 +32,11 @@ # define VFORK_UNLOCK ((void) 0) #endif -#ifdef __UCLIBC_HAS_THREADS__ -#include -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 -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 +__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 #include +#include -#ifdef __UCLIBC_HAS_THREADS__ -#include -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_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 + +__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 @@ -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 @@ -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 @@ -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 @@ -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 #include +#include -#ifdef __UCLIBC_HAS_THREADS__ -#include -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 @@ -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 @@ -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 @@ -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 #include #include -#ifdef __UCLIBC_HAS_THREADS__ -#include + /* 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 + +__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 - */ +*/ #define _GNU_SOURCE #include @@ -26,16 +26,9 @@ #include #include -#ifdef __UCLIBC_HAS_THREADS__ -#include -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 +__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 +#include /* 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 -#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 #include - .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 + +__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 + * + * 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 + +#ifdef __UCLIBC_HAS_THREADS__ + +#include + +#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 -#include -#include - -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); -}