diff --git a/core/palloc.m b/core/palloc.m index 3dfe17b2ddbb51060c96fee0597f8d4976b0afbd..bc9c5a2fd95c1912759d6c1bb1f940eea867921e 100644 --- a/core/palloc.m +++ b/core/palloc.m @@ -269,7 +269,7 @@ palloc(struct palloc_pool *restrict pool, size_t size) ptr = palloc_slow_path(pool, rz_size); assert(poisoned(ptr + PALLOC_REDZONE, size) == NULL); - VALGRIND_MEMPOOL_ALLOC(pool, ptr + PALLOC_REDZONE, size); + VALGRIND_MAKE_MEM_DEFINED(ptr + PALLOC_REDZONE, size); return ptr + PALLOC_REDZONE; } @@ -293,25 +293,65 @@ palloca(struct palloc_pool *pool, size_t size, size_t align) return (void *)TYPEALIGN(align, (uintptr_t)ptr); } + +static inline void +chunk_free(struct chunk *chunk) +{ + if (chunk->size <= palloc_greatest_size()) { + chunk->free = chunk->size - sizeof(struct chunk); + chunk->brk = (void *)chunk + sizeof(struct chunk); + SLIST_INSERT_HEAD(&chunk->class->chunks, chunk, free_link); + poison_chunk(chunk); + } else { + free(chunk); + } +} + +/** + * Release all memory down to new_size; new_size has to be previously + * obtained by calling palloc_allocated(). + */ +void +ptruncate(struct palloc_pool *pool, size_t new_size) +{ + assert(new_size <= pool->allocated); + + ssize_t cut_size = pool->allocated - new_size; + struct chunk *chunk = SLIST_FIRST(&pool->chunks); + + for (chunk = SLIST_FIRST(&pool->chunks); chunk; + chunk = SLIST_FIRST(&pool->chunks)) { + + size_t chunk_used = (chunk->size - chunk->free - + sizeof(struct chunk)); + if (chunk_used > cut_size) { + /* This is the last chunk to trim. */ + chunk->brk -= cut_size; + chunk->free += cut_size; + VALGRIND_MAKE_MEM_NOACCESS(chunk->brk, cut_size); + cut_size = 0; + break; + } + cut_size -= chunk_used; + /* Remove the entire chunk. */ + SLIST_REMOVE_HEAD(&pool->chunks, busy_link); + chunk_free(chunk); + } + assert(cut_size == 0); + pool->allocated = new_size; +} + void prelease(struct palloc_pool *pool) { struct chunk *chunk, *next_chunk; - for (chunk = SLIST_FIRST(&pool->chunks); chunk != NULL; chunk = next_chunk) { + for (chunk = SLIST_FIRST(&pool->chunks); chunk; chunk = next_chunk) { next_chunk = SLIST_NEXT(chunk, busy_link); - if (chunk->size <= palloc_greatest_size()) { - chunk->free = chunk->size - sizeof(struct chunk); - chunk->brk = (void *)chunk + sizeof(struct chunk); - SLIST_INSERT_HEAD(&chunk->class->chunks, chunk, free_link); - poison_chunk(chunk); - } else { - free(chunk); - } + chunk_free(chunk); } SLIST_INIT(&pool->chunks); - VALGRIND_MEMPOOL_TRIM(pool, NULL, 0); pool->allocated = 0; } @@ -331,7 +371,6 @@ palloc_create_pool(const char *name) palloc_set_name(pool, name); SLIST_INIT(&pool->chunks); SLIST_INSERT_HEAD(&pools, pool, link); - VALGRIND_CREATE_MEMPOOL(pool, PALLOC_REDZONE, 0); return pool; } @@ -340,7 +379,6 @@ palloc_destroy_pool(struct palloc_pool *pool) { SLIST_REMOVE(&pools, pool, palloc_pool, link); prelease(pool); - VALGRIND_DESTROY_MEMPOOL(pool); free(pool); } diff --git a/include/palloc.h b/include/palloc.h index a6b4425a8965cec4e928b87640eafbbf2968cc73..b93722ce6cf57c5310be5d3bc2c858c64b1a12c9 100644 --- a/include/palloc.h +++ b/include/palloc.h @@ -40,6 +40,7 @@ void *palloc(struct palloc_pool *pool, size_t size) __attribute__((regparm(2))); void *p0alloc(struct palloc_pool *pool, size_t size) __attribute__((regparm(2))); void *palloca(struct palloc_pool *pool, size_t size, size_t align); void prelease(struct palloc_pool *pool); +void ptruncate(struct palloc_pool *pool, size_t sz); void prelease_after(struct palloc_pool *pool, size_t after); struct palloc_pool *palloc_create_pool(const char *name); void palloc_destroy_pool(struct palloc_pool *); diff --git a/mod/box/box_lua.m b/mod/box/box_lua.m index 9507d173e9ccce6e47d3cb49c6c4fa271aebf321..eb643f1899e1523343741143ebf8f1f81d73992e 100644 --- a/mod/box/box_lua.m +++ b/mod/box/box_lua.m @@ -646,11 +646,13 @@ static int lbox_process(lua_State *L) } int top = lua_gettop(L); /* to know how much is added by rw_callback */ + size_t allocated_size = palloc_allocated(fiber->gc_pool); struct box_txn *old_txn = txn_enter_lua(L); @try { rw_callback(op, &req); } @finally { fiber->mod_data.txn = old_txn; + ptruncate(fiber->gc_pool, allocated_size); } return lua_gettop(L) - top; } diff --git a/test/box/lua.result b/test/box/lua.result index 0fbc3a9738552decfeeede1560e1ed6e90fd5458..149674fdf354cc985e9096b6c4b9c0c0fb775675 100644 --- a/test/box/lua.result +++ b/test/box/lua.result @@ -814,6 +814,9 @@ Found 25 tuples: lua box.space[0]:truncate() --- ... +lua box.crossjoin = nil +--- +... # A test case for Bug#901674 # No way to inspect exceptions from Box in Lua diff --git a/test/box/lua.test b/test/box/lua.test index 627bec1ba608b07bd816e7a33d8ebfed5cabb94f..3cca574787fd90de592db22817243baf45dd62f2 100644 --- a/test/box/lua.test +++ b/test/box/lua.test @@ -237,6 +237,7 @@ exec admin "lua box.space[0]:insert(4, 'world')" exec admin "lua box.space[0]:insert(5, 'hello world')" exec sql "call box.crossjoin('0', '0', '10000')" exec admin "lua box.space[0]:truncate()" +exec admin "lua box.crossjoin = nil" print """ # A test case for Bug#901674 # No way to inspect exceptions from Box in Lua