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