This commit is contained in:
parent
dc83cf7bf4
commit
c1b41c7ae5
@ -439,3 +439,347 @@
|
||||
closesocket(s); /* don't care about the result */
|
||||
#else
|
||||
if(s_socketpair(AF_UNIX, SOCK_STREAM, 0, fd, 1, "socketpair"))
|
||||
--- src/str.c 2011-05-02 19:14:53.000000000 +0200
|
||||
+++ src/str.c 2011-05-08 08:37:57.000000000 +0200
|
||||
@@ -38,17 +38,128 @@
|
||||
#include "common.h"
|
||||
#include "prototypes.h"
|
||||
|
||||
-typedef struct str_struct {
|
||||
- struct str_struct *prev, *next;
|
||||
+#ifndef va_copy
|
||||
+#ifdef __va_copy
|
||||
+#define va_copy(dst, src) __va_copy((dst), (src))
|
||||
+#else /* __va_copy */
|
||||
+#define va_copy(dst, src) memcpy(&(dst), &(src), sizeof(va_list))
|
||||
+#endif /* __va_copy */
|
||||
+#endif /* va_copy */
|
||||
+
|
||||
+typedef struct alloc_list {
|
||||
+ struct alloc_list *prev, *next;
|
||||
size_t size;
|
||||
unsigned int magic;
|
||||
-} STR;
|
||||
-static void str_set(STR *);
|
||||
-static STR *str_get();
|
||||
+} ALLOC_LIST;
|
||||
+
|
||||
+static void set_alloc_head(ALLOC_LIST *);
|
||||
+static ALLOC_LIST *get_alloc_head();
|
||||
+
|
||||
+char *str_dup(const char *str) {
|
||||
+ char *retval;
|
||||
+
|
||||
+ retval=str_alloc(strlen(str)+1);
|
||||
+ if(retval)
|
||||
+ strcpy(retval, str);
|
||||
+ return retval;
|
||||
+}
|
||||
+
|
||||
+char *str_printf(const char *format, ...) {
|
||||
+ char *txt;
|
||||
+ va_list arglist;
|
||||
+
|
||||
+ va_start(arglist, format);
|
||||
+ txt=str_vprintf(format, arglist);
|
||||
+ va_end(arglist);
|
||||
+ return txt;
|
||||
+}
|
||||
+
|
||||
+char *str_vprintf(const char *format, va_list start_ap) {
|
||||
+ int n, size=64;
|
||||
+ char *p, *np;
|
||||
+ va_list ap;
|
||||
+
|
||||
+ p=str_alloc(size);
|
||||
+ if(!p)
|
||||
+ return NULL;
|
||||
+ for(;;) {
|
||||
+ va_copy(ap, start_ap);
|
||||
+ n=vsnprintf(p, size, format, ap);
|
||||
+ if(n>-1 && n<size)
|
||||
+ return p;
|
||||
+ if(n>-1) /* glibc 2.1 */
|
||||
+ size=n+1; /* precisely what is needed */
|
||||
+ else /* glibc 2.0, WIN32, etc. */
|
||||
+ size*=2; /* twice the old size */
|
||||
+ np=str_realloc(p, size);
|
||||
+ if(!np) {
|
||||
+ str_free(p);
|
||||
+ return NULL;
|
||||
+ }
|
||||
+ p=np; /* LOL */
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+#ifdef USE_UCONTEXT
|
||||
+
|
||||
+static ALLOC_LIST *alloc_tls=NULL;
|
||||
+
|
||||
+void str_init() {
|
||||
+}
|
||||
+
|
||||
+static void set_alloc_head(ALLOC_LIST *alloc_head) {
|
||||
+ if(ready_head)
|
||||
+ ready_head->tls=alloc_head;
|
||||
+ else /* ucontext threads not initialized */
|
||||
+ alloc_tls=alloc_head;
|
||||
+}
|
||||
+
|
||||
+static ALLOC_LIST *get_alloc_head() {
|
||||
+ if(ready_head)
|
||||
+ return ready_head->tls;
|
||||
+ else /* ucontext threads not initialized */
|
||||
+ return alloc_tls;
|
||||
+}
|
||||
+
|
||||
+#endif /* USE_UCONTEXT */
|
||||
+
|
||||
+#ifdef USE_FORK
|
||||
+
|
||||
+static ALLOC_LIST *alloc_tls=NULL;
|
||||
+
|
||||
+void str_init() {
|
||||
+}
|
||||
+
|
||||
+static void set_alloc_head(ALLOC_LIST *alloc_head) {
|
||||
+ alloc_tls=alloc_head;
|
||||
+}
|
||||
+
|
||||
+static ALLOC_LIST *get_alloc_head() {
|
||||
+ return alloc_tls;
|
||||
+}
|
||||
+
|
||||
+#endif /* USE_FORK */
|
||||
+
|
||||
+#ifdef USE_PTHREAD
|
||||
+
|
||||
+static pthread_key_t pthread_key;
|
||||
+
|
||||
+void str_init() {
|
||||
+ pthread_key_create(&pthread_key, NULL);
|
||||
+}
|
||||
+
|
||||
+static void set_alloc_head(ALLOC_LIST *alloc_head) {
|
||||
+ pthread_setspecific(pthread_key, alloc_head);
|
||||
+}
|
||||
+
|
||||
+static ALLOC_LIST *get_alloc_head() {
|
||||
+ return pthread_getspecific(pthread_key);
|
||||
+}
|
||||
+
|
||||
+#endif /* USE_PTHREAD */
|
||||
|
||||
#ifdef USE_WIN32
|
||||
|
||||
-/* __thread does not work in mingw32 due to a bug in GCC */
|
||||
static DWORD tls_index;
|
||||
|
||||
void str_init() {
|
||||
@@ -59,97 +170,81 @@
|
||||
}
|
||||
}
|
||||
|
||||
-static void str_set(STR *str) {
|
||||
- if(!TlsSetValue(tls_index, str)) {
|
||||
+static void set_alloc_head(ALLOC_LIST *alloc_head) {
|
||||
+ if(!TlsSetValue(tls_index, alloc_head)) {
|
||||
s_log(LOG_ERR, "TlsSetValue failed");
|
||||
die(1);
|
||||
}
|
||||
}
|
||||
|
||||
-static STR *str_get() {
|
||||
- STR *str;
|
||||
+static ALLOC_LIST *get_alloc_head() {
|
||||
+ ALLOC_LIST *alloc_head;
|
||||
|
||||
- str=TlsGetValue(tls_index);
|
||||
- if(!str && GetLastError()!=ERROR_SUCCESS) {
|
||||
+ alloc_head=TlsGetValue(tls_index);
|
||||
+ if(!alloc_head && GetLastError()!=ERROR_SUCCESS) {
|
||||
s_log(LOG_ERR, "TlsGetValue failed");
|
||||
die(1);
|
||||
}
|
||||
- return str;
|
||||
-}
|
||||
-
|
||||
-#else
|
||||
-
|
||||
-/* gcc Thread-Local Storage */
|
||||
-static __thread STR *root_str=NULL;
|
||||
-
|
||||
-void str_init() {
|
||||
- if(root_str)
|
||||
- s_log(LOG_WARNING, "str_init: Non-empty allocation list");
|
||||
+ return alloc_head;
|
||||
}
|
||||
|
||||
-static void str_set(STR *str) {
|
||||
- root_str=str;
|
||||
-}
|
||||
-
|
||||
-static STR *str_get() {
|
||||
- return root_str;
|
||||
-}
|
||||
-
|
||||
-#endif
|
||||
+#endif /* USE_WIN32 */
|
||||
|
||||
void str_cleanup() {
|
||||
- STR *str, *tmp;
|
||||
+ ALLOC_LIST *alloc_head, *tmp;
|
||||
|
||||
- str=str_get();
|
||||
- while(str) {
|
||||
- tmp=str;
|
||||
- str=tmp->next;
|
||||
+ alloc_head=get_alloc_head();
|
||||
+ while(alloc_head) {
|
||||
+ tmp=alloc_head;
|
||||
+ alloc_head=tmp->next;
|
||||
free(tmp);
|
||||
}
|
||||
- str_set(NULL);
|
||||
+ set_alloc_head(NULL);
|
||||
}
|
||||
|
||||
void str_stats() {
|
||||
- STR *tmp;
|
||||
+ ALLOC_LIST *tmp;
|
||||
int blocks=0, bytes=0;
|
||||
|
||||
- for(tmp=str_get(); tmp; tmp=tmp->next) {
|
||||
+ for(tmp=get_alloc_head(); tmp; tmp=tmp->next) {
|
||||
++blocks;
|
||||
bytes+=tmp->size;
|
||||
}
|
||||
- s_log(LOG_DEBUG, "str_stats: %d blocks, %d bytes", blocks, bytes);
|
||||
+ s_log(LOG_DEBUG, "str_stats: %d block(s), %d byte(s)", blocks, bytes);
|
||||
}
|
||||
|
||||
void *str_alloc(size_t size) {
|
||||
- STR *str, *tmp;
|
||||
+ ALLOC_LIST *alloc_head, *tmp;
|
||||
|
||||
if(size>=1024*1024) /* huge allocations are not allowed */
|
||||
return NULL;
|
||||
- tmp=calloc(1, sizeof(STR)+size);
|
||||
+ tmp=calloc(1, sizeof(ALLOC_LIST)+size);
|
||||
if(!tmp)
|
||||
return NULL;
|
||||
- str=str_get();
|
||||
+ alloc_head=get_alloc_head();
|
||||
tmp->prev=NULL;
|
||||
- tmp->next=str;
|
||||
+ tmp->next=alloc_head;
|
||||
tmp->size=size;
|
||||
tmp->magic=0xdeadbeef;
|
||||
- if(str)
|
||||
- str->prev=tmp;
|
||||
- str_set(tmp);
|
||||
+ if(alloc_head)
|
||||
+ alloc_head->prev=tmp;
|
||||
+ set_alloc_head(tmp);
|
||||
return tmp+1;
|
||||
}
|
||||
|
||||
void *str_realloc(void *ptr, size_t size) {
|
||||
- STR *oldtmp, *tmp;
|
||||
+ ALLOC_LIST *old_tmp, *tmp;
|
||||
|
||||
if(!ptr)
|
||||
return str_alloc(size);
|
||||
- oldtmp=(STR *)ptr-1;
|
||||
- if(oldtmp->magic!=0xdeadbeef) { /* not allocated by str_alloc() */
|
||||
+ old_tmp=(ALLOC_LIST *)ptr-1;
|
||||
+ if(old_tmp->magic!=0xdeadbeef) { /* not allocated by str_alloc() */
|
||||
s_log(LOG_CRIT, "INTERNAL ERROR: str_realloc: Bad magic");
|
||||
die(1);
|
||||
}
|
||||
- tmp=realloc(oldtmp, sizeof(STR)+size);
|
||||
+ if(size>=1024*1024) /* huge allocations are not allowed */
|
||||
+ return NULL;
|
||||
+ tmp=realloc(old_tmp, sizeof(ALLOC_LIST)+size);
|
||||
if(!tmp)
|
||||
return NULL;
|
||||
/* refresh all possibly invalidated pointers */
|
||||
@@ -158,17 +253,17 @@
|
||||
if(tmp->prev)
|
||||
tmp->prev->next=tmp;
|
||||
tmp->size=size;
|
||||
- if(str_get()==oldtmp)
|
||||
- str_set(tmp);
|
||||
+ if(get_alloc_head()==old_tmp)
|
||||
+ set_alloc_head(tmp);
|
||||
return tmp+1;
|
||||
}
|
||||
|
||||
void str_free(void *ptr) {
|
||||
- STR *tmp;
|
||||
+ ALLOC_LIST *tmp;
|
||||
|
||||
if(!ptr) /* do not attempt to free null pointers */
|
||||
return;
|
||||
- tmp=(STR *)ptr-1;
|
||||
+ tmp=(ALLOC_LIST *)ptr-1;
|
||||
if(tmp->magic!=0xdeadbeef) { /* not allocated by str_alloc() */
|
||||
s_log(LOG_CRIT, "INTERNAL ERROR: str_free: Bad magic");
|
||||
die(1);
|
||||
@@ -178,54 +273,9 @@
|
||||
tmp->next->prev=tmp->prev;
|
||||
if(tmp->prev)
|
||||
tmp->prev->next=tmp->next;
|
||||
- if(str_get()==tmp)
|
||||
- str_set(tmp->next);
|
||||
+ if(get_alloc_head()==tmp)
|
||||
+ set_alloc_head(tmp->next);
|
||||
free(tmp);
|
||||
}
|
||||
|
||||
-char *str_dup(const char *str) {
|
||||
- char *retval;
|
||||
-
|
||||
- retval=str_alloc(strlen(str)+1);
|
||||
- if(retval)
|
||||
- strcpy(retval, str);
|
||||
- return retval;
|
||||
-}
|
||||
-
|
||||
-char *str_vprintf(const char *format, va_list start_ap) {
|
||||
- int n, size=64;
|
||||
- char *p, *np;
|
||||
- va_list ap;
|
||||
-
|
||||
- p=str_alloc(size);
|
||||
- if(!p)
|
||||
- return NULL;
|
||||
- for(;;) {
|
||||
- va_copy(ap, start_ap);
|
||||
- n=vsnprintf(p, size, format, ap);
|
||||
- if(n>-1 && n<size)
|
||||
- return p;
|
||||
- if(n>-1) /* glibc 2.1 */
|
||||
- size=n+1; /* precisely what is needed */
|
||||
- else /* glibc 2.0 */
|
||||
- size*=2; /* twice the old size */
|
||||
- np=str_realloc(p, size);
|
||||
- if(!np) {
|
||||
- str_free(p);
|
||||
- return NULL;
|
||||
- }
|
||||
- p=np; /* LOL */
|
||||
- }
|
||||
-}
|
||||
-
|
||||
-char *str_printf(const char *format, ...) {
|
||||
- char *txt;
|
||||
- va_list arglist;
|
||||
-
|
||||
- va_start(arglist, format);
|
||||
- txt=str_vprintf(format, arglist);
|
||||
- va_end(arglist);
|
||||
- return txt;
|
||||
-}
|
||||
-
|
||||
/* end of str.c */
|
||||
|
Loading…
x
Reference in New Issue
Block a user