diff options
author | Roger A. Faulkner <Roger.Faulkner@Oracle.COM> | 2010-04-03 09:48:44 -0700 |
---|---|---|
committer | Roger A. Faulkner <Roger.Faulkner@Oracle.COM> | 2010-04-03 09:48:44 -0700 |
commit | 3e14f97f673e8a630f076077de35afdd43dc1587 (patch) | |
tree | 9828b6b676f58d7b27dd28e00202d3f3461a5cd8 /usr/src/lib/libast/common/vmalloc/malloc.c | |
parent | 4f60987df4dcaa54a88b596f861fbf4f3382c65e (diff) | |
download | illumos-gate-3e14f97f673e8a630f076077de35afdd43dc1587.tar.gz |
6939349 RFE: Update ksh93 to ast-ksh.2010-03-09
6877392 ksh93 regresses 'uniq -c' performance
6887363 Korn shell 93 sometimes mishandles return value of its child process
6900314 (while true ; do true|true ; done) hang in ioctl() with SIGTTOU
6904557 wc no longer counts number of bytes correctly
6904575 cut -d with multibyte character no longer works
6904597 paste -d no longer works with multibyte characters
6904780 /usr/bin/cksum changed output in snv_128
6904870 uniq -s does not skip multibyte characters correctly
6904878 join -t no longer works with multibyte char separator
6907460 EXIT trap handlers are sometimes executed twice
6909579 libast getopt solaris compatibility broken
6920072 ksh93 tail -f, with unconditional .25s sleep and line parsing, about 37x slower than cat
6932124 mktemp in ksh93 is broken
Contributed by Olga Kryzhanovska <olga.kryzhanovska@gmail.com>
Diffstat (limited to 'usr/src/lib/libast/common/vmalloc/malloc.c')
-rw-r--r-- | usr/src/lib/libast/common/vmalloc/malloc.c | 611 |
1 files changed, 396 insertions, 215 deletions
diff --git a/usr/src/lib/libast/common/vmalloc/malloc.c b/usr/src/lib/libast/common/vmalloc/malloc.c index da4a839ecd..84f61120ad 100644 --- a/usr/src/lib/libast/common/vmalloc/malloc.c +++ b/usr/src/lib/libast/common/vmalloc/malloc.c @@ -1,7 +1,7 @@ /*********************************************************************** * * * This software is part of the ast package * -* Copyright (c) 1985-2009 AT&T Intellectual Property * +* Copyright (c) 1985-2010 AT&T Intellectual Property * * and is licensed under the * * Common Public License, Version 1.0 * * by AT&T Intellectual Property * @@ -88,21 +88,39 @@ typedef struct ______mstats Mstats_t; #define _AST_std_malloc 1 #endif -#if ( !_std_malloc || !_BLD_ast ) && !_AST_std_malloc - -/* malloc compatibility functions. -** These are aware of debugging/profiling and driven by the environment variables: -** VMETHOD: select an allocation method by name. +/* malloc compatibility functions +** +** These are aware of debugging/profiling and are driven by the +** VMALLOC_OPTIONS environment variable which is a space-separated +** list of [no]name[=value] options: ** -** VMPROFILE: if is a file name, write profile data to it. -** VMTRACE: if is a file name, write trace data to it. -** The pattern %p in a file name will be replaced by the process ID. +** abort if Vmregion==Vmdebug then VM_DBABORT is set, +** otherwise _BLD_debug enabled assertions abort() +** on failure +** check if Vmregion==Vmbest then the region is checked every op +** method=m sets Vmregion=m if not defined, m (Vm prefix optional) +** may be one of { best debug last profile } +** mmap prefer mmap() over brk() for region allocation +** period=n sets Vmregion=Vmdebug if not defined, if +** Vmregion==Vmdebug the region is checked every n ops +** profile=f sets Vmregion=Vmprofile if not set, if +** Vmregion==Vmprofile then profile info printed to file f +** region if Vmregion==Vmbest then block free verifies +** that the block belongs to the region +** start=n sets Vmregion=Vmdebug if not defined, if +** Vmregion==Vmdebug region checking starts after n ops +** trace=f enables tracing to file f +** warn=f sets Vmregion=Vmdebug if not defined, if +** Vmregion==Vmdebug then warnings printed to file f +** watch=a sets Vmregion=Vmdebug if not defined, if +** Vmregion==Vmdebug then address a is watched ** -** VMDEBUG: -** a: abort on any warning. -** w[decimal]: file descriptor for warnings. -** [decimal]: period to check arena. -** 0x[hexadecimal]: address to watch. +** Output files are created if they don't exist. &n and /dev/fd/n name +** the file descriptor n which must be open for writing. The pattern %p +** in a file name is replaced by the process ID. +** +** VMALLOC_OPTIONS combines the features of these previously used env vars: +** { VMDEBUG VMETHOD VMPROFILE VMTRACE } ** ** Written by Kiem-Phong Vo, kpv@research.att.com, 01/16/94. */ @@ -118,6 +136,13 @@ typedef struct ______mstats Mstats_t; #define CREAT_MODE 0644 #endif +static Vmulong_t _Vmdbstart = 0; +static Vmulong_t _Vmdbcheck = 0; +static Vmulong_t _Vmdbtime = 0; +static int _Vmpffd = -1; + +#if ( !_std_malloc || !_BLD_ast ) && !_AST_std_malloc + #if !_map_malloc #undef calloc #undef cfree @@ -182,44 +207,7 @@ lcl_getenv(const char* s) #define extern extern __EXPORT__ #endif -#if __STD_C -static Vmulong_t atou(char** sp) -#else -static Vmulong_t atou(sp) -char** sp; -#endif -{ - char* s = *sp; - Vmulong_t v = 0; - - if(s[0] == '0' && (s[1] == 'x' || s[1] == 'X') ) - { for(s += 2; *s; ++s) - { if(*s >= '0' && *s <= '9') - v = (v << 4) + (*s - '0'); - else if(*s >= 'a' && *s <= 'f') - v = (v << 4) + (*s - 'a') + 10; - else if(*s >= 'A' && *s <= 'F') - v = (v << 4) + (*s - 'A') + 10; - else break; - } - } - else - { for(; *s; ++s) - { if(*s >= '0' && *s <= '9') - v = v*10 + (*s - '0'); - else break; - } - } - - *sp = s; - return v; -} - static int _Vmflinit = 0; -static Vmulong_t _Vmdbstart = 0; -static Vmulong_t _Vmdbcheck = 0; -static Vmulong_t _Vmdbtime = 0; -static int _Vmpffd = -1; #define VMFLINIT() \ { if(!_Vmflinit) vmflinit(); \ if(_Vmdbcheck) \ @@ -232,99 +220,11 @@ static int _Vmpffd = -1; } #if __STD_C -static char* insertpid(char* begs, char* ends) -#else -static char* insertpid(begs,ends) -char* begs; -char* ends; -#endif -{ int pid; - char* s; - - if((pid = getpid()) < 0) - return NIL(char*); - - s = ends; - do - { if(s == begs) - return NIL(char*); - *--s = '0' + pid%10; - } while((pid /= 10) > 0); - while(s < ends) - *begs++ = *s++; - - return begs; -} - -#if __STD_C -static int createfile(char* file) -#else -static int createfile(file) -char* file; -#endif -{ - char buf[1024]; - char *next, *endb; - - next = buf; - endb = buf + sizeof(buf); - while(*file) - { if(*file == '%') - { switch(file[1]) - { - case 'p' : - if(!(next = insertpid(next,endb)) ) - return -1; - file += 2; - break; - default : - goto copy; - } - } - else - { copy: - *next++ = *file++; - } - - if(next >= endb) - return -1; - } - - *next = '\0'; -#if _PACKAGE_ast - { int fd; - fd = open(buf,O_WRONLY|O_CREAT|O_TRUNC,CREAT_MODE); -#ifdef FD_CLOEXEC - if (fd >= 0) - fcntl(fd, F_SETFD, FD_CLOEXEC); -#endif - return fd; - } -#else - return creat(buf,CREAT_MODE); -#endif -} - -#if __STD_C -static void pfprint(void) -#else -static void pfprint() -#endif -{ - if(Vmregion->meth.meth == VM_MTPROFILE) - vmprofile(Vmregion,_Vmpffd); -} - -#if __STD_C static int vmflinit(void) #else static int vmflinit() #endif { - char* env; - Vmalloc_t* vm; - int fd; - Vmulong_t addr; char* file; int line; Void_t* func; @@ -333,82 +233,8 @@ static int vmflinit() _Vmflinit = 1; VMFLF(Vmregion,file,line,func); - /* if getenv() calls malloc(), the eventual region may not see this */ - vm = NIL(Vmalloc_t*); - if((env = getenv("VMETHOD")) ) - { if(strcmp(env,"Vmdebug") == 0 || strcmp(env,"vmdebug") == 0) - vm = vmopen(Vmdcsbrk,Vmdebug,0); - else if(strcmp(env,"Vmprofile") == 0 || strcmp(env,"vmprofile") == 0 ) - vm = vmopen(Vmdcsbrk,Vmprofile,0); - else if(strcmp(env,"Vmlast") == 0 || strcmp(env,"vmlast") == 0 ) - vm = vmopen(Vmdcsbrk,Vmlast,0); - else if(strcmp(env,"Vmbest") == 0 || strcmp(env,"vmbest") == 0 ) - vm = Vmheap; - } - - if((!vm || vm->meth.meth == VM_MTDEBUG) && - (env = getenv("VMDEBUG")) && env[0] ) - { if(vm || (vm = vmopen(Vmdcsbrk,Vmdebug,0)) ) - { reg int setcheck = 0; - - while(*env) - { if(*env == 'a') - { vmset(vm,VM_DBABORT,1); - env += 1; - } - else if(*env =='w') - { env += 1; - if((fd = atou(&env)) >= 0 ) - vmdebug(fd); - } - else if(*env < '0' || *env > '9') - env += 1; - else if(env[0] == '0' && (env[1] == 'x' || env[1] == 'X') ) - { if((addr = atou(&env)) != 0) - vmdbwatch((Void_t*)addr); - } - else - { _Vmdbcheck = atou(&env); - setcheck = 1; - if(*env == ',') - { env += 1; - _Vmdbstart = atou(&env); - } - } - } - if(!setcheck) - _Vmdbcheck = 1; - } - } - - if((!vm || vm->meth.meth == VM_MTPROFILE) && - (env = getenv("VMPROFILE")) && env[0] ) - { _Vmpffd = createfile(env); - if(!vm) - vm = vmopen(Vmdcsbrk,Vmprofile,0); - } - - /* slip in the new region now so that malloc() will work fine */ - if(vm) - Vmregion = vm; - - /* turn on tracing if requested */ - if((env = getenv("VMTRACE")) && env[0] && (fd = createfile(env)) >= 0) - { vmset(Vmregion,VM_TRACE,1); - vmtrace(fd); - } - - /* make sure that profile data is output upon exiting */ - if(vm && vm->meth.meth == VM_MTPROFILE) - { if(_Vmpffd < 0) - _Vmpffd = 2; - /* this may wind up calling malloc(), but region is ok now */ - atexit(pfprint); - } - else if(_Vmpffd >= 0) - { close(_Vmpffd); - _Vmpffd = -1; - } + /* if getenv() calls malloc(), the options may not affect the eventual region */ + VMOPTIONS(); /* reset file and line number to correct values for the call */ Vmregion->file = file; @@ -938,4 +764,359 @@ extern Mstats_t F0(_ast_mstats, void) { return mstats(); } #endif /*!_std_malloc*/ +#if __STD_C +static Vmulong_t atou(char** sp) +#else +static Vmulong_t atou(sp) +char** sp; +#endif +{ + char* s = *sp; + Vmulong_t v = 0; + + if(s[0] == '0' && (s[1] == 'x' || s[1] == 'X') ) + { for(s += 2; *s; ++s) + { if(*s >= '0' && *s <= '9') + v = (v << 4) + (*s - '0'); + else if(*s >= 'a' && *s <= 'f') + v = (v << 4) + (*s - 'a') + 10; + else if(*s >= 'A' && *s <= 'F') + v = (v << 4) + (*s - 'A') + 10; + else break; + } + } + else + { for(; *s; ++s) + { if(*s >= '0' && *s <= '9') + v = v*10 + (*s - '0'); + else break; + } + } + + *sp = s; + return v; +} + +#if __STD_C +static char* insertpid(char* begs, char* ends) +#else +static char* insertpid(begs,ends) +char* begs; +char* ends; +#endif +{ int pid; + char* s; + + if((pid = getpid()) < 0) + return NIL(char*); + + s = ends; + do + { if(s == begs) + return NIL(char*); + *--s = '0' + pid%10; + } while((pid /= 10) > 0); + while(s < ends) + *begs++ = *s++; + + return begs; +} + +#if __STD_C +static int createfile(char* file) +#else +static int createfile(file) +char* file; +#endif +{ + char buf[1024]; + char *next, *endb; + int fd; + + next = buf; + endb = buf + sizeof(buf); + while(*file) + { if(*file == '%') + { switch(file[1]) + { + case 'p' : + if(!(next = insertpid(next,endb)) ) + return -1; + file += 2; + break; + default : + goto copy; + } + } + else + { copy: + *next++ = *file++; + } + + if(next >= endb) + return -1; + } + + *next = '\0'; + file = buf; + if (*file == '&' && *(file += 1) || strncmp(file, "/dev/fd/", 8) == 0 && *(file += 8)) + fd = dup((int)atou(&file)); + else if (*file) +#if _PACKAGE_ast + fd = open(file, O_WRONLY|O_CREAT|O_TRUNC, CREAT_MODE); +#else + fd = creat(file, CREAT_MODE); +#endif + else + return -1; +#if _PACKAGE_ast +#ifdef FD_CLOEXEC + if (fd >= 0) + fcntl(fd, F_SETFD, FD_CLOEXEC); +#endif +#endif + return fd; +} + +#if __STD_C +static void pfprint(void) +#else +static void pfprint() +#endif +{ + if(Vmregion->meth.meth == VM_MTPROFILE) + vmprofile(Vmregion,_Vmpffd); +} + +/* + * initialize runtime options from the VMALLOC_OPTIONS env var + */ + +#define COPY(t,e,f) while ((*t = *f++) && t < e) t++ + +#if __STD_C +void _vmoptions(void) +#else +void _vmoptions() +#endif +{ + Vmalloc_t* vm = 0; + char* trace = 0; + char* s; + char* t; + char* v; + Vmulong_t n; + int fd; + char buf[1024]; + + _Vmoptions = 1; + t = buf; + v = &buf[sizeof(buf)-1]; + if (s = getenv("VMALLOC_OPTIONS")) + COPY(t, v, s); +#if 1 /* backwards compatibility until 2011 */ + else + { + char* p; + + if (s = getenv("VMDEBUG")) + { + switch (*s++) + { + case 0: + break; + case 'a': + p = " abort"; + COPY(t, v, p); + break; + case 'w': + p = " warn"; + COPY(t, v, p); + break; + case '0': + if (*s-- == 'x') + { + p = " watch="; + COPY(t, v, p); + COPY(t, v, s); + break; + } + /*FALLTHROUGH*/ + default: + p = " period="; + COPY(t, v, p); + COPY(t, v, s); + break; + } + } + if ((s = getenv("VMETHOD")) && *s) + { + p = " method="; + COPY(t, v, p); + COPY(t, v, s); + } + if ((s = getenv("VMPROFILE")) && *s) + { + p = " profile="; + COPY(t, v, p); + COPY(t, v, s); + } + if ((s = getenv("VMTRACE")) && *s) + { + p = " trace="; + COPY(t, v, p); + COPY(t, v, s); + } + } +#endif + if (t > buf) + { + *t = 0; + s = buf; + for (;;) + { + while (*s == ' ' || *s == '\t' || *s == '\r' || *s == '\n') + s++; + if (!*(t = s)) + break; + v = 0; + while (*s) + if (*s == ' ' || *s == '\t' || *s == '\r' || *s == '\n') + { + *s++ = 0; + break; + } + else if (!v && *s == '=') + { + *s++ = 0; + if (!*(v = s)) + v = 0; + } + else + s++; + if (t[0] == 'n' && t[1] == 'o') + continue; + switch (t[0]) + { + case 'a': /* abort */ + if (!vm) + vm = vmopen(Vmdcsbrk, Vmdebug, 0); + if (vm && vm->meth.meth == VM_MTDEBUG) + vmset(vm, VM_DBABORT, 1); + else + _Vmassert |= VM_abort; + break; + case 'c': /* check */ + _Vmassert |= VM_check; + break; + case 'm': + switch (t[1]) + { + case 'e': /* method=<method> */ + if (v && !vm) + { + if ((v[0] == 'V' || v[0] == 'v') && (v[1] == 'M' || v[1] == 'm')) + v += 2; + if (strcmp(v, "debug") == 0) + vm = vmopen(Vmdcsbrk, Vmdebug, 0); + else if (strcmp(v, "profile") == 0) + vm = vmopen(Vmdcsbrk, Vmprofile, 0); + else if (strcmp(v, "last") == 0) + vm = vmopen(Vmdcsbrk, Vmlast, 0); + else if (strcmp(v, "best") == 0) + vm = Vmheap; + } + break; + case 'm': /* mmap */ +#if _mem_mmap_anon || _mem_mmap_zero + _Vmassert |= VM_mmap; +#endif + break; + } + break; + case 'p': + if (v) + switch (t[1]) + { + case 'e': /* period=<count> */ + if (!vm) + vm = vmopen(Vmdcsbrk, Vmdebug, 0); + if (vm && vm->meth.meth == VM_MTDEBUG) + _Vmdbcheck = atou(&v); + break; + case 'r': /* profile=<path> */ + if (!vm) + vm = vmopen(Vmdcsbrk, Vmprofile, 0); + if (v && vm && vm->meth.meth == VM_MTPROFILE) + _Vmpffd = createfile(v); + break; + } + break; + case 'r': /* region */ + _Vmassert |= VM_region; + break; + case 's': /* start=<count> */ + if (!vm) + vm = vmopen(Vmdcsbrk, Vmdebug, 0); + if (v && vm && vm->meth.meth == VM_MTDEBUG) + _Vmdbstart = atou(&v); + break; + case 't': /* trace=<path> */ + trace = v; + break; + case 'w': + if (t[1] == 'a') + switch (t[2]) + { + case 'r': /* warn=<path> */ + if (!vm) + vm = vmopen(Vmdcsbrk, Vmdebug, 0); + if (v && vm && vm->meth.meth == VM_MTDEBUG && (fd = createfile(v)) >= 0) + vmdebug(fd); + break; + case 't': /* watch=<addr> */ + if (!vm) + vm = vmopen(Vmdcsbrk, Vmdebug, 0); + if (v && vm && vm->meth.meth == VM_MTDEBUG && (n = atou(&v)) >= 0) + vmdbwatch((Void_t*)n); + break; + } + break; + } + } + } + + /* slip in the new region now so that malloc() will work fine */ + + if (vm) + { + if (vm->meth.meth == VM_MTDEBUG) + _Vmdbcheck = 1; + Vmregion = vm; + } + + /* enable tracing */ + + if (trace && (fd = createfile(trace)) >= 0) + { + vmset(Vmregion, VM_TRACE, 1); + vmtrace(fd); + } + + /* make sure that profile data is output upon exiting */ + + if (vm && vm->meth.meth == VM_MTPROFILE) + { + if (_Vmpffd < 0) + _Vmpffd = 2; + /* this may wind up calling malloc(), but region is ok now */ + atexit(pfprint); + } + else if (_Vmpffd >= 0) + { + close(_Vmpffd); + _Vmpffd = -1; + } +} + #endif /*_UWIN*/ |