void chpl_free_pthread_stack(void* stack){ int free_flag; size_t page_size; free_flag = 0; page_size = 0; if(chpl_use_guard_page){ free_flag = PROT_READ | PROT_WRITE | PROT_EXEC; page_size = chpl_getSysPageSize(); mprotect((unsigned char*)stack - page_size, page_size, free_flag); chpl_free((unsigned char*)stack - page_size); } else chpl_free(stack); }
void free(void* ptr) { if( ! ptr ) return; if( DEBUG_REPLACE_MALLOC ) printf("in free(%p)\n", ptr); // check to see if we're freeing a pointer that was allocated // before the our allocator came up. if( !chpl_mem_inited() || is_system_allocated(ptr, NULL) ) { if( DEBUG_REPLACE_MALLOC ) printf("calling system free\n"); __libc_free(ptr); return; } if( DEBUG_REPLACE_MALLOC ) printf("calling chpl_free\n"); chpl_free(ptr); }
void* chpl_alloc_pthread_stack(size_t stack_size){ size_t page_size, mem_size; void* stack; void* mem_buffer; int rc; rc = 0; // Gets the system page size since we'll use it for guard pages // and guard pages are only enabled when not using a huge-pages heap. page_size = chpl_getSysPageSize(); mem_size = (chpl_use_guard_page ? stack_size + page_size : stack_size); // uses memalign to align to page_size to simplify logic for the guard page // case but thread stacks could be allocated without such alignment mem_buffer = chpl_memalign(page_size, mem_size); if(mem_buffer == NULL){ return NULL; } stack = mem_buffer; if(chpl_use_guard_page){ /* This is architecture-dependent * * Since the stack grows downward, I have to insert the guard * page at the lowest address. */ stack = (unsigned char*)mem_buffer + page_size; rc = mprotect(mem_buffer, page_size, PROT_NONE); if( rc != 0 ) { chpl_free(mem_buffer); return NULL; } } return stack; }