diff options
| author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2002-11-18 13:24:27 -0200 |
|---|---|---|
| committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2002-11-18 13:24:27 -0200 |
| commit | f0185f762840cdf80cc81b0c3e67e306e015f1f3 (patch) | |
| tree | 6aeee336d213dfbe8171b398ac3ee648d82e8659 | |
| parent | 9bab2cf55d9b151d730c1461e3882a5fbc7d790d (diff) | |
| download | lua-f0185f762840cdf80cc81b0c3e67e306e015f1f3.tar.gz lua-f0185f762840cdf80cc81b0c3e67e306e015f1f3.tar.bz2 lua-f0185f762840cdf80cc81b0c3e67e306e015f1f3.zip | |
support for tests of yield inside hooks + better support for tests
with valgrind and other memory checkers
| -rw-r--r-- | ltests.c | 97 |
1 files changed, 75 insertions, 22 deletions
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: ltests.c,v 1.143 2002/11/14 15:41:38 roberto Exp roberto $ | 2 | ** $Id: ltests.c,v 1.144 2002/11/14 16:59:16 roberto Exp roberto $ |
| 3 | ** Internal Module for Debugging of the Lua Implementation | 3 | ** Internal Module for Debugging of the Lua Implementation |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -56,15 +56,25 @@ static void setnameval (lua_State *L, const char *name, int val) { | |||
| 56 | ** ======================================================================= | 56 | ** ======================================================================= |
| 57 | */ | 57 | */ |
| 58 | 58 | ||
| 59 | |||
| 60 | /* ensures maximum alignment for HEADER */ | ||
| 61 | #define HEADER (sizeof(L_Umaxalign)) | ||
| 62 | |||
| 63 | #define MARKSIZE 8 | ||
| 64 | #define MARK 0x55 /* 01010101 (a nice pattern) */ | 59 | #define MARK 0x55 /* 01010101 (a nice pattern) */ |
| 65 | 60 | ||
| 66 | 61 | #ifndef EXTERNMEMCHECK | |
| 67 | #define blocksize(b) (cast(size_t *, cast(char *, b) - HEADER)) | 62 | /* full memory check */ |
| 63 | #define HEADER (sizeof(L_Umaxalign)) /* ensures maximum alignment for HEADER */ | ||
| 64 | #define MARKSIZE 16 /* size of marks after each block */ | ||
| 65 | #define blockhead(b) (cast(char *, b) - HEADER) | ||
| 66 | #define setsize(newblock, size) (*cast(size_t *, newblock) = size) | ||
| 67 | #define checkblocksize(b, size) (size == (*cast(size_t *, blockhead(b)))) | ||
| 68 | #define fillmem(mem,size) memset(mem, -MARK, size) | ||
| 69 | #else | ||
| 70 | /* external memory check: don't do it twice */ | ||
| 71 | #define HEADER 0 | ||
| 72 | #define MARKSIZE 0 | ||
| 73 | #define blockhead(b) (b) | ||
| 74 | #define setsize(newblock, size) /* empty */ | ||
| 75 | #define checkblocksize(b,size) (1) | ||
| 76 | #define fillmem(mem,size) /* empty */ | ||
| 77 | #endif | ||
| 68 | 78 | ||
| 69 | unsigned long memdebug_numblocks = 0; | 79 | unsigned long memdebug_numblocks = 0; |
| 70 | unsigned long memdebug_total = 0; | 80 | unsigned long memdebug_total = 0; |
| @@ -72,9 +82,8 @@ unsigned long memdebug_maxmem = 0; | |||
| 72 | unsigned long memdebug_memlimit = ULONG_MAX; | 82 | unsigned long memdebug_memlimit = ULONG_MAX; |
| 73 | 83 | ||
| 74 | 84 | ||
| 75 | static void *checkblock (void *block) { | 85 | static void *checkblock (void *block, size_t size) { |
| 76 | size_t *b = blocksize(block); | 86 | void *b = blockhead(block); |
| 77 | size_t size = *b; | ||
| 78 | int i; | 87 | int i; |
| 79 | for (i=0;i<MARKSIZE;i++) | 88 | for (i=0;i<MARKSIZE;i++) |
| 80 | lua_assert(*(cast(char *, b)+HEADER+size+i) == MARK+i); /* corrupted block? */ | 89 | lua_assert(*(cast(char *, b)+HEADER+size+i) == MARK+i); /* corrupted block? */ |
| @@ -82,11 +91,11 @@ static void *checkblock (void *block) { | |||
| 82 | } | 91 | } |
| 83 | 92 | ||
| 84 | 93 | ||
| 85 | static void freeblock (void *block) { | 94 | static void freeblock (void *block, size_t size) { |
| 86 | if (block) { | 95 | if (block) { |
| 87 | size_t size = *blocksize(block); | 96 | lua_assert(checkblocksize(block, size)); |
| 88 | block = checkblock(block); | 97 | block = checkblock(block, size); |
| 89 | memset(block, -1, size+HEADER+MARKSIZE); /* erase block */ | 98 | fillmem(block, size+HEADER+MARKSIZE); /* erase block */ |
| 90 | free(block); /* free original block */ | 99 | free(block); /* free original block */ |
| 91 | memdebug_numblocks--; | 100 | memdebug_numblocks--; |
| 92 | memdebug_total -= size; | 101 | memdebug_total -= size; |
| @@ -95,11 +104,11 @@ static void freeblock (void *block) { | |||
| 95 | 104 | ||
| 96 | 105 | ||
| 97 | void *debug_realloc (void *block, size_t oldsize, size_t size) { | 106 | void *debug_realloc (void *block, size_t oldsize, size_t size) { |
| 98 | lua_assert(oldsize == 0 || oldsize == *blocksize(block)); | 107 | lua_assert(oldsize == 0 || checkblocksize(block, oldsize)); |
| 99 | /* ISO does not specify what realloc(NULL, 0) does */ | 108 | /* ISO does not specify what realloc(NULL, 0) does */ |
| 100 | lua_assert(block != NULL || size > 0); | 109 | lua_assert(block != NULL || size > 0); |
| 101 | if (size == 0) { | 110 | if (size == 0) { |
| 102 | freeblock(block); | 111 | freeblock(block, oldsize); |
| 103 | return NULL; | 112 | return NULL; |
| 104 | } | 113 | } |
| 105 | else if (size > oldsize && memdebug_total+size-oldsize > memdebug_memlimit) | 114 | else if (size > oldsize && memdebug_total+size-oldsize > memdebug_memlimit) |
| @@ -108,21 +117,21 @@ void *debug_realloc (void *block, size_t oldsize, size_t size) { | |||
| 108 | void *newblock; | 117 | void *newblock; |
| 109 | int i; | 118 | int i; |
| 110 | size_t realsize = HEADER+size+MARKSIZE; | 119 | size_t realsize = HEADER+size+MARKSIZE; |
| 120 | size_t commonsize = (oldsize < size) ? oldsize : size; | ||
| 111 | if (realsize < size) return NULL; /* overflow! */ | 121 | if (realsize < size) return NULL; /* overflow! */ |
| 112 | newblock = malloc(realsize); /* alloc a new block */ | 122 | newblock = malloc(realsize); /* alloc a new block */ |
| 113 | if (newblock == NULL) return NULL; | 123 | if (newblock == NULL) return NULL; |
| 114 | if (oldsize > size) oldsize = size; | ||
| 115 | if (block) { | 124 | if (block) { |
| 116 | memcpy(cast(char *, newblock)+HEADER, block, oldsize); | 125 | memcpy(cast(char *, newblock)+HEADER, block, commonsize); |
| 117 | freeblock(block); /* erase (and check) old copy */ | 126 | freeblock(block, oldsize); /* erase (and check) old copy */ |
| 118 | } | 127 | } |
| 119 | /* initialize new part of the block with something `weird' */ | 128 | /* initialize new part of the block with something `weird' */ |
| 120 | memset(cast(char *, newblock)+HEADER+oldsize, -MARK, size-oldsize); | 129 | fillmem(cast(char *, newblock)+HEADER+commonsize, size-commonsize); |
| 121 | memdebug_total += size; | 130 | memdebug_total += size; |
| 122 | if (memdebug_total > memdebug_maxmem) | 131 | if (memdebug_total > memdebug_maxmem) |
| 123 | memdebug_maxmem = memdebug_total; | 132 | memdebug_maxmem = memdebug_total; |
| 124 | memdebug_numblocks++; | 133 | memdebug_numblocks++; |
| 125 | *cast(size_t *, newblock) = size; | 134 | setsize(newblock, size); |
| 126 | for (i=0;i<MARKSIZE;i++) | 135 | for (i=0;i<MARKSIZE;i++) |
| 127 | *(cast(char *, newblock)+HEADER+size+i) = cast(char, MARK+i); | 136 | *(cast(char *, newblock)+HEADER+size+i) = cast(char, MARK+i); |
| 128 | return cast(char *, newblock)+HEADER; | 137 | return cast(char *, newblock)+HEADER; |
| @@ -681,6 +690,48 @@ static int testC (lua_State *L) { | |||
| 681 | /* }====================================================== */ | 690 | /* }====================================================== */ |
| 682 | 691 | ||
| 683 | 692 | ||
| 693 | /* | ||
| 694 | ** {====================================================== | ||
| 695 | ** tests for yield inside hooks | ||
| 696 | ** ======================================================= | ||
| 697 | */ | ||
| 698 | |||
| 699 | static void yieldf (lua_State *L, lua_Debug *ar) { | ||
| 700 | lua_yield(L, 0); | ||
| 701 | } | ||
| 702 | |||
| 703 | static int setyhook (lua_State *L) { | ||
| 704 | if (lua_isnoneornil(L, 1)) | ||
| 705 | lua_sethook(L, NULL, 0); /* turn off hooks */ | ||
| 706 | else { | ||
| 707 | const char *smask = luaL_checkstring(L, 1); | ||
| 708 | unsigned long count = LUA_MASKCOUNT(luaL_optint(L, 2, 0)); | ||
| 709 | if (strchr(smask, 'l')) count |= LUA_MASKLINE; | ||
| 710 | lua_sethook(L, yieldf, count); | ||
| 711 | } | ||
| 712 | return 0; | ||
| 713 | } | ||
| 714 | |||
| 715 | |||
| 716 | static int coresume (lua_State *L) { | ||
| 717 | int status; | ||
| 718 | lua_State *co = lua_tothread(L, 1); | ||
| 719 | luaL_argcheck(L, co, 1, "coroutine expected"); | ||
| 720 | status = lua_resume(co, 0); | ||
| 721 | if (status != 0) { | ||
| 722 | lua_pushboolean(L, 0); | ||
| 723 | lua_insert(L, -2); | ||
| 724 | return 2; /* return false + error message */ | ||
| 725 | } | ||
| 726 | else { | ||
| 727 | lua_pushboolean(L, 1); | ||
| 728 | return 1; | ||
| 729 | } | ||
| 730 | } | ||
| 731 | |||
| 732 | /* }====================================================== */ | ||
| 733 | |||
| 734 | |||
| 684 | 735 | ||
| 685 | static const struct luaL_reg tests_funcs[] = { | 736 | static const struct luaL_reg tests_funcs[] = { |
| 686 | {"hash", hash_query}, | 737 | {"hash", hash_query}, |
| @@ -709,6 +760,8 @@ static const struct luaL_reg tests_funcs[] = { | |||
| 709 | {"doremote", doremote}, | 760 | {"doremote", doremote}, |
| 710 | {"log2", log2_aux}, | 761 | {"log2", log2_aux}, |
| 711 | {"totalmem", mem_query}, | 762 | {"totalmem", mem_query}, |
| 763 | {"resume", coresume}, | ||
| 764 | {"setyhook", setyhook}, | ||
| 712 | {NULL, NULL} | 765 | {NULL, NULL} |
| 713 | }; | 766 | }; |
| 714 | 767 | ||
