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; }
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; } } }
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); }
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; }
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); } }
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); }
// 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; }
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()); }
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; } } }
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"); }
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); }