static inline struct boundary_tag* split_tag( struct boundary_tag* tag ) { unsigned int remainder = tag->real_size - sizeof(struct boundary_tag) - tag->size; struct boundary_tag *new_tag = (struct boundary_tag*)((unsigned int)tag + sizeof(struct boundary_tag) + tag->size); new_tag->magic = LIBALLOC_MAGIC; new_tag->real_size = remainder; new_tag->next = NULL; new_tag->prev = NULL; new_tag->split_left = tag; new_tag->split_right = tag->split_right; if (new_tag->split_right != NULL) new_tag->split_right->split_left = new_tag; tag->split_right = new_tag; tag->real_size -= new_tag->real_size; insert_tag( new_tag, -1 ); return new_tag; }
void handle_tag(pTHX_ const TagTypeInfo *ptti, CtTagList *ptl, SV *name, SV *val, SV **rv) { const struct tag_tbl_ent *etbl; const char *tagstr; CtTagType tagid; CtTag *tag; assert(ptl); assert(name); if (SvROK(name)) Perl_croak(aTHX_ "Tag name must be a string, not a reference"); tagstr = SvPV_nolen(name); tagid = get_tag_id(tagstr); if (tagid == CBC_INVALID_TAG) Perl_croak(aTHX_ "Invalid tag name '%s'", tagstr); if (tagid > NUM_TAGIDS) fatal("Unknown tag type (%d) in handle_tag()", (int) tagid); etbl = &gs_TagTbl[tagid]; tag = find_tag(*ptl, tagid); if (etbl->verify) etbl->verify(aTHX_ ptti, tag, val); if (val) { TagSetRV rv; if (tag == NULL) { dTHR; dXCPT; tag = tag_new(tagid, etbl->vtbl); XCPT_TRY_START { rv = etbl->set(aTHX_ ptti, tag, val); } XCPT_TRY_END XCPT_CATCH { tag_delete(tag); XCPT_RETHROW; } insert_tag(ptl, tag); } else
void free(void *ptr) { int index; struct boundary_tag *tag; if ( ptr == NULL ) return; liballoc_lock(); tag = (struct boundary_tag*)((unsigned int)ptr - sizeof( struct boundary_tag )); if ( tag->magic != LIBALLOC_MAGIC ) { liballoc_unlock(); // release the lock return; } // MELT LEFT... while ( (tag->split_left != NULL) && (tag->split_left->index >= 0) ) { tag = melt_left( tag ); remove_tag( tag ); } // MELT RIGHT... while ( (tag->split_right != NULL) && (tag->split_right->index >= 0) ) { tag = absorb_right( tag ); } // Where is it going back to? index = getexp( tag->real_size - sizeof(struct boundary_tag) ); if ( index < MINEXP ) index = MINEXP; // A whole, empty block? if ( (tag->split_left == NULL) && (tag->split_right == NULL) ) { if ( l_completePages[ index ] == MAXCOMPLETE ) { // Too many standing by to keep. Free this one. unsigned int pages = tag->real_size / l_pageSize; if ( (tag->real_size % l_pageSize) != 0 ) pages += 1; if ( pages < l_pageCount ) pages = l_pageCount; liballoc_free( tag, pages ); liballoc_unlock(); return; } l_completePages[ index ] += 1; // Increase the count of complete pages. } // .......... insert_tag( tag, index ); liballoc_unlock(); }
void free(void *ptr) { int index; struct boundary_tag *tag; if ( ptr == NULL ) return; liballoc_lock(); tag = (struct boundary_tag*)((unsigned int)ptr - sizeof( struct boundary_tag )); if ( tag->magic != LIBALLOC_MAGIC ) { liballoc_unlock(); // release the lock return; } #ifdef DEBUG l_inuse -= tag->size; printf("free: %x, %i, %i\n", ptr, (int)l_inuse / 1024, (int)l_allocated / 1024 ); #endif // MELT LEFT... while ( (tag->split_left != NULL) && (tag->split_left->index >= 0) ) { #ifdef DEBUG printf("Melting tag left into available memory. Left was %i, becomes %i (%i)\n", tag->split_left->real_size, tag->split_left->real_size + tag->real_size, tag->split_left->real_size ); #endif tag = melt_left( tag ); remove_tag( tag ); } // MELT RIGHT... while ( (tag->split_right != NULL) && (tag->split_right->index >= 0) ) { #ifdef DEBUG printf("Melting tag right into available memory. This was was %i, becomes %i (%i)\n", tag->real_size, tag->split_right->real_size + tag->real_size, tag->split_right->real_size ); #endif tag = absorb_right( tag ); } // Where is it going back to? index = getexp( tag->real_size - sizeof(struct boundary_tag) ); if ( index < MINEXP ) index = MINEXP; // A whole, empty block? if ( (tag->split_left == NULL) && (tag->split_right == NULL) ) { if ( l_completePages[ index ] == MAXCOMPLETE ) { // Too many standing by to keep. Free this one. unsigned int pages = tag->real_size / l_pageSize; if ( (tag->real_size % l_pageSize) != 0 ) pages += 1; if ( pages < l_pageCount ) pages = l_pageCount; liballoc_free( tag, pages ); #ifdef DEBUG l_allocated -= pages * l_pageSize; printf("Resource freeing %x of %i pages\n", tag, pages ); dump_array(); #endif liballoc_unlock(); return; } l_completePages[ index ] += 1; // Increase the count of complete pages. } // .......... insert_tag( tag, index ); #ifdef DEBUG printf("Returning tag with %i bytes (requested %i bytes), which has exponent: %i\n", tag->real_size, tag->size, index ); dump_array(); #endif liballoc_unlock(); }