forked from GitHub/gf-core
more bugfixes in the allocator
This commit is contained in:
@@ -1027,29 +1027,32 @@ object PgfDB::delete_block_descriptor(object map, size_t *psize, object *po)
|
|||||||
fit:
|
fit:
|
||||||
*po = descr->o;
|
*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);
|
int index = (descr->descr_txn_id != ms->curr_txn_id);
|
||||||
descr->chain = free_descriptors[index];
|
descr->chain = free_descriptors[index];
|
||||||
free_descriptors[index] = map;
|
free_descriptors[index] = map;
|
||||||
if (index == 1 && free_descriptors[2] == 0)
|
if (index == 1 && free_descriptors[2] == 0)
|
||||||
free_descriptors[2] = map;
|
free_descriptors[2] = map;
|
||||||
|
|
||||||
if (descr->left == 0) {
|
return new_map;
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1125,7 +1128,7 @@ object PgfDB::malloc_internal(size_t bytes)
|
|||||||
}
|
}
|
||||||
|
|
||||||
PGF_INTERNAL
|
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)
|
if (oldo == 0)
|
||||||
return malloc_internal(new_bytes);
|
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 old_nb = request2size(old_bytes);
|
||||||
size_t new_nb = request2size(new_bytes);
|
size_t new_nb = request2size(new_bytes);
|
||||||
|
|
||||||
if (oldo + old_nb == top) {
|
if (txn_id == ms->curr_txn_id) {
|
||||||
ssize_t nb = new_nb-old_nb;
|
if (old_nb == new_nb)
|
||||||
ssize_t free_size = mmap_size - top;
|
return oldo;
|
||||||
|
|
||||||
if (nb > free_size) {
|
if (oldo + old_nb == top) {
|
||||||
size_t alloc_size =
|
ssize_t nb = new_nb-old_nb;
|
||||||
((nb - free_size + page_size - 1) / page_size) * page_size;
|
ssize_t free_size = mmap_size - top;
|
||||||
size_t new_size =
|
|
||||||
ms->file_size + alloc_size;
|
|
||||||
|
|
||||||
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
|
resize_map(new_size);
|
||||||
top += nb;
|
}
|
||||||
|
|
||||||
|
// If the object is at the end of the allocation area
|
||||||
|
top += nb;
|
||||||
|
|
||||||
#ifdef DEBUG_MEMORY_ALLOCATOR
|
#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
|
#endif
|
||||||
|
|
||||||
return oldo;
|
return oldo;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
object newo = malloc_internal(new_bytes);
|
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);
|
free_internal(oldo, old_bytes);
|
||||||
return newo;
|
return newo;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -103,8 +103,8 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<class A>
|
template<class A>
|
||||||
static ref<A> realloc(ref<A> r, size_t old_extra_bytes, size_t 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);
|
return current_db->realloc_internal(r.as_object(), sizeof(A)+old_extra_bytes, sizeof(A)+new_extra_bytes, txn_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class A>
|
template<class A>
|
||||||
@@ -144,7 +144,7 @@ private:
|
|||||||
|
|
||||||
PGF_INTERNAL_DECL object malloc_internal(size_t bytes);
|
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);
|
PGF_INTERNAL_DECL void free_internal(object o, size_t bytes);
|
||||||
|
|
||||||
|
|||||||
@@ -1847,7 +1847,7 @@ public:
|
|||||||
|
|
||||||
size_t len = entry->backrefs->len;
|
size_t len = entry->backrefs->len;
|
||||||
ref<Vector<PgfSequenceBackref>> backrefs =
|
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].container = container;
|
||||||
backrefs->data[len].seq_index = seq_index;
|
backrefs->data[len].seq_index = seq_index;
|
||||||
entry->backrefs = backrefs;
|
entry->backrefs = backrefs;
|
||||||
|
|||||||
@@ -270,13 +270,12 @@ PgfPhrasetable phrasetable_internalize(PgfPhrasetable table,
|
|||||||
: 0;
|
: 0;
|
||||||
|
|
||||||
ref<Vector<PgfSequenceBackref>> backrefs =
|
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].container = container;
|
||||||
backrefs->data[len].seq_index = seq_index;
|
backrefs->data[len].seq_index = seq_index;
|
||||||
|
|
||||||
PgfPhrasetable new_table =
|
PgfPhrasetable new_table =
|
||||||
Node<PgfPhrasetableEntry>::upd_node(table, table->left, table->right);
|
Node<PgfPhrasetableEntry>::upd_node(table, table->left, table->right);
|
||||||
Vector<PgfSequenceBackref>::release(new_table->value.backrefs);
|
|
||||||
new_table->value.backrefs = backrefs;
|
new_table->value.backrefs = backrefs;
|
||||||
*pentry = ref<PgfPhrasetableEntry>::from_ptr(&new_table->value);
|
*pentry = ref<PgfPhrasetableEntry>::from_ptr(&new_table->value);
|
||||||
return new_table;
|
return new_table;
|
||||||
@@ -299,7 +298,7 @@ ref<PgfSequence> phrasetable_relink(PgfPhrasetable table,
|
|||||||
: table->value.backrefs->len;
|
: table->value.backrefs->len;
|
||||||
|
|
||||||
ref<Vector<PgfSequenceBackref>> backrefs =
|
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].container = container;
|
||||||
backrefs->data[len].seq_index = seq_index;
|
backrefs->data[len].seq_index = seq_index;
|
||||||
table->value.backrefs = backrefs;
|
table->value.backrefs = backrefs;
|
||||||
@@ -342,29 +341,25 @@ PgfPhrasetable phrasetable_delete(PgfPhrasetable table,
|
|||||||
size_t len = table->value.backrefs->len;
|
size_t len = table->value.backrefs->len;
|
||||||
if (len > 1) {
|
if (len > 1) {
|
||||||
ref<Vector<PgfSequenceBackref>> backrefs =
|
ref<Vector<PgfSequenceBackref>> backrefs =
|
||||||
vector_new<PgfSequenceBackref>(len-1);
|
vector_resize<PgfSequenceBackref>(table->value.backrefs, len-1, table->txn_id);
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
while (i < len) {
|
while (i < len) {
|
||||||
ref<PgfSequenceBackref> backref =
|
ref<PgfSequenceBackref> backref =
|
||||||
vector_elem(table->value.backrefs, i);
|
vector_elem(backrefs, i);
|
||||||
if (backref->container == container &&
|
if (backref->container == container &&
|
||||||
backref->seq_index == seq_index) {
|
backref->seq_index == seq_index) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
*vector_elem(backrefs, i) = *backref;
|
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
i++;
|
i++;
|
||||||
while (i < len) {
|
while (i < len) {
|
||||||
ref<PgfSequenceBackref> backref =
|
*vector_elem(backrefs, i-1) = *vector_elem(backrefs, i);
|
||||||
vector_elem(table->value.backrefs, i);
|
|
||||||
*vector_elem(backrefs, i-1) = *backref;
|
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
PgfPhrasetable new_table =
|
PgfPhrasetable new_table =
|
||||||
Node<PgfPhrasetableEntry>::upd_node(table, table->left, table->right);
|
Node<PgfPhrasetableEntry>::upd_node(table, table->left, table->right);
|
||||||
Vector<PgfSequenceBackref>::release(new_table->value.backrefs);
|
|
||||||
new_table->value.backrefs = backrefs;
|
new_table->value.backrefs = backrefs;
|
||||||
return new_table;
|
return new_table;
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -31,55 +31,20 @@ ref<C> vector_new(Vector<A> C::* field, size_t len)
|
|||||||
PGF_INTERNAL_DECL size_t
|
PGF_INTERNAL_DECL size_t
|
||||||
get_next_padovan(size_t min);
|
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
|
/* Resize a vector by changing its length. If there is no enough space
|
||||||
* the implementation will create a copy, but whenever possible it will
|
* the implementation will create a copy, but whenever possible it will
|
||||||
* return the reference of the original vector. In the later case, it
|
* return the reference to the original vector. A copy is created also
|
||||||
* changes the length in-place which means that the function is safe
|
* if txn_id is different from the current transaction. In this way
|
||||||
* only if the vector was created during the current transaction. */
|
* it is safe to change the length. */
|
||||||
template <class A> inline PGF_INTERNAL
|
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 old_len = get_next_padovan(vec->len);
|
||||||
size_t new_len = get_next_padovan(len);
|
|
||||||
|
|
||||||
if (old_len == new_len)
|
vec = PgfDB::realloc<Vector<A>>(vec,old_len*sizeof(A),new_len*sizeof(A),txn_id);
|
||||||
return vec;
|
vec->len = 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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class A> inline PGF_INTERNAL
|
template <class A> inline PGF_INTERNAL
|
||||||
|
|||||||
Reference in New Issue
Block a user