Пример #1
0
// try applying sequence
int try_sequence(SEQLIST *test_sequence, int mem_size) {
  SEQLIST *sptr;
  unsigned char *mblock;

  // reset the memory allocator being tested
  MEMORY_SIZE = mem_size;
  init_myalloc();

  for (sptr = test_sequence; !seq_null(sptr); sptr = seq_next(sptr)) {
    if (seq_alloc(sptr)) {     // allocate a block
      mblock = myalloc(seq_size(sptr));
      if (mblock == 0) {
        return 0; // failed -- return indication
      }
      else {
        // keep track of address allocated (for later frees)
        seq_set_myalloc_block(sptr, mblock);
        // put data in the block
        //  (so we can test that it holds data w/out corruption)
        fill_data(seq_ref_block(sptr), mblock, seq_size(sptr));
      }
    }
    else {    // dealloc
      myfree(seq_myalloc_block(seq_tofree(sptr)));
    }
  }

  return 1; // succeeded in allocating entire sequence
}
Пример #2
0
/**
* DESCRIPTION:  deletes the back/last element
*   in the seq and returns its value.
*   If the seq is empty, the seq is unchanged and
*     the return value has no meaning (i.e., this is
*     the client's fault!)
* RUNTIME REQ: O(1)
*/
extern ETYPE seq_del_back(Seq seq){
    if( seq_size(seq) <= 0){
	return (ETYPE)-1;
    }
    Node* nodehold = seq->tail;
    if( seq_size(seq) == 1){
	    seq->head = NULL;	
    } 
    //if the list is at least 2 big, the head will not change
    ETYPE holder = seq->tail->a;
    //even if one node, should set tail to null
    seq->tail = seq->tail->bw;
    if( seq->tail != NULL) seq->tail->fw = NULL;
    free(nodehold);
    --(seq->numN);
    return holder;
}
Пример #3
0
/**
* DESCRIPTION:  deletes the front/first element
*   in the seq and returns its value.
*   If the seq is empty, the seq is unchanged and
*     the return value has no meaning (i.e., this is
*     the client's fault!
* RUNTIME REQ: O(1)
*/
extern ETYPE seq_del_front(Seq seq){
    if( seq_size(seq) <= 0){
	return (ETYPE)-1;
    }
    Node* nodehold = seq->head;
    if( seq_size(seq) == 1){
	seq->tail = NULL;	
    }
    //if the list is at least 2 big, the tail will not change
    ETYPE holder = seq->head->a;
    //even if one node, should set head to null;
    seq->head = seq->head->fw;
    if( seq->head != NULL) seq->head->bw = NULL;
    free(nodehold);
    --(seq->numN);
    return holder;
}
Пример #4
0
/**
* DESCRIPTION:  adds a new element with given val
*    to the "front" of the seq.
* RUNTIME REQ: O(1)
*/
extern void seq_add_front(Seq seq, ETYPE val){
  Node* front;
  front = (Node*)malloc(sizeof(Node) );
  front->a = val;
  if( seq_size(seq) >= 1){ //at least one node (head and tail exist)
	  front->fw = seq->head; //point the new front to the list
	  seq->head->bw = front; //point the "old" front to the new front
  }
  else{ //the seq has 0 elems; front is both "front" and "end"
	  seq->tail = front;
	  front->fw = NULL;
  }
  front->bw = NULL;
  seq->head = front;
  ++(seq->numN); //reflect addition of new node
}
Пример #5
0
/**
* DESCRIPTION:  adds a new element to the "back" of
*  the seq
* RUNTIME REQ: O(1)
*/
extern void seq_add_back(Seq seq, ETYPE val){
    Node* back;
    back = (Node*)malloc(sizeof(Node) );
    back->a = val;
    if( seq_size(seq) >= 1){ //at least one node (head and tail exist)
	back->bw = seq->tail; //point the new tail to the list
	seq->tail->fw = back; //point the "old" tail to the new end
    }
    else{ //the seq has 0 elems; back is both "front" and "end"
	seq->head = back;
	seq->tail = back;
	back->bw = NULL;
    }
    back->fw = NULL;
    seq->tail = back;
    ++(seq->numN); //reflect addition of new node
}
Пример #6
0
// check all still allocated blocks in a test sequence
//  contain the data originally placed into them
//  i.e. have not been corrupted
int check_data(SEQLIST *test_sequence) {
  int result;
  SEQLIST *current;

  result = 0; // stays zero if no errors

  for (current = test_sequence; !seq_null(current); current = seq_next(current)) {
    // only check if an allocate which has not been freed
    if (seq_alloc(current) && !seq_freed(current)) {
      if (!same_data(seq_ref_block(current), seq_myalloc_block(current),
                     seq_size(current))) {
        if (VERBOSE) {
          printf("Mismatch in sequence starting at:\n");
          seq_print(current);
        }

        // returning a 1 means it failed
        result = 1;
      }
    }
  }

  return result;
}
Пример #7
0
// create a test sequence which never uses more than max_used_memory
//   and allocates a total of max_used_memory*allocation_factor
SEQLIST *generate_sequence(int max_used_memory, int allocation_factor) {
  int used_memory = 0;
  int total_allocated = 0;
  int next_block_size = 0;
  int allocated_blocks = 0;
  int actual_max_used_memory = 0;

  SEQLIST *test_sequence = (SEQLIST *) 0;
  SEQLIST *tail_sequence = (SEQLIST *) 0;
  SEQLIST *tofree = (SEQLIST *) 0;

  unsigned char *new_block_ref;

  while (total_allocated < allocation_factor * max_used_memory) {
    next_block_size = random_block_size(max_used_memory);

    // first see if we need to free anything in order to
    //  accommodate the new allocation
    while (used_memory + next_block_size > max_used_memory) {
      // randomly pick a block to free
      SEQLIST *tofree =
        find_nth_allocated_block(test_sequence, random_int(allocated_blocks));

      // add the free
      tail_sequence = seq_set_next_free(tofree, tail_sequence);

      // reclaim the memory
      used_memory -= seq_size(tofree);
      allocated_blocks--;

      // mark the old block as something that has been freed
      seq_free(tofree);
    }

    // allocate a reference buffer for the new block
    new_block_ref = allocate_and_fill(next_block_size);

    // now allocate that block
    if (seq_null(test_sequence)) {
      // special case for first allocation
      test_sequence = seq_add_front(next_block_size, new_block_ref, (SEQLIST *) 0);
      tail_sequence = test_sequence;
    }
    else {
      // typical case we add at the end
      tail_sequence =
        seq_set_next_allocate(next_block_size, new_block_ref, tail_sequence);
    }

    // debug
    //seq_print(tail_sequence); // just prints the new one

    total_allocated += next_block_size;
    used_memory += next_block_size;

    if (used_memory > actual_max_used_memory)
      actual_max_used_memory = used_memory;

    allocated_blocks++;
  }

  // just so can manually see this is doing something sensible
  printf("Actual maximum memory usage %d (%f)\n", actual_max_used_memory,
         ((double) actual_max_used_memory / (double) max_used_memory));

  return test_sequence;
}
Пример #8
0
/**
* DESCRIPTION:  returns the last/back element
*  of the sequence; does not modify the
*  sequence.  If sequence is empty then
*  return value has no meaning (client's
*  fault!
* RUNTIME REQ:  O(1)
*/
extern ETYPE seq_peek_back(Seq seq){
    if( seq_size(seq) <= 0){
	return (ETYPE)-1;
    }
    return seq->tail->a;
}
Пример #9
0
/**
* DESCRIPTION:  returns the front element
*  of the sequence; does not modify the
*  sequence.  If sequence is empty then
*  return value has no meaning (client's
*  fault!
* RUNTIME REQ:  O(1)
*/
extern ETYPE seq_peek_front(Seq seq){
    if( seq_size(seq) <= 0){
	return (ETYPE)-1;
    }
    return seq->head->a;
}