Beispiel #1
0
void* linkedlist_remove(linkedlist _list, void* data)
{
    linkedlist_t* list = (linkedlist_t*) _list;
    node* n = find_by_data(list, data);

    if(NULL == n)
        return NULL;

    if(is_first(list, n)) // at the first
    {
        if(is_last(list, n)) // only one exists
        {
            set_head(list, NULL);
            set_tail(list, NULL);
        }
        else // one or more exist
        {
            set_head(list, get_next(n));
            set_prev(n, NULL);
        }
    }
    else if(is_last((linkedlist_t*)_list, n))
    {
        set_next(get_prev(n), NULL);
        set_tail(list, get_prev(n));
    }
    else
    {
        set_prev(get_next(n), get_prev(n));
        set_next(get_prev(n), get_next(n));
    }
    list->size--;
    free(n);
    return data;
}
Beispiel #2
0
void *
MEM_realloc_func(MEM_Controller controller, char *filename, 
                int line, void *ptr, size_t size)
{
    void        *new_ptr;
    size_t      alloc_size;
    void        *real_ptr;
#ifdef  DEBUG
    Header      old_header;
    int         old_size;
    
    alloc_size = size + sizeof(Header) + MARK_SIZE;
    if (ptr != NULL) {
        real_ptr = (char *)ptr - sizeof(Header);
        check_mark((Header *)real_ptr);
        old_header = *((Header *)real_ptr);
        old_size = old_header.s.size;
        unchain_block(controller, real_ptr);
    } else {
        real_ptr = NULL;
        old_size = 0;
    }
#else
    alloc_size = size;
    real_ptr = ptr;
#endif    

    new_ptr = realloc(real_ptr, alloc_size);
    if (new_ptr == NULL) {
        if (ptr == NULL) {
            error_handler(controller, filename, line, "realloc(malloc)");
        } else {
            error_handler(controller, filename, line, "realloc");
            free(real_ptr);
        }
    }
    
#ifdef DEBUG
    if (ptr) {
        *((Header *)new_ptr) = old_header;
        ((Header *)new_ptr)->s.size = size;
        rechain_block(controller, (Header *)new_ptr);
        set_tail(new_ptr, alloc_size);
    } else {
        set_header(new_ptr, size, filename, line);
        set_tail(new_ptr, alloc_size);
        chain_block(controller, (Header *)new_ptr);
    }
    
    new_ptr = (char *)new_ptr + sizeof(Header);
    if (size > old_size) {
        memset((char *)new_ptr + old_size, oxCC, size-old_size);
    }
#endif
        
    return new_ptr;
}
// Dequeue an operation
SolarisAttachOperation* SolarisAttachListener::dequeue() {
  for (;;) {
    int res;

    // wait for somebody to enqueue something
    while ((res = ::sema_wait(wakeup())) == EINTR)
      ;
    if (res) {
      warning("sema_wait failed: %s", os::strerror(res));
      return NULL;
    }

    // lock the list
    res = os::Solaris::mutex_lock(mutex());
    assert(res == 0, "mutex_lock failed");

    // remove the head of the list
    SolarisAttachOperation* op = head();
    if (op != NULL) {
      set_head(op->next());
      if (head() == NULL) {
        set_tail(NULL);
      }
    }

    // unlock
    os::Solaris::mutex_unlock(mutex());

    // if we got an operation when return it.
    if (op != NULL) {
      return op;
    }
  }
}
Beispiel #4
0
char *
MEM_strdup_func(MEM_Controller controller, char *filename, int line,
                char *str)
{
    char        *ptr;
    int         size;
    size_t      alloc_size;

    size = strlen(str) + 1;
#ifdef DEBUG
    alloc_size = size + sizeof(Header) + MARK_SIZE;
#else
    alloc_size = size;
#endif
    ptr = malloc(alloc_size);
    if (ptr == NULL) {
        error_handler(controller, filename, line, "strdup");
    }

#ifdef DEBUG
    memset(ptr, 0xCC, alloc_size);
    set_header((Header*)ptr, size, filename, line);
    set_tail(ptr, alloc_size);
    chain_block(controller, (Header*)ptr);
    ptr = (char*)ptr + sizeof(Header);
#endif
    strcpy(ptr, str);

    return(ptr);
}
Beispiel #5
0
void *
MEM_malloc_func(MEM_Controller controller, 
                char *filename, 
                int line, 
                size_t size)
{
    void *ptr;
    size_t alloc_size;
    
#ifdef DEBUG
    alloc_size = size + sizeof(Header) + MARK_SIZE;
#else
    alloc_size = size;
#endif
    ptr = malloc(alloc_size);
    if (ptr == NULL) {
        error_handler(controller, filename, line, "malloc");
    }
    
#ifdef DEBUG
    memset(ptr, oxCC, alloc_size);
    set_header(ptr, size, filename, line);
    set_tail(ptr, alloc_size);
    chain_block(controller, (Header *)ptr);
    ptr = (char *)ptr + sizeof(Header);
#endif

    return ptr;
}    
Beispiel #6
0
void FreeList<Chunk>::getFirstNChunksFromList(size_t n, FreeList<Chunk>* fl) {
  assert_proper_lock_protection();
  assert(fl->count() == 0, "Precondition");
  if (count() > 0) {
    int k = 1;
    fl->set_head(head()); n--;
    Chunk* tl = head();
    while (tl->next() != NULL && n > 0) {
      tl = tl->next(); n--; k++;
    }
    assert(tl != NULL, "Loop Inv.");

    // First, fix up the list we took from.
    Chunk* new_head = tl->next();
    set_head(new_head);
    set_count(count() - k);
    if (new_head == NULL) {
      set_tail(NULL);
    } else {
      new_head->link_prev(NULL);
    }
    // Now we can fix up the tail.
    tl->link_next(NULL);
    // And return the result.
    fl->set_tail(tl);
    fl->set_count(k);
  }
}
Beispiel #7
0
void FreeList<Chunk>::reset() {
  // Don't set the _size to 0 because this method is
  // used with a existing list that has a size but which has
  // been emptied.
  // Don't clear the _protecting_lock of an existing list.
  set_count(0);
  set_head(NULL);
  set_tail(NULL);
}
Beispiel #8
0
// function definition
linkedlist linkedlist_new(void)
{
    int linkedlist_size = sizeof(linkedlist_t);
    linkedlist_t* list = (linkedlist_t*) malloc(linkedlist_size);
    set_head(list, NULL);
    set_tail(list, NULL);
    list->size = 0;
    return (linkedlist) list;
}
// Enqueue an operation. This is called from a native thread that is not attached to VM.
// Also we need to be careful not to execute anything that results in more than a 4k stack.
//
int Win32AttachListener::enqueue(char* cmd, char* arg0, char* arg1, char* arg2, char* pipename) {
  // listener not running
  if (!AttachListener::is_initialized()) {
    return ATTACH_ERROR_DISABLED;
  }

  // check that all paramteres to the operation
  if (strlen(cmd) > AttachOperation::name_length_max) return ATTACH_ERROR_ILLEGALARG;
  if (strlen(arg0) > AttachOperation::arg_length_max) return ATTACH_ERROR_ILLEGALARG;
  if (strlen(arg1) > AttachOperation::arg_length_max) return ATTACH_ERROR_ILLEGALARG;
  if (strlen(arg2) > AttachOperation::arg_length_max) return ATTACH_ERROR_ILLEGALARG;
  if (strlen(pipename) > Win32AttachOperation::pipe_name_max) return ATTACH_ERROR_ILLEGALARG;

  // check for a well-formed pipename
  if (strstr(pipename, "\\\\.\\pipe\\") != pipename) return ATTACH_ERROR_ILLEGALARG;

  // grab the lock for the list
  DWORD res = ::WaitForSingleObject(mutex(), INFINITE);
  if (res != WAIT_OBJECT_0) {
    return ATTACH_ERROR_INTERNAL;
  }

  // try to get an operation from the available list
  Win32AttachOperation* op = available();
  if (op != NULL) {
    set_available(op->next());

    // add to end (tail) of list
    op->set_next(NULL);
    if (tail() == NULL) {
      set_head(op);
    } else {
      tail()->set_next(op);
    }
    set_tail(op);

    op->set_name(cmd);
    op->set_arg(0, arg0);
    op->set_arg(1, arg1);
    op->set_arg(2, arg2);
    op->set_pipe(pipename);

    // Increment number of enqueued operations.
    // Side effect: Semaphore will be signaled and will release
    // any blocking waiters (i.e. the AttachListener thread).
    BOOL not_exceeding_semaphore_maximum_count =
      ::ReleaseSemaphore(enqueued_ops_semaphore(), 1, NULL);
    guarantee(not_exceeding_semaphore_maximum_count, "invariant");
  }
  ::ReleaseMutex(mutex());

  return (op != NULL) ? 0 : ATTACH_ERROR_RESOURCE;
}
Beispiel #10
0
int add_at_last(linkedlist_t* list, void* data)
{
    node* n;
    n = node_new(data);

    // empty?
    if(NULL == get_head(list))
    {
        set_head(list, n);
        set_tail(list, n);
        list->size = 1;
        return list->size;
    }

    set_next(get_tail(list), n);
    set_prev(n, get_tail(list));
    set_tail(list, n);

    list->size++;
    return list->size;
}
// Enqueue an operation. This is called from a native thread that is not attached to VM.
// Also we need to be careful not to execute anything that results in more than a 4k stack.
//
int Win32AttachListener::enqueue(char* cmd, char* arg0, char* arg1, char* arg2, char* pipename) {
  // listener not running
  if (!AttachListener::is_initialized()) {
    return ATTACH_ERROR_DISABLED;
  }

  // check that all paramteres to the operation
  if (strlen(cmd) > AttachOperation::name_length_max) return ATTACH_ERROR_ILLEGALARG;
  if (strlen(arg0) > AttachOperation::arg_length_max) return ATTACH_ERROR_ILLEGALARG;
  if (strlen(arg0) > AttachOperation::arg_length_max) return ATTACH_ERROR_ILLEGALARG;
  if (strlen(pipename) > Win32AttachOperation::pipe_name_max) return ATTACH_ERROR_ILLEGALARG;

  // check for a well-formed pipename
  if (strstr(pipename, "\\\\.\\pipe\\") != pipename) return ATTACH_ERROR_ILLEGALARG;

  // grab the lock for the list
  DWORD res = ::WaitForSingleObject(mutex(), INFINITE);
  if (res != WAIT_OBJECT_0) {
    return ATTACH_ERROR_INTERNAL;
  }

  // try to get an operation from the available list
  Win32AttachOperation* op = available();
  if (op != NULL) {
    set_available(op->next());

    // add to end (tail) of list
    op->set_next(NULL);
    if (tail() == NULL) {
      set_head(op);
    } else {
      tail()->set_next(op);
    }
    set_tail(op);

    op->set_name(cmd);
    op->set_arg(0, arg0);
    op->set_arg(1, arg1);
    op->set_arg(2, arg2);
    op->set_pipe(pipename);

    // wakeup the thread waiting for operations
    ::ReleaseSemaphore(wakeup(), 1, NULL);
  }
  ::ReleaseMutex(mutex());

  return (op != NULL) ? 0 : ATTACH_ERROR_RESOURCE;
}
// Initialization - create the door, locks, and other initialization
int SolarisAttachListener::init() {
  if (create_door()) {
    return -1;
  }

  int status = os::Solaris::mutex_init(&_mutex);
  assert_status(status==0, status, "mutex_init");

  status = ::sema_init(&_wakeup, 0, NULL, NULL);
  assert_status(status==0, status, "sema_init");

  set_head(NULL);
  set_tail(NULL);

  return 0;
}
// Preallocate the maximum number of operations that can be enqueued.
int Win32AttachListener::init() {
  _mutex = (void*)::CreateMutex(NULL, FALSE, NULL);
  guarantee(_mutex != (HANDLE)NULL, "mutex creation failed");

  _enqueued_ops_semaphore = ::CreateSemaphore(NULL, 0, max_enqueued_operations, NULL);
  guarantee(_enqueued_ops_semaphore != (HANDLE)NULL, "semaphore creation failed");

  set_head(NULL);
  set_tail(NULL);
  set_available(NULL);

  for (int i=0; i<max_enqueued_operations; i++) {
    Win32AttachOperation* op = new Win32AttachOperation();
    op->set_next(available());
    set_available(op);
  }

  return 0;
}
// preallocate the required number of operations
int Win32AttachListener::init() {
  _mutex = (void*)::CreateMutex(NULL, FALSE, NULL);
  guarantee(_mutex != (HANDLE)NULL, "mutex creation failed");

  _wakeup = ::CreateSemaphore(NULL, 0, 1, NULL);
  guarantee(_wakeup != (HANDLE)NULL, "semaphore creation failed");

  set_head(NULL);
  set_tail(NULL);

  // preallocate a few operations
  set_available(NULL);
  for (int i=0; i<preallocate_count; i++) {
    Win32AttachOperation* op = new Win32AttachOperation();
    op->set_next(available());
    set_available(op);
  }

  return 0;
}
// Enqueue an operation
void SolarisAttachListener::enqueue(SolarisAttachOperation* op) {
  // lock list
  int res = os::Solaris::mutex_lock(mutex());
  assert(res == 0, "mutex_lock failed");

  // enqueue at tail
  op->set_next(NULL);
  if (head() == NULL) {
    set_head(op);
  } else {
    tail()->set_next(op);
  }
  set_tail(op);

  // wakeup the attach listener
  RESTARTABLE(::sema_post(wakeup()), res);
  assert(res == 0, "sema_post failed");

  // unlock
  os::Solaris::mutex_unlock(mutex());
}
Beispiel #16
0
size_t buffer_read(char* buffer, unsigned char* buf, size_t len,
                   int on_empty) {
  uint32_t available;
  uint32_t bytes;
  uint32_t tail;
  uint32_t size;
  uint32_t read;
  if (is_empty(buffer)) return on_empty;
  available = get_available(buffer);
  bytes = available > len ? len : available;
  tail = get_tail(buffer);
  size = get_size(buffer);
  read = 0;
  while (read < bytes) {
    char* value_pointer = buffer + kDataIndex + tail;
    *(buf + read) = *value_pointer;
    tail = (tail + 1) % size;
    read++;
  }
  set_tail(buffer, tail);
  return read;
}
// dequeue the operation from the head of the operation list. If
Win32AttachOperation* Win32AttachListener::dequeue() {
  for (;;) {
    DWORD res = ::WaitForSingleObject(wakeup(), INFINITE);
    guarantee(res == WAIT_OBJECT_0, "wait failed");

    res = ::WaitForSingleObject(mutex(), INFINITE);
    guarantee(res == WAIT_OBJECT_0, "wait failed");

    Win32AttachOperation* op = head();
    if (op != NULL) {
      set_head(op->next());
      if (head() == NULL) {     // list is empty
        set_tail(NULL);
      }
    }
    ::ReleaseMutex(mutex());

    if (op != NULL) {
      return op;
    }
  }
}
// dequeue the operation from the head of the operation list.
Win32AttachOperation* Win32AttachListener::dequeue() {
  for (;;) {
    DWORD res = ::WaitForSingleObject(enqueued_ops_semaphore(), INFINITE);
    // returning from WaitForSingleObject will have decreased
    // the current count of the semaphore by 1.
    guarantee(res == WAIT_OBJECT_0, "wait failed");

    res = ::WaitForSingleObject(mutex(), INFINITE);
    guarantee(res == WAIT_OBJECT_0, "wait failed");

    Win32AttachOperation* op = head();
    if (op != NULL) {
      set_head(op->next());
      if (head() == NULL) {     // list is empty
        set_tail(NULL);
      }
    }
    ::ReleaseMutex(mutex());

    if (op != NULL) {
      return op;
    }
  }
}
Beispiel #19
0
void FreeList::reset(uint hint) {
    set_count(0);
    set_head(NULL);
    set_tail(NULL);
    set_hint(hint);
}
TreeList* TreeList::removeChunkReplaceIfNeeded(TreeChunk* tc) {

  TreeList* retTL = this;
  FreeChunk* list = head();
  assert(!list || list != list->next(), "Chunk on list twice");
  assert(tc != NULL, "Chunk being removed is NULL");
  assert(parent() == NULL || this == parent()->left() || 
    this == parent()->right(), "list is inconsistent");
  assert(tc->isFree(), "Header is not marked correctly");
  assert(head() == NULL || head()->prev() == NULL, "list invariant");
  assert(tail() == NULL || tail()->next() == NULL, "list invariant");

  FreeChunk* prevFC = tc->prev();
  TreeChunk* nextTC = TreeChunk::as_TreeChunk(tc->next());
  assert(list != NULL, "should have at least the target chunk");

  // Is this the first item on the list?
  if (tc == list) {
    // The "getChunk..." functions for a TreeList will not return the
    // first chunk in the list unless it is the last chunk in the list
    // because the first chunk is also acting as the tree node.
    // When coalescing happens, however, the first chunk in the a tree
    // list can be the start of a free range.  Free ranges are removed
    // from the free lists so that they are not available to be 
    // allocated when the sweeper yields (giving up the free list lock)
    // to allow mutator activity.  If this chunk is the first in the
    // list and is not the last in the list, do the work to copy the
    // TreeList from the first chunk to the next chunk and update all
    // the TreeList pointers in the chunks in the list.
    if (nextTC == NULL) {
      assert(prevFC == NULL, "Not last chunk in the list")
      set_tail(NULL);
      set_head(NULL);
    } else {
      debug_only(
        if (PrintGC && Verbose) {
  	gclog_or_tty->print_cr("Removing first but not only chunk in TreeList");
        gclog_or_tty->print_cr("Node: " INTPTR_FORMAT " parent: " INTPTR_FORMAT
            " right: " INTPTR_FORMAT " left: " INTPTR_FORMAT, 
            tc, tc->list()->parent(), tc->list()->right(), tc->list()->left());
        gclog_or_tty->print_cr("Next before: " INTPTR_FORMAT " parent: " 
            INTPTR_FORMAT " right: " INTPTR_FORMAT " left: " INTPTR_FORMAT,
            nextTC, nextTC->list()->parent(), nextTC->list()->right(), 
  	  nextTC->list()->left());
        gclog_or_tty->print_cr("	head: " INTPTR_FORMAT " tail: " 
            INTPTR_FORMAT, nextTC->list()->head(), nextTC->list()->tail());
        }
      )
      // copy embedded list.
      nextTC->set_embedded_list(tc->embedded_list());
      retTL = nextTC->embedded_list();
      // Fix the pointer to the list in each chunk in the list.
      // This can be slow for a long list.  Consider having
      // an option that does not allow the first chunk on the
      // list to be coalesced.
      for (TreeChunk* curTC = nextTC; curTC != NULL; 
	  curTC = TreeChunk::as_TreeChunk(curTC->next())) {
        curTC->set_list(retTL);
      }
      // Fix the parent to point to the new TreeList.
      if (retTL->parent() != NULL) {
	if (this == retTL->parent()->left()) {
	  retTL->parent()->setLeft(retTL);
	} else {
	  assert(this == retTL->parent()->right(), "Parent is incorrect");
	  retTL->parent()->setRight(retTL);
	}
      }
      // Fix the children's parent pointers to point to the
      // new list.
      assert(right() == retTL->right(), "Should have been copied");
      if (retTL->right() != NULL) {
	retTL->right()->setParent(retTL);
      }
      assert(left() == retTL->left(), "Should have been copied");
      if (retTL->left() != NULL) {
	retTL->left()->setParent(retTL);
      }
      retTL->link_head(nextTC);
      debug_only(
        if (PrintGC && Verbose) {
          gclog_or_tty->print_cr("Next after: " INTPTR_FORMAT " parent: " 
            INTPTR_FORMAT " right: " INTPTR_FORMAT " left: " INTPTR_FORMAT,
            nextTC, nextTC->list()->parent(), nextTC->list()->right(), 
  	    nextTC->list()->left());
          gclog_or_tty->print_cr("	head: " INTPTR_FORMAT " tail: " 
            INTPTR_FORMAT, nextTC->list()->head(), nextTC->list()->tail());
        }
      )
      assert(nextTC->isFree(), "Should be a free chunk");
    }
Beispiel #21
0
void BitMap::resize(size_t bitset_size_, bool value){
    set_tail(value);
    bitset_size = bitset_size_;
    array.resize((bitset_size_ == 0) ? 0 : (bitset_size_ - 1) / block_size + 1, value ? ~0u : 0);
}