/************************************************************************ Create an instance of a red black tree. @return an empty rb tree */ UNIV_INTERN ib_rbt_t* rbt_create( /*=======*/ size_t sizeof_value, /*!< in: sizeof data item */ ib_rbt_compare compare) /*!< in: fn to compare items */ { ib_rbt_t* tree; ib_rbt_node_t* node; tree = (ib_rbt_t*) ut_malloc(sizeof(*tree)); memset(tree, 0, sizeof(*tree)); tree->sizeof_value = sizeof_value; /* Create the sentinel (NIL) node. */ node = tree->nil = (ib_rbt_node_t*) ut_malloc(sizeof(*node)); memset(node, 0, sizeof(*node)); node->color = IB_RBT_BLACK; node->parent = node->left = node->right = node; /* Create the "fake" root, the real root node will be the left child of this node. */ node = tree->root = (ib_rbt_node_t*) ut_malloc(sizeof(*node)); memset(node, 0, sizeof(*node)); node->color = IB_RBT_BLACK; node->parent = node->left = node->right = tree->nil; tree->compare = compare; return(tree); }
byte* os_awe_allocate_virtual_mem_window( /*===============================*/ /* out, own: allocated memory, or NULL if did not succeed */ ulint size) /* in: virtual memory allocation size in bytes, must be < 2 GB */ { #ifdef UNIV_SIMULATE_AWE ulint i; os_awe_simulate_window = ut_align(ut_malloc(4096 + size), 4096); os_awe_simulate_window_size = size; os_awe_simulate_map = ut_malloc(sizeof(byte*) * (size / 4096)); for (i = 0; i < (size / 4096); i++) { *(os_awe_simulate_map + i) = NULL; } return(os_awe_simulate_window); #elif defined(__WIN2000__) byte* ptr; if (size > (ulint)0x7FFFFFFFUL) { fprintf(stderr, "InnoDB: AWE: Cannot allocate %lu bytes" " of virtual memory\n", size); return(NULL); } ptr = VirtualAlloc(NULL, (SIZE_T)size, MEM_RESERVE | MEM_PHYSICAL, PAGE_READWRITE); if (ptr == NULL) { fprintf(stderr, "InnoDB: AWE: Cannot allocate %lu bytes" " of virtual memory, error %lu\n", size, (ulint)GetLastError()); return(NULL); } os_awe_window = ptr; os_awe_window_size = size; ut_total_allocated_memory += size; return(ptr); #else UT_NOT_USED(size); return(NULL); #endif }
/**********************************************************************//** Implements realloc. This is needed by /pars/lexyy.c. Otherwise, you should not use this function because the allocation functions in mem0mem.h are the recommended ones in InnoDB. man realloc in Linux, 2004: realloc() changes the size of the memory block pointed to by ptr to size bytes. The contents will be unchanged to the minimum of the old and new sizes; newly allocated mem- ory will be uninitialized. If ptr is NULL, the call is equivalent to malloc(size); if size is equal to zero, the call is equivalent to free(ptr). Unless ptr is NULL, it must have been returned by an earlier call to malloc(), calloc() or realloc(). RETURN VALUE realloc() returns a pointer to the newly allocated memory, which is suitably aligned for any kind of variable and may be different from ptr, or NULL if the request fails. If size was equal to 0, either NULL or a pointer suitable to be passed to free() is returned. If realloc() fails the original block is left untouched - it is not freed or moved. @return own: pointer to new mem block or NULL */ UNIV_INTERN void* ut_realloc( /*=======*/ void* ptr, /*!< in: pointer to old block or NULL */ ulint size) /*!< in: desired size */ { ut_mem_block_t* block; ulint old_size; ulint min_size; void* new_ptr; if (UNIV_LIKELY(srv_use_sys_malloc)) { return(realloc(ptr, size)); } if (ptr == NULL) { return(ut_malloc(size)); } if (size == 0) { ut_free(ptr); return(NULL); } block = (ut_mem_block_t*)((byte*)ptr - sizeof(ut_mem_block_t)); ut_a(block->magic_n == UT_MEM_MAGIC_N); old_size = block->size - sizeof(ut_mem_block_t); if (size < old_size) { min_size = size; } else { min_size = old_size; } new_ptr = ut_malloc(size); if (new_ptr == NULL) { return(NULL); } /* Copy the old data from ptr */ ut_memcpy(new_ptr, ptr, min_size); ut_free(ptr); return(new_ptr); }
/*************************************************************//** Creates a hash table with >= n array cells. The actual number of cells is chosen to be a prime number slightly bigger than n. @return own: created table */ UNIV_INTERN hash_table_t* hash_create( /*========*/ ulint n) /*!< in: number of array cells */ { hash_cell_t* array; ulint prime; hash_table_t* table; prime = ut_find_prime(n); table = mem_alloc(sizeof(hash_table_t)); array = ut_malloc(sizeof(hash_cell_t) * prime); table->array = array; table->n_cells = prime; #ifndef UNIV_HOTBACKUP # if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG table->adaptive = FALSE; # endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */ table->n_mutexes = 0; table->mutexes = NULL; table->heaps = NULL; #endif /* !UNIV_HOTBACKUP */ table->heap = NULL; ut_d(table->magic_n = HASH_TABLE_MAGIC_N); /* Initialize the cell array */ hash_table_clear(table); return(table); }
struct client_queue* client_create_shmqueue(unsigned long shm_addr, int shm_len){ int i; struct client_queue *client_q = ut_malloc(sizeof(struct client_queue)); int desc_length; g_data_offset = 8*SHM_PAGE_SIZE; client_q->recv_q.shm_queue = create_shmqueue(shm_addr,shm_len,&desc_length); client_q->recv_q.desc_head=0; client_q->recv_q.desc_list_length=0; client_q->recv_q.used_id=0; client_q->send_q.shm_queue = create_shmqueue(shm_addr+4*SHM_PAGE_SIZE,shm_len,&desc_length); client_q->send_q.desc_head=0; client_q->send_q.desc_list_length=desc_length; client_q->send_q.used_id=0; client_q->shm_start_addr = (unsigned char *)shm_addr; /* Fille the Recv queue with empty buffers */ for (i = 0; i < MAX_BUF ; i++) { client_add_buf(client_q,i,RECV); } return client_q; }
/************************************************************************ Generic insert of a value in the rb tree. @return inserted node */ UNIV_INTERN const ib_rbt_node_t* rbt_insert( /*=======*/ ib_rbt_t* tree, /*!< in: rb tree */ const void* key, /*!< in: key for ordering */ const void* value) /*!< in: value of key, this value is copied to the node */ { ib_rbt_node_t* node; /* Create the node that will hold the value data. */ node = (ib_rbt_node_t*) ut_malloc(SIZEOF_NODE(tree)); memcpy(node->value, value, tree->sizeof_value); node->parent = node->left = node->right = tree->nil; /* Insert in the tree in the usual way. */ rbt_tree_insert(tree, key, node); rbt_balance_tree(tree, node); ++tree->n_nodes; return(node); }
ibool srv_parse_log_group_home_dirs( /*==========================*/ /* out: TRUE if ok, FALSE if parsing error */ char* str, /* in: character string */ char*** log_group_home_dirs) /* out, own: log group home dirs */ { char* input_str; char* path; ulint i = 0; input_str = str; /* First calculate the number of directories and check syntax: path;path;... */ while (*str != '\0') { path = str; while (*str != ';' && *str != '\0') { str++; } i++; if (*str == ';') { str++; } else if (*str != '\0') { return(FALSE); } } *log_group_home_dirs = (char**) ut_malloc(i * sizeof(void*)); /* Then store the actual values to our array */ str = input_str; i = 0; while (*str != '\0') { path = str; while (*str != ';' && *str != '\0') { str++; } if (*str == ';') { *str = '\0'; str++; } (*log_group_home_dirs)[i] = path; i++; } return(TRUE); }
/***************************************************************//** Inserts a created memory heap to the hash table of current allocated memory heaps. */ UNIV_INTERN void mem_hash_insert( /*============*/ mem_heap_t* heap, /*!< in: the created heap */ const char* file_name, /*!< in: file name of creation */ ulint line) /*!< in: line where created */ { mem_hash_node_t* new_node; ulint cell_no ; ut_ad(mem_heap_check(heap)); mutex_enter(&mem_hash_mutex); cell_no = ut_hash_ulint((ulint)heap, MEM_HASH_SIZE); /* Allocate a new node to the list */ new_node = ut_malloc(sizeof(mem_hash_node_t)); new_node->heap = heap; new_node->file_name = file_name; new_node->line = line; new_node->nth_heap = mem_n_created_heaps; /* Insert into lists */ UT_LIST_ADD_FIRST(list, *mem_hash_get_nth_cell(cell_no), new_node); UT_LIST_ADD_LAST(all_list, mem_all_list_base, new_node); mem_n_created_heaps++; mutex_exit(&mem_hash_mutex); }
/************************************************************************ Add a new node to the tree, useful for data that is pre-sorted. @return appended node */ UNIV_INTERN const ib_rbt_node_t* rbt_add_node( /*=========*/ ib_rbt_t* tree, /*!< in: rb tree */ ib_rbt_bound_t* parent, /*!< in: bounds */ const void* value) /*!< in: this value is copied to the node */ { ib_rbt_node_t* node; /* Create the node that will hold the value data */ node = (ib_rbt_node_t*) ut_malloc(SIZEOF_NODE(tree)); memcpy(node->value, value, tree->sizeof_value); node->parent = node->left = node->right = tree->nil; /* If tree is empty */ if (parent->last == NULL) { parent->last = tree->root; } /* Append the node, the hope here is that the caller knows what s/he is doing. */ rbt_tree_add_child(tree, parent, node); rbt_balance_tree(tree, node); ++tree->n_nodes; #if defined(IB_RBT_TESTING) ut_a(rbt_validate(tree)); #endif return(node); }
sync_array_t* sync_array_create( /*==============*/ /* out, own: created wait array */ ulint n_cells, /* in: number of cells in the array to create */ ulint protection) /* in: either SYNC_ARRAY_OS_MUTEX or SYNC_ARRAY_MUTEX: determines the type of mutex protecting the data structure */ { sync_array_t* arr; sync_cell_t* cell_array; sync_cell_t* cell; ulint i; ut_a(n_cells > 0); /* Allocate memory for the data structures */ arr = ut_malloc(sizeof(sync_array_t)); cell_array = ut_malloc(sizeof(sync_cell_t) * n_cells); arr->n_cells = n_cells; arr->n_reserved = 0; arr->array = cell_array; arr->protection = protection; arr->sg_count = 0; arr->res_count = 0; /* Then create the mutex to protect the wait array complex */ if (protection == SYNC_ARRAY_OS_MUTEX) { arr->os_mutex = os_mutex_create(NULL); } else if (protection == SYNC_ARRAY_MUTEX) { mutex_create(&arr->mutex, SYNC_NO_ORDER_CHECK); } else { ut_error; } for (i = 0; i < n_cells; i++) { cell = sync_array_get_nth_cell(arr, i); cell->wait_object = NULL; cell->waiting = FALSE; cell->signal_count = 0; } return(arr); }
/*********************************************************//** Creates an operating system mutex semaphore. Because these are slow, the mutex semaphore of InnoDB itself (mutex_t) should be used where possible. @return the mutex handle */ UNIV_INTERN os_mutex_t os_mutex_create( /*============*/ const char* name) /*!< in: the name of the mutex, if NULL the mutex is created without a name */ { #ifdef __WIN__ HANDLE mutex; os_mutex_t mutex_str; mutex = CreateMutex(NULL, /* No security attributes */ FALSE, /* Initial state: no owner */ (LPCTSTR) name); ut_a(mutex); #else os_fast_mutex_t* mutex; os_mutex_t mutex_str; UT_NOT_USED(name); mutex = ut_malloc(sizeof(os_fast_mutex_t)); os_fast_mutex_init(mutex); #endif mutex_str = ut_malloc(sizeof(os_mutex_str_t)); mutex_str->handle = mutex; mutex_str->count = 0; mutex_str->event = os_event_create(NULL); if (UNIV_LIKELY(os_sync_mutex_inited)) { /* When creating os_sync_mutex itself we cannot reserve it */ os_mutex_enter(os_sync_mutex); } UT_LIST_ADD_FIRST(os_mutex_list, os_mutex_list, mutex_str); os_mutex_count++; if (UNIV_LIKELY(os_sync_mutex_inited)) { os_mutex_exit(os_sync_mutex); } return(mutex_str); }
/********************************************************************//** Creates a memory pool. @return memory pool */ UNIV_INTERN mem_pool_t* mem_pool_create( /*============*/ ulint size) /*!< in: pool size in bytes */ { mem_pool_t* pool; mem_area_t* area; ulint i; ulint used; pool = ut_malloc(sizeof(mem_pool_t)); pool->buf = ut_malloc_low(size, TRUE); pool->size = size; mutex_create(&pool->mutex, SYNC_MEM_POOL); /* Initialize the free lists */ for (i = 0; i < 64; i++) { UT_LIST_INIT(pool->free_list[i]); } used = 0; while (size - used >= MEM_AREA_MIN_SIZE) { i = ut_2_log(size - used); if (ut_2_exp(i) > size - used) { /* ut_2_log rounds upward */ i--; } area = (mem_area_t*)(pool->buf + used); mem_area_set_size(area, ut_2_exp(i)); mem_area_set_free(area, TRUE); UNIV_MEM_FREE(MEM_AREA_EXTRA_SIZE + (byte*) area, ut_2_exp(i) - MEM_AREA_EXTRA_SIZE); UT_LIST_ADD_FIRST(free_list, pool->free_list[i], area); used = used + ut_2_exp(i); } ut_ad(size >= used); pool->reserved = 0; return(pool); }
/**********************************************************************//** Creates a table memory object. @return own: table object */ UNIV_INTERN dict_table_t* dict_mem_table_create( /*==================*/ const char* name, /*!< in: table name */ ulint space, /*!< in: space where the clustered index of the table is placed; this parameter is ignored if the table is made a member of a cluster */ ulint n_cols, /*!< in: number of columns */ ulint flags) /*!< in: table flags */ { dict_table_t* table; mem_heap_t* heap; ut_ad(name); ut_a(!(flags & (~0 << DICT_TF2_BITS))); heap = mem_heap_create(DICT_HEAP_SIZE); table = mem_heap_zalloc(heap, sizeof(dict_table_t)); table->heap = heap; table->flags = (unsigned int) flags; table->name = ut_malloc(strlen(name) + 1); memcpy(table->name, name, strlen(name) + 1); table->space = (unsigned int) space; table->n_cols = (unsigned int) (n_cols + DATA_N_SYS_COLS); table->cols = mem_heap_alloc(heap, (n_cols + DATA_N_SYS_COLS) * sizeof(dict_col_t)); #ifndef UNIV_HOTBACKUP table->autoinc_lock = mem_heap_alloc(heap, lock_get_size()); mutex_create(autoinc_mutex_key, &table->autoinc_mutex, SYNC_DICT_AUTOINC_MUTEX); table->autoinc = 0; /* The number of transactions that are either waiting on the AUTOINC lock or have been granted the lock. */ table->n_waiting_or_granted_auto_inc_locks = 0; table->is_corrupt = FALSE; #endif /* !UNIV_HOTBACKUP */ ut_d(table->magic_n = DICT_TABLE_MAGIC_N); return(table); }
/*******************************************************************//** Creates a synchronization wait array. It is protected by a mutex which is automatically reserved when the functions operating on it are called. @return own: created wait array */ UNIV_INTERN sync_array_t* sync_array_create( /*==============*/ ulint n_cells, /*!< in: number of cells in the array to create */ ulint protection) /*!< in: either SYNC_ARRAY_OS_MUTEX or SYNC_ARRAY_MUTEX: determines the type of mutex protecting the data structure */ { ulint sz; sync_array_t* arr; ut_a(n_cells > 0); /* Allocate memory for the data structures */ arr = ut_malloc(sizeof(sync_array_t)); memset(arr, 0x0, sizeof(*arr)); sz = sizeof(sync_cell_t) * n_cells; arr->array = ut_malloc(sz); memset(arr->array, 0x0, sz); arr->n_cells = n_cells; arr->protection = protection; /* Then create the mutex to protect the wait array complex */ if (protection == SYNC_ARRAY_OS_MUTEX) { arr->os_mutex = os_mutex_create(); } else if (protection == SYNC_ARRAY_MUTEX) { mutex_create(syn_arr_mutex_key, &arr->mutex, SYNC_NO_ORDER_CHECK); } else { ut_error; } return(arr); }
struct place * nc_create_place (void) { struct place * p; p = ut_malloc (sizeof (struct place)); ls_insert (&u.net.places, &p->nod); p->id = u.net.numpl++; al_init (&p->pre); al_init (&p->post); al_init (&p->cont); ls_init (&p->conds); p->m = 0; return p; }
/**********************************************************************//** Add a new node to the tree, useful for data that is pre-sorted. @return appended node */ UNIV_INTERN const ib_rbt_node_t* rbt_add_node( /*=========*/ ib_rbt_t* tree, /*!< in: rb tree */ ib_rbt_bound_t* parent, /*!< in: bounds */ const void* value) /*!< in: this value is copied to the node */ { ib_rbt_node_t* node; /* Create the node that will hold the value data */ node = (ib_rbt_node_t*) ut_malloc(SIZEOF_NODE(tree)); memcpy(node->value, value, tree->sizeof_value); return(rbt_add_preallocated_node(tree, parent, node)); }
struct trans * nc_create_transition (void) { struct trans * t; t = ut_malloc (sizeof (struct trans)); ls_insert (&u.net.trans, &t->nod); t->id = ++u.net.numtr; al_init (&t->pre); al_init (&t->post); al_init (&t->cont); ls_init (&t->events); t->m = 0; t->parikhcnt1 = 0; t->parikhcnt2 = 0; return t; }
void* os_mem_alloc_nocache( /*=================*/ /* out: allocated memory */ ulint n) /* in: number of bytes */ { #ifdef __WIN__ void* ptr; ptr = VirtualAlloc(NULL, n, MEM_COMMIT, PAGE_READWRITE | PAGE_NOCACHE); ut_a(ptr); return(ptr); #else return(ut_malloc(n)); #endif }
hash_table_t* hash_create( /*========*/ /* out, own: created table */ ulint n) /* in: number of array cells */ { hash_cell_t* array; ulint prime; hash_table_t* table; ulint i; hash_cell_t* cell; prime = ut_find_prime(n); table = mem_alloc(sizeof(hash_table_t)); array = ut_malloc(sizeof(hash_cell_t) * prime); table->array = array; table->n_cells = prime; table->n_mutexes = 0; table->mutexes = NULL; table->heaps = NULL; table->heap = NULL; table->magic_n = HASH_TABLE_MAGIC_N; /* Initialize the cell array */ for (i = 0; i < prime; i++) { cell = hash_get_nth_cell(table, i); cell->node = NULL; } return(table); }
/***************************************************************//** Creates a memory heap block where data can be allocated. @return own: memory heap block, NULL if did not succeed (only possible for MEM_HEAP_BTR_SEARCH type heaps) */ UNIV_INTERN mem_block_t* mem_heap_create_block( /*==================*/ mem_heap_t* heap, /*!< in: memory heap or NULL if first block should be created */ ulint n, /*!< in: number of bytes needed for user data */ ulint type, /*!< in: type of heap: MEM_HEAP_DYNAMIC or MEM_HEAP_BUFFER */ const char* file_name,/*!< in: file name where created */ ulint line) /*!< in: line where created */ { #ifndef UNIV_HOTBACKUP buf_block_t* buf_block = NULL; #endif /* !UNIV_HOTBACKUP */ mem_block_t* block; ulint len; ut_ad((type == MEM_HEAP_DYNAMIC) || (type == MEM_HEAP_BUFFER) || (type == MEM_HEAP_BUFFER + MEM_HEAP_BTR_SEARCH)); if (heap && heap->magic_n != MEM_BLOCK_MAGIC_N) { mem_analyze_corruption(heap); } /* In dynamic allocation, calculate the size: block header + data. */ len = MEM_BLOCK_HEADER_SIZE + MEM_SPACE_NEEDED(n); #ifndef UNIV_HOTBACKUP if (type == MEM_HEAP_DYNAMIC || len < UNIV_PAGE_SIZE / 2) { ut_ad(type == MEM_HEAP_DYNAMIC || n <= MEM_MAX_ALLOC_IN_BUF); block = mem_area_alloc(&len, mem_comm_pool); } else { len = UNIV_PAGE_SIZE; if ((type & MEM_HEAP_BTR_SEARCH) && heap) { /* We cannot allocate the block from the buffer pool, but must get the free block from the heap header free block field */ buf_block = heap->free_block; heap->free_block = NULL; if (UNIV_UNLIKELY(!buf_block)) { return(NULL); } } else { buf_block = buf_block_alloc(NULL, 0); } block = (mem_block_t*) buf_block->frame; } ut_ad(block); block->buf_block = buf_block; block->free_block = NULL; #else /* !UNIV_HOTBACKUP */ len = MEM_BLOCK_HEADER_SIZE + MEM_SPACE_NEEDED(n); block = ut_malloc(len); ut_ad(block); #endif /* !UNIV_HOTBACKUP */ block->magic_n = MEM_BLOCK_MAGIC_N; ut_strlcpy_rev(block->file_name, file_name, sizeof(block->file_name)); block->line = line; #ifdef MEM_PERIODIC_CHECK mem_pool_mutex_enter(); if (!mem_block_list_inited) { mem_block_list_inited = TRUE; UT_LIST_INIT(mem_block_list); } UT_LIST_ADD_LAST(mem_block_list, mem_block_list, block); mem_pool_mutex_exit(); #endif mem_block_set_len(block, len); mem_block_set_type(block, type); mem_block_set_free(block, MEM_BLOCK_HEADER_SIZE); mem_block_set_start(block, MEM_BLOCK_HEADER_SIZE); if (UNIV_UNLIKELY(heap == NULL)) { /* This is the first block of the heap. The field total_size should be initialized here */ block->total_size = len; } else { /* Not the first allocation for the heap. This block's total_length field should be set to undefined. */ ut_d(block->total_size = ULINT_UNDEFINED); UNIV_MEM_INVALID(&block->total_size, sizeof block->total_size); heap->total_size += len; } ut_ad((ulint)MEM_BLOCK_HEADER_SIZE < len); return(block); }
ibool os_awe_allocate_physical_mem( /*=========================*/ /* out: TRUE if success */ os_awe_t** page_info, /* out, own: array of opaque data containing the info for allocated physical memory pages; each allocated 4 kB physical memory page has one slot of type os_awe_t in the array */ ulint n_megabytes) /* in: number of megabytes to allocate */ { #ifdef UNIV_SIMULATE_AWE os_awe_simulate_page_info = ut_malloc (sizeof(os_awe_t) * n_megabytes * ((1024 * 1024) / OS_AWE_X86_PAGE_SIZE)); os_awe_simulate_mem = ut_align(ut_malloc(4096 + 1024 * 1024 * n_megabytes), 4096); os_awe_simulate_mem_size = n_megabytes * 1024 * 1024; *page_info = os_awe_simulate_page_info; return(TRUE); #elif defined(__WIN2000__) BOOL bResult; os_awe_t NumberOfPages; /* Question: why does Windows use the name ULONG_PTR for a scalar integer type? Maybe because we may also refer to &NumberOfPages? */ os_awe_t NumberOfPagesInitial; SYSTEM_INFO sSysInfo; int PFNArraySize; if (n_megabytes > 64 * 1024) { fprintf(stderr, "InnoDB: AWE: Error: tried to allocate %lu MB.\n" "InnoDB: AWE cannot allocate more than" " 64 GB in any computer.\n", n_megabytes); return(FALSE); } GetSystemInfo(&sSysInfo); /* fill the system information structure */ if ((ulint)OS_AWE_X86_PAGE_SIZE != (ulint)sSysInfo.dwPageSize) { fprintf(stderr, "InnoDB: AWE: Error: this computer has a page size" " of %lu.\n" "InnoDB: Should be 4096 bytes for" " InnoDB AWE support to work.\n", (ulint)sSysInfo.dwPageSize); return(FALSE); } /* Calculate the number of pages of memory to request */ NumberOfPages = n_megabytes * ((1024 * 1024) / OS_AWE_X86_PAGE_SIZE); /* Calculate the size of page_info for allocated physical pages */ PFNArraySize = NumberOfPages * sizeof(os_awe_t); *page_info = (os_awe_t*)HeapAlloc(GetProcessHeap(), 0, PFNArraySize); if (*page_info == NULL) { fprintf(stderr, "InnoDB: AWE: Failed to allocate page info" " array from process heap, error %lu\n", (ulint)GetLastError()); return(FALSE); } ut_total_allocated_memory += PFNArraySize; /* Enable this process' privilege to lock pages to physical memory */ if (!os_awe_enable_lock_pages_in_mem()) { return(FALSE); } /* Allocate the physical memory */ NumberOfPagesInitial = NumberOfPages; os_awe_page_info = *page_info; os_awe_n_pages = (ulint)NumberOfPages; /* Compilation note: if the compiler complains the function is not defined, see the note at the start of this file */ bResult = AllocateUserPhysicalPages(GetCurrentProcess(), &NumberOfPages, *page_info); if (bResult != TRUE) { fprintf(stderr, "InnoDB: AWE: Cannot allocate physical pages," " error %lu.\n", (ulint)GetLastError()); return(FALSE); } if (NumberOfPagesInitial != NumberOfPages) { fprintf(stderr, "InnoDB: AWE: Error: allocated only %lu pages" " of %lu requested.\n" "InnoDB: Check that you have enough free RAM.\n" "InnoDB: In Windows XP Professional and" " 2000 Professional\n" "InnoDB: Windows PAE size is max 4 GB." " In 2000 and .NET\n" "InnoDB: Advanced Servers and 2000 Datacenter Server" " it is 32 GB,\n" "InnoDB: and in .NET Datacenter Server it is 64 GB.\n" "InnoDB: A Microsoft web page said that" " the processor must be an Intel\n" "InnoDB: processor.\n", (ulint)NumberOfPages, (ulint)NumberOfPagesInitial); return(FALSE); } fprintf(stderr, "InnoDB: Using Address Windowing Extensions (AWE);" " allocated %lu MB\n", n_megabytes); return(TRUE); #else UT_NOT_USED(n_megabytes); UT_NOT_USED(page_info); return(FALSE); #endif }
/*********************************************************//** Creates an event semaphore, i.e., a semaphore which may just have two states: signaled and nonsignaled. The created event is manual reset: it must be reset explicitly by calling sync_os_reset_event. @return the event handle */ UNIV_INTERN os_event_t os_event_create( /*============*/ const char* name) /*!< in: the name of the event, if NULL the event is created without a name */ { #ifdef __WIN__ os_event_t event; event = ut_malloc(sizeof(struct os_event_struct)); event->handle = CreateEvent(NULL, /* No security attributes */ TRUE, /* Manual reset */ FALSE, /* Initial state nonsignaled */ (LPCTSTR) name); if (!event->handle) { fprintf(stderr, "InnoDB: Could not create a Windows event semaphore;" " Windows error %lu\n", (ulong) GetLastError()); } #else /* Unix */ os_event_t event; UT_NOT_USED(name); event = ut_malloc(sizeof(struct os_event_struct)); os_fast_mutex_init(&(event->os_mutex)); ut_a(0 == pthread_cond_init(&(event->cond_var), NULL)); event->is_set = FALSE; /* We return this value in os_event_reset(), which can then be be used to pass to the os_event_wait_low(). The value of zero is reserved in os_event_wait_low() for the case when the caller does not want to pass any signal_count value. To distinguish between the two cases we initialize signal_count to 1 here. */ event->signal_count = 1; #endif /* __WIN__ */ /* The os_sync_mutex can be NULL because during startup an event can be created [ because it's embedded in the mutex/rwlock ] before this module has been initialized */ if (os_sync_mutex != NULL) { os_mutex_enter(os_sync_mutex); } /* Put to the list of events */ UT_LIST_ADD_FIRST(os_event_list, os_event_list, event); os_event_count++; if (os_sync_mutex != NULL) { os_mutex_exit(os_sync_mutex); } return(event); }
/********************************************************************//** Allocates memory from a pool. NOTE: This low-level function should only be used in mem0mem.*! @return own: allocated memory buffer */ UNIV_INTERN void* mem_area_alloc( /*===========*/ ulint* psize, /*!< in: requested size in bytes; for optimum space usage, the size should be a power of 2 minus MEM_AREA_EXTRA_SIZE; out: allocated size in bytes (greater than or equal to the requested size) */ mem_pool_t* pool) /*!< in: memory pool */ { mem_area_t* area; ulint size; ulint n; ibool ret; /* If we are using os allocator just make a simple call to malloc */ if (UNIV_LIKELY(srv_use_sys_malloc)) { return(malloc(*psize)); } size = *psize; n = ut_2_log(ut_max(size + MEM_AREA_EXTRA_SIZE, MEM_AREA_MIN_SIZE)); mutex_enter(&(pool->mutex)); mem_n_threads_inside++; ut_a(mem_n_threads_inside == 1); area = UT_LIST_GET_FIRST(pool->free_list[n]); if (area == NULL) { ret = mem_pool_fill_free_list(n, pool); if (ret == FALSE) { /* Out of memory in memory pool: we try to allocate from the operating system with the regular malloc: */ mem_n_threads_inside--; mutex_exit(&(pool->mutex)); return(ut_malloc(size)); } area = UT_LIST_GET_FIRST(pool->free_list[n]); } if (!mem_area_get_free(area)) { fprintf(stderr, "InnoDB: Error: Removing element from mem pool" " free list %lu though the\n" "InnoDB: element is not marked free!\n", (ulong) n); mem_analyze_corruption(area); /* Try to analyze a strange assertion failure reported at [email protected] where the free bit IS 1 in the hex dump above */ if (mem_area_get_free(area)) { fprintf(stderr, "InnoDB: Probably a race condition" " because now the area is marked free!\n"); } ut_error; } if (UT_LIST_GET_LEN(pool->free_list[n]) == 0) { fprintf(stderr, "InnoDB: Error: Removing element from mem pool" " free list %lu\n" "InnoDB: though the list length is 0!\n", (ulong) n); mem_analyze_corruption(area); ut_error; } ut_ad(mem_area_get_size(area) == ut_2_exp(n)); mem_area_set_free(area, FALSE); UT_LIST_REMOVE(free_list, pool->free_list[n], area); pool->reserved += mem_area_get_size(area); mem_n_threads_inside--; mutex_exit(&(pool->mutex)); ut_ad(mem_pool_validate(pool)); *psize = ut_2_exp(n) - MEM_AREA_EXTRA_SIZE; UNIV_MEM_ALLOC(MEM_AREA_EXTRA_SIZE + (byte*)area, *psize); return((void*)(MEM_AREA_EXTRA_SIZE + ((byte*)area))); }
/********************************************************************** When doing a DROP TABLE/DISCARD TABLESPACE we have to drop all page hash index entries belonging to that table. This function tries to do that in batch. Note that this is a 'best effort' attempt and does not guarantee that ALL hash entries will be removed. */ static void buf_LRU_drop_page_hash_for_tablespace( /*==================================*/ ulint id) /* in: space id */ { buf_block_t* block; ulint* page_arr; ulint num_entries; page_arr = ut_malloc(sizeof(ulint) * BUF_LRU_DROP_SEARCH_HASH_SIZE); mutex_enter(&buf_pool->mutex); scan_again: num_entries = 0; block = UT_LIST_GET_LAST(buf_pool->LRU); while (block != NULL) { buf_block_t* prev_block; mutex_enter(&block->mutex); prev_block = UT_LIST_GET_PREV(LRU, block); ut_a(block->state == BUF_BLOCK_FILE_PAGE); if (block->space != id || block->buf_fix_count > 0 || block->io_fix != 0) { /* We leave the fixed pages as is in this scan. To be dealt with later in the final scan. */ mutex_exit(&block->mutex); goto next_page; } ut_ad(block->space == id); if (block->is_hashed) { /* Store the offset(i.e.: page_no) in the array so that we can drop hash index in a batch later. */ page_arr[num_entries] = block->offset; mutex_exit(&block->mutex); ut_a(num_entries < BUF_LRU_DROP_SEARCH_HASH_SIZE); ++num_entries; if (num_entries < BUF_LRU_DROP_SEARCH_HASH_SIZE) { goto next_page; } /* Array full. We release the buf_pool->mutex to obey the latching order. */ mutex_exit(&buf_pool->mutex); buf_LRU_drop_page_hash_batch(id, page_arr, num_entries); num_entries = 0; mutex_enter(&buf_pool->mutex); } else { mutex_exit(&block->mutex); } next_page: /* Note that we may have released the buf_pool->mutex above after reading the prev_block during processing of a page_hash_batch (i.e.: when the array was full). This means that prev_block can change in LRU list. This is OK because this function is a 'best effort' to drop as many search hash entries as possible and it does not guarantee that ALL such entries will be dropped. */ block = prev_block; /* If, however, block has been removed from LRU list to the free list then we should restart the scan. block->state is protected by buf_pool->mutex. */ if (block && block->state != BUF_BLOCK_FILE_PAGE) { ut_a(num_entries == 0); goto scan_again; } } mutex_exit(&buf_pool->mutex); /* Drop any remaining batch of search hashed pages. */ buf_LRU_drop_page_hash_batch(id, page_arr, num_entries); ut_free(page_arr); }
ibool srv_parse_data_file_paths_and_sizes( /*================================*/ /* out: TRUE if ok, FALSE if parsing error */ char* str, /* in: the data file path string */ char*** data_file_names, /* out, own: array of data file names */ ulint** data_file_sizes, /* out, own: array of data file sizes in megabytes */ ulint** data_file_is_raw_partition,/* out, own: array of flags showing which data files are raw partitions */ ulint* n_data_files, /* out: number of data files */ ibool* is_auto_extending, /* out: TRUE if the last data file is auto-extending */ ulint* max_auto_extend_size) /* out: max auto extend size for the last file if specified, 0 if not */ { char* input_str; char* endp; char* path; ulint size; ulint i = 0; *is_auto_extending = FALSE; *max_auto_extend_size = 0; input_str = str; /* First calculate the number of data files and check syntax: path:size[M | G];path:size[M | G]... . Note that a Windows path may contain a drive name and a ':'. */ while (*str != '\0') { path = str; while ((*str != ':' && *str != '\0') || (*str == ':' && (*(str + 1) == '\\' || *(str + 1) == '/'))) { str++; } if (*str == '\0') { return(FALSE); } str++; size = strtoul(str, &endp, 10); str = endp; if (*str != 'M' && *str != 'G') { size = size / (1024 * 1024); } else if (*str == 'G') { size = size * 1024; str++; } else { str++; } if (strlen(str) >= ut_strlen(":autoextend") && 0 == ut_memcmp(str, (char*)":autoextend", ut_strlen(":autoextend"))) { str += ut_strlen(":autoextend"); if (strlen(str) >= ut_strlen(":max:") && 0 == ut_memcmp(str, (char*)":max:", ut_strlen(":max:"))) { str += ut_strlen(":max:"); size = strtoul(str, &endp, 10); str = endp; if (*str != 'M' && *str != 'G') { size = size / (1024 * 1024); } else if (*str == 'G') { size = size * 1024; str++; } else { str++; } } if (*str != '\0') { return(FALSE); } } if (strlen(str) >= 6 && *str == 'n' && *(str + 1) == 'e' && *(str + 2) == 'w') { str += 3; } if (strlen(str) >= 3 && *str == 'r' && *(str + 1) == 'a' && *(str + 2) == 'w') { str += 3; } if (size == 0) { return(FALSE); } i++; if (*str == ';') { str++; } else if (*str != '\0') { return(FALSE); } } *data_file_names = (char**)ut_malloc(i * sizeof(void*)); *data_file_sizes = (ulint*)ut_malloc(i * sizeof(ulint)); *data_file_is_raw_partition = (ulint*)ut_malloc(i * sizeof(ulint)); *n_data_files = i; /* Then store the actual values to our arrays */ str = input_str; i = 0; while (*str != '\0') { path = str; /* Note that we must ignore the ':' in a Windows path */ while ((*str != ':' && *str != '\0') || (*str == ':' && (*(str + 1) == '\\' || *(str + 1) == '/'))) { str++; } if (*str == ':') { /* Make path a null-terminated string */ *str = '\0'; str++; } size = strtoul(str, &endp, 10); str = endp; if ((*str != 'M') && (*str != 'G')) { size = size / (1024 * 1024); } else if (*str == 'G') { size = size * 1024; str++; } else { str++; } (*data_file_names)[i] = path; (*data_file_sizes)[i] = size; if (strlen(str) >= ut_strlen(":autoextend") && 0 == ut_memcmp(str, (char*)":autoextend", ut_strlen(":autoextend"))) { *is_auto_extending = TRUE; str += ut_strlen(":autoextend"); if (strlen(str) >= ut_strlen(":max:") && 0 == ut_memcmp(str, (char*)":max:", ut_strlen(":max:"))) { str += ut_strlen(":max:"); size = strtoul(str, &endp, 10); str = endp; if (*str != 'M' && *str != 'G') { size = size / (1024 * 1024); } else if (*str == 'G') { size = size * 1024; str++; } else { str++; } *max_auto_extend_size = size; } if (*str != '\0') { return(FALSE); } } (*data_file_is_raw_partition)[i] = 0; if (strlen(str) >= 6 && *str == 'n' && *(str + 1) == 'e' && *(str + 2) == 'w') { str += 3; (*data_file_is_raw_partition)[i] = SRV_NEW_RAW; } if (strlen(str) >= 3 && *str == 'r' && *(str + 1) == 'a' && *(str + 2) == 'w') { str += 3; if ((*data_file_is_raw_partition)[i] == 0) { (*data_file_is_raw_partition)[i] = SRV_OLD_RAW; } } i++; if (*str == ';') { str++; } } return(TRUE); }
mem_area_t *area, ibool free) { area->size_and_free = (area->size_and_free & ~MEM_AREA_FREE) | free; } mem_pool_t* mem_pool_create( ulint size) { mem_pool_t* pool; mem_area_t* area; ulint i; ulint used; pool = ut_maloc(sizeof(mem_pool_t)); pool_buf = ut_malloc(size); pool_size = size; mutex_create(&(pool->mutex)); mutex_set_level(&(pool->mutex), SYNC_MEM_POOL); for(i = 0; i < 64; i++) { UT_LIST_INIT(pool->free_list[i]); } used = 0; while(size - used >= MEM_AREA_MIN_SIZE) { i = ut_2_log(size - used); if (ut_2_exp(i) > size - used) { i--; }
mem_pool_t* mem_pool_create( /*============*/ /* out: memory pool */ ulint size) /* in: pool size in bytes */ { mem_pool_t* pool; mem_area_t* area; ulint i; ulint used; ut_a(size > 10000); pool = ut_malloc(sizeof(mem_pool_t)); /* We do not set the memory to zero (FALSE) in the pool, but only when allocated at a higher level in mem0mem.c. This is to avoid masking useful Purify warnings. */ pool->buf = ut_malloc_low(size, FALSE, TRUE); pool->size = size; mutex_create(&pool->mutex, SYNC_MEM_POOL); /* Initialize the free lists */ for (i = 0; i < 64; i++) { UT_LIST_INIT(pool->free_list[i]); } used = 0; while (size - used >= MEM_AREA_MIN_SIZE) { i = ut_2_log(size - used); if (ut_2_exp(i) > size - used) { /* ut_2_log rounds upward */ i--; } area = (mem_area_t*)(pool->buf + used); mem_area_set_size(area, ut_2_exp(i)); mem_area_set_free(area, TRUE); UNIV_MEM_FREE(MEM_AREA_EXTRA_SIZE + (byte*) area, ut_2_exp(i) - MEM_AREA_EXTRA_SIZE); UT_LIST_ADD_FIRST(free_list, pool->free_list[i], area); used = used + ut_2_exp(i); } ut_ad(size >= used); pool->reserved = 0; return(pool); }
ibool srv_parse_data_file_paths_and_sizes( /*================================*/ /* out: TRUE if ok, FALSE if parsing error */ char* str, /* in: the data file path string */ char*** data_file_names, /* out, own: array of data file names */ ulint** data_file_sizes, /* out, own: array of data file sizes in megabytes */ ulint** data_file_is_raw_partition,/* out, own: array of flags showing which data files are raw partitions */ ulint* n_data_files, /* out: number of data files */ ibool* is_auto_extending, /* out: TRUE if the last data file is auto-extending */ ulint* max_auto_extend_size) /* out: max auto extend size for the last file if specified, 0 if not */ { char* input_str; char* path; ulint size; ulint i = 0; *is_auto_extending = FALSE; *max_auto_extend_size = 0; input_str = str; /* First calculate the number of data files and check syntax: path:size[M | G];path:size[M | G]... . Note that a Windows path may contain a drive name and a ':'. */ while (*str != '\0') { path = str; while ((*str != ':' && *str != '\0') || (*str == ':' && (*(str + 1) == '\\' || *(str + 1) == '/' || *(str + 1) == ':'))) { str++; } if (*str == '\0') { return(FALSE); } str++; str = srv_parse_megabytes(str, &size); if (0 == strncmp(str, ":autoextend", (sizeof ":autoextend") - 1)) { str += (sizeof ":autoextend") - 1; if (0 == strncmp(str, ":max:", (sizeof ":max:") - 1)) { str += (sizeof ":max:") - 1; str = srv_parse_megabytes(str, &size); } if (*str != '\0') { return(FALSE); } } if (strlen(str) >= 6 && *str == 'n' && *(str + 1) == 'e' && *(str + 2) == 'w') { str += 3; } if (*str == 'r' && *(str + 1) == 'a' && *(str + 2) == 'w') { str += 3; } if (size == 0) { return(FALSE); } i++; if (*str == ';') { str++; } else if (*str != '\0') { return(FALSE); } } if (i == 0) { /* If innodb_data_file_path was defined it must contain at least one data file definition */ return(FALSE); } *data_file_names = (char**)ut_malloc(i * sizeof(void*)); *data_file_sizes = (ulint*)ut_malloc(i * sizeof(ulint)); *data_file_is_raw_partition = (ulint*)ut_malloc(i * sizeof(ulint)); *n_data_files = i; /* Then store the actual values to our arrays */ str = input_str; i = 0; while (*str != '\0') { path = str; /* Note that we must step over the ':' in a Windows path; a Windows path normally looks like C:\ibdata\ibdata1:1G, but a Windows raw partition may have a specification like \\.\C::1Gnewraw or \\.\PHYSICALDRIVE2:1Gnewraw */ while ((*str != ':' && *str != '\0') || (*str == ':' && (*(str + 1) == '\\' || *(str + 1) == '/' || *(str + 1) == ':'))) { str++; } if (*str == ':') { /* Make path a null-terminated string */ *str = '\0'; str++; } str = srv_parse_megabytes(str, &size); (*data_file_names)[i] = path; (*data_file_sizes)[i] = size; if (0 == strncmp(str, ":autoextend", (sizeof ":autoextend") - 1)) { *is_auto_extending = TRUE; str += (sizeof ":autoextend") - 1; if (0 == strncmp(str, ":max:", (sizeof ":max:") - 1)) { str += (sizeof ":max:") - 1; str = srv_parse_megabytes( str, max_auto_extend_size); } if (*str != '\0') { return(FALSE); } } (*data_file_is_raw_partition)[i] = 0; if (strlen(str) >= 6 && *str == 'n' && *(str + 1) == 'e' && *(str + 2) == 'w') { str += 3; (*data_file_is_raw_partition)[i] = SRV_NEW_RAW; } if (*str == 'r' && *(str + 1) == 'a' && *(str + 2) == 'w') { str += 3; if ((*data_file_is_raw_partition)[i] == 0) { (*data_file_is_raw_partition)[i] = SRV_OLD_RAW; } } i++; if (*str == ';') { str++; } } return(TRUE); }