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;
}
Example #2
0
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();
}
Example #4
0
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();
}