more bugfixes in the allocator

This commit is contained in:
Krasimir Angelov
2022-05-28 07:43:56 +02:00
parent 02e45f478f
commit 109f8c86e8
5 changed files with 59 additions and 91 deletions

View File

@@ -1027,29 +1027,32 @@ object PgfDB::delete_block_descriptor(object map, size_t *psize, object *po)
fit:
*po = descr->o;
object new_map;
if (descr->left == 0) {
new_map = descr->right;
} else if (descr->right == 0) {
new_map = descr->left;
} else {
if (ptr(block_descr,descr->left)->sz > ptr(block_descr,descr->right)->sz) {
object right = descr->right;
object left = pop_last_block_descriptor(descr->left, &new_map);
new_map = upd_block_descr(new_map, left, right);
new_map = balanceR_block_descriptor(new_map);
} else {
object left = descr->left;
object right = pop_first_block_descriptor(descr->right, &new_map);
new_map = upd_block_descr(new_map, left, right);
new_map = balanceL_block_descriptor(new_map);
}
}
int index = (descr->descr_txn_id != ms->curr_txn_id);
descr->chain = free_descriptors[index];
free_descriptors[index] = map;
if (index == 1 && free_descriptors[2] == 0)
free_descriptors[2] = map;
if (descr->left == 0) {
return descr->right;
} else if (descr->right == 0) {
return descr->left;
} else {
if (ptr(block_descr,descr->left)->sz > ptr(block_descr,descr->right)->sz) {
object right = descr->right;
object left = pop_last_block_descriptor(descr->left, &map);
map = upd_block_descr(map, left, right);
return balanceR_block_descriptor(map);
} else {
object left = descr->left;
object right = pop_first_block_descriptor(descr->right, &map);
map = upd_block_descr(map, left, right);
return balanceL_block_descriptor(map);
}
}
return new_map;
}
}
@@ -1125,7 +1128,7 @@ object PgfDB::malloc_internal(size_t bytes)
}
PGF_INTERNAL
object PgfDB::realloc_internal(object oldo, size_t old_bytes, size_t new_bytes)
object PgfDB::realloc_internal(object oldo, size_t old_bytes, size_t new_bytes, txn_t txn_id)
{
if (oldo == 0)
return malloc_internal(new_bytes);
@@ -1133,31 +1136,36 @@ object PgfDB::realloc_internal(object oldo, size_t old_bytes, size_t new_bytes)
size_t old_nb = request2size(old_bytes);
size_t new_nb = request2size(new_bytes);
if (oldo + old_nb == top) {
ssize_t nb = new_nb-old_nb;
ssize_t free_size = mmap_size - top;
if (txn_id == ms->curr_txn_id) {
if (old_nb == new_nb)
return oldo;
if (nb > free_size) {
size_t alloc_size =
((nb - free_size + page_size - 1) / page_size) * page_size;
size_t new_size =
ms->file_size + alloc_size;
if (oldo + old_nb == top) {
ssize_t nb = new_nb-old_nb;
ssize_t free_size = mmap_size - top;
resize_map(new_size);
}
if (nb > free_size) {
size_t alloc_size =
((nb - free_size + page_size - 1) / page_size) * page_size;
size_t new_size =
ms->file_size + alloc_size;
// If the object is at the end of the allocation area
top += nb;
resize_map(new_size);
}
// If the object is at the end of the allocation area
top += nb;
#ifdef DEBUG_MEMORY_ALLOCATOR
fprintf(stderr, "realloc_internal(%016lx,%ld,%ld)\n", oldo, old_bytes, new_bytes);
fprintf(stderr, "realloc_internal(%016lx,%ld,%ld)\n", oldo, old_bytes, new_bytes);
#endif
return oldo;
return oldo;
}
}
object newo = malloc_internal(new_bytes);
memcpy(base+newo, base+oldo, old_bytes < new_bytes ? old_bytes : new_bytes);
memcpy(base+newo, base+oldo, (old_bytes < new_bytes) ? old_bytes : new_bytes);
free_internal(oldo, old_bytes);
return newo;
}

View File

@@ -103,8 +103,8 @@ public:
}
template<class A>
static ref<A> realloc(ref<A> r, size_t old_extra_bytes, size_t new_extra_bytes) {
return current_db->realloc_internal(r.as_object(), sizeof(A)+old_extra_bytes, sizeof(A)+new_extra_bytes);
static ref<A> realloc(ref<A> r, size_t old_extra_bytes, size_t new_extra_bytes, txn_t txn_id) {
return current_db->realloc_internal(r.as_object(), sizeof(A)+old_extra_bytes, sizeof(A)+new_extra_bytes, txn_id);
}
template<class A>
@@ -144,7 +144,7 @@ private:
PGF_INTERNAL_DECL object malloc_internal(size_t bytes);
PGF_INTERNAL_DECL object realloc_internal(object oldo, size_t old_bytes, size_t new_bytes);
PGF_INTERNAL_DECL object realloc_internal(object oldo, size_t old_bytes, size_t new_bytes, txn_t txn_id);
PGF_INTERNAL_DECL void free_internal(object o, size_t bytes);

View File

@@ -1847,7 +1847,7 @@ public:
size_t len = entry->backrefs->len;
ref<Vector<PgfSequenceBackref>> backrefs =
vector_unsafe_resize<PgfSequenceBackref>(entry->backrefs, len+1);
vector_resize<PgfSequenceBackref>(entry->backrefs, len+1, PgfDB::get_txn_id());
backrefs->data[len].container = container;
backrefs->data[len].seq_index = seq_index;
entry->backrefs = backrefs;

View File

@@ -270,13 +270,12 @@ PgfPhrasetable phrasetable_internalize(PgfPhrasetable table,
: 0;
ref<Vector<PgfSequenceBackref>> backrefs =
vector_copy<PgfSequenceBackref>(table->value.backrefs, len+1);
vector_resize<PgfSequenceBackref>(table->value.backrefs, len+1, table->txn_id);
backrefs->data[len].container = container;
backrefs->data[len].seq_index = seq_index;
PgfPhrasetable new_table =
Node<PgfPhrasetableEntry>::upd_node(table, table->left, table->right);
Vector<PgfSequenceBackref>::release(new_table->value.backrefs);
new_table->value.backrefs = backrefs;
*pentry = ref<PgfPhrasetableEntry>::from_ptr(&new_table->value);
return new_table;
@@ -299,7 +298,7 @@ ref<PgfSequence> phrasetable_relink(PgfPhrasetable table,
: table->value.backrefs->len;
ref<Vector<PgfSequenceBackref>> backrefs =
vector_unsafe_resize<PgfSequenceBackref>(table->value.backrefs, len+1);
vector_resize<PgfSequenceBackref>(table->value.backrefs, len+1, table->txn_id);
backrefs->data[len].container = container;
backrefs->data[len].seq_index = seq_index;
table->value.backrefs = backrefs;
@@ -342,29 +341,25 @@ PgfPhrasetable phrasetable_delete(PgfPhrasetable table,
size_t len = table->value.backrefs->len;
if (len > 1) {
ref<Vector<PgfSequenceBackref>> backrefs =
vector_new<PgfSequenceBackref>(len-1);
vector_resize<PgfSequenceBackref>(table->value.backrefs, len-1, table->txn_id);
size_t i = 0;
while (i < len) {
ref<PgfSequenceBackref> backref =
vector_elem(table->value.backrefs, i);
ref<PgfSequenceBackref> backref =
vector_elem(backrefs, i);
if (backref->container == container &&
backref->seq_index == seq_index) {
break;
}
*vector_elem(backrefs, i) = *backref;
i++;
}
i++;
while (i < len) {
ref<PgfSequenceBackref> backref =
vector_elem(table->value.backrefs, i);
*vector_elem(backrefs, i-1) = *backref;
*vector_elem(backrefs, i-1) = *vector_elem(backrefs, i);
i++;
}
PgfPhrasetable new_table =
Node<PgfPhrasetableEntry>::upd_node(table, table->left, table->right);
Vector<PgfSequenceBackref>::release(new_table->value.backrefs);
new_table->value.backrefs = backrefs;
return new_table;
} else {

View File

@@ -31,55 +31,20 @@ ref<C> vector_new(Vector<A> C::* field, size_t len)
PGF_INTERNAL_DECL size_t
get_next_padovan(size_t min);
/* Resize a vector by creating a new one and copying the old content.
* The new vector is now also safe to update */
template <class A> inline PGF_INTERNAL
ref<Vector<A>> vector_copy(ref<Vector<A>> vec, size_t len)
{
size_t size = len*sizeof(A);
ref<Vector<A>> res = PgfDB::malloc<Vector<A>>(size);
res->len = len;
memcpy(res->data, vec->data, size);
return res;
}
/* Resize a vector by changing its length. If there is no enough space
* the implementation will create a copy, but whenever possible it will
* return the reference of the original vector. In the later case, it
* changes the length in-place which means that the function is safe
* only if the vector was created during the current transaction. */
* return the reference to the original vector. A copy is created also
* if txn_id is different from the current transaction. In this way
* it is safe to change the length. */
template <class A> inline PGF_INTERNAL
ref<Vector<A>> vector_unsafe_resize(ref<Vector<A>> vec, size_t len)
ref<Vector<A>> vector_resize(ref<Vector<A>> vec, size_t len, txn_t txn_id)
{
size_t new_len = get_next_padovan(len);
size_t old_len = get_next_padovan(vec->len);
size_t new_len = get_next_padovan(len);
if (old_len == new_len)
return vec;
ref<Vector<A>> res = PgfDB::realloc<Vector<A>>(vec,old_len*sizeof(A),new_len*sizeof(A)).as_object();
res->len = len;
return res;
}
/* Resize a vector embedded in another structure, by changing its length.
* If there is no enough space the implementation will copy the structure,
* but whenever possible it will return a reference to
* the original structure. In the later case, it changes
* the vector's length in-place which means that the function is safe
* only if the structure was created during the current transaction. */
template <class C, class A> inline PGF_INTERNAL
ref<C> vector_unsafe_resize(ref<C> r, Vector<A> C::* field, size_t len)
{
size_t old_len = get_next_padovan((r->*field).len);
size_t new_len = get_next_padovan(len);
if (old_len == new_len)
return r;
ref<C> res = PgfDB::realloc<C>(r,old_len*sizeof(A),new_len*sizeof(A)).as_object();
(res->*field).len = len;
return res;
vec = PgfDB::realloc<Vector<A>>(vec,old_len*sizeof(A),new_len*sizeof(A),txn_id);
vec->len = len;
return vec;
}
template <class A> inline PGF_INTERNAL