summaryrefslogtreecommitdiff
path: root/innobase/os
diff options
context:
space:
mode:
authorunknown <heikki@hundin.mysql.fi>2003-01-06 22:07:25 +0200
committerunknown <heikki@hundin.mysql.fi>2003-01-06 22:07:25 +0200
commit9497c997041e20baab3ebaa985c9e29235fdf0ca (patch)
tree88f03b8d4b471aa94f27b4a3ed510bcd7c2c3ccb /innobase/os
parentef62b4c948d68108c0945ebde33540b03b392a6d (diff)
downloadmariadb-git-9497c997041e20baab3ebaa985c9e29235fdf0ca.tar.gz
buf0buf.c, buf0buf.ic, buf0buf.h:
Reduce memory usage of the buffer headers Many files: Merge InnoDB-4.1 with AWE support sql/mysqld.cc: Merge InnoDB-4.1 with AWE support sql/set_var.cc: Merge InnoDB-4.1 with AWE support sql/ha_innodb.h: Merge InnoDB-4.1 with AWE support sql/ha_innodb.cc: Merge InnoDB-4.1 with AWE support innobase/btr/btr0cur.c: Merge InnoDB-4.1 with AWE support innobase/btr/btr0pcur.c: Merge InnoDB-4.1 with AWE support innobase/buf/buf0flu.c: Merge InnoDB-4.1 with AWE support innobase/buf/buf0lru.c: Merge InnoDB-4.1 with AWE support innobase/buf/buf0rea.c: Merge InnoDB-4.1 with AWE support innobase/include/btr0pcur.h: Merge InnoDB-4.1 with AWE support innobase/include/buf0lru.h: Merge InnoDB-4.1 with AWE support innobase/include/log0recv.h: Merge InnoDB-4.1 with AWE support innobase/include/os0proc.h: Merge InnoDB-4.1 with AWE support innobase/include/srv0srv.h: Merge InnoDB-4.1 with AWE support innobase/log/log0log.c: Merge InnoDB-4.1 with AWE support innobase/log/log0recv.c: Merge InnoDB-4.1 with AWE support innobase/os/os0file.c: Merge InnoDB-4.1 with AWE support innobase/os/os0proc.c: Merge InnoDB-4.1 with AWE support innobase/srv/srv0srv.c: Merge InnoDB-4.1 with AWE support innobase/srv/srv0start.c: Merge InnoDB-4.1 with AWE support innobase/trx/trx0sys.c: Merge InnoDB-4.1 with AWE support innobase/trx/trx0trx.c: Merge InnoDB-4.1 with AWE support innobase/ut/ut0ut.c: Merge InnoDB-4.1 with AWE support innobase/include/buf0buf.h: Reduce memory usage of the buffer headers innobase/include/buf0buf.ic: Reduce memory usage of the buffer headers innobase/buf/buf0buf.c: Reduce memory usage of the buffer headers
Diffstat (limited to 'innobase/os')
-rw-r--r--innobase/os/os0file.c2
-rw-r--r--innobase/os/os0proc.c462
2 files changed, 461 insertions, 3 deletions
diff --git a/innobase/os/os0file.c b/innobase/os/os0file.c
index fa5482a8cd1..9eae358c7fb 100644
--- a/innobase/os/os0file.c
+++ b/innobase/os/os0file.c
@@ -2127,7 +2127,7 @@ os_aio_simulated_handle(
ulint offs;
ulint lowest_offset;
byte* combined_buf;
- byte* combined_buf2= 0; /* Remove warning */
+ byte* combined_buf2;
ibool ret;
ulint n;
ulint i;
diff --git a/innobase/os/os0proc.c b/innobase/os/os0proc.c
index 1ee448a4a44..61db7bd13b2 100644
--- a/innobase/os/os0proc.c
+++ b/innobase/os/os0proc.c
@@ -12,11 +12,469 @@ Created 9/30/1995 Heikki Tuuri
#include "os0proc.ic"
#endif
+#include "ut0mem.h"
+#include "ut0byte.h"
+
+
+/*
+How to get AWE to compile on Windows?
+-------------------------------------
+
+the Visual C++ has to be relatively recent and _WIN32_WINNT has to be
+defined to a value >= 0x0500 when windows.h is included. An easy way
+to accomplish that is to put
+
+#define _WIN32_WINNT 0x0500
+
+to the start of file \mysql\include\config-win.h
+
+Where does AWE work?
+-------------------
+
+See the error message in os_awe_allocate_physical_mem().
+
+How to assign privileges for mysqld to use AWE?
+-----------------------------------------------
+
+See the error message in os_awe_enable_lock_pages_in_mem().
+
+Use Windows AWE functions in this order
+---------------------------------------
+
+(1) os_awe_enable_lock_pages_in_mem();
+(2) os_awe_allocate_physical_mem();
+(3) os_awe_allocate_virtual_mem_window();
+(4) os_awe_map_physical_mem_to_window().
+
+To test 'AWE' in a computer which does not have the AWE API,
+you can compile with UNIV_SIMULATE_AWE defined in this file.
+*/
+
+#ifdef UNIV_SIMULATE_AWE
+/* If we simulate AWE, we allocate the 'physical memory' here */
+byte* os_awe_simulate_mem;
+ulint os_awe_simulate_mem_size;
+os_awe_t* os_awe_simulate_page_info;
+byte* os_awe_simulate_window;
+ulint os_awe_simulate_window_size;
+/* In simulated AWE the following contains a NULL pointer or a pointer
+to a mapped 'physical page' for each 4 kB page in the AWE window */
+byte** os_awe_simulate_map;
+#endif
+
+#ifdef __NT__
+os_awe_t* os_awe_page_info;
+ulint os_awe_n_pages;
+byte* os_awe_window;
+ulint os_awe_window_size;
+#endif
+
+/********************************************************************
+Windows AWE support. Tries to enable the "lock pages in memory" privilege for
+the current process so that the current process can allocate memory-locked
+virtual address space to act as the window where AWE maps physical memory. */
+
+ibool
+os_awe_enable_lock_pages_in_mem(void)
+/*=================================*/
+ /* out: TRUE if success, FALSE if error;
+ prints error info to stderr if no success */
+{
+#ifdef UNIV_SIMULATE_AWE
+
+ return(TRUE);
+
+#elif defined(__NT__)
+ struct {
+ DWORD Count;
+ LUID_AND_ATTRIBUTES Privilege[1];
+ } Info;
+ HANDLE hProcess;
+ HANDLE Token;
+ BOOL Result;
+
+ hProcess = GetCurrentProcess();
+
+ /* Open the token of the current process */
+
+ Result = OpenProcessToken(hProcess,
+ TOKEN_ADJUST_PRIVILEGES,
+ &Token);
+ if (Result != TRUE) {
+ fprintf(stderr,
+ "InnoDB: AWE: Cannot open process token, error %lu\n",
+ (ulint)GetLastError());
+ return(FALSE);
+ }
+
+ Info.Count = 1;
+
+ Info.Privilege[0].Attributes = SE_PRIVILEGE_ENABLED;
+
+ /* Get the local unique identifier (LUID) of the SE_LOCK_MEMORY
+ privilege */
+
+ Result = LookupPrivilegeValue(NULL, SE_LOCK_MEMORY_NAME,
+ &(Info.Privilege[0].Luid));
+ if (Result != TRUE) {
+ fprintf(stderr,
+ "InnoDB: AWE: Cannot get local privilege value for %s, error %lu.\n",
+ SE_LOCK_MEMORY_NAME, (ulint)GetLastError());
+
+ return(FALSE);
+ }
+
+ /* Try to adjust the privilege */
+
+ Result = AdjustTokenPrivileges(Token, FALSE,
+ (PTOKEN_PRIVILEGES)&Info,
+ 0, NULL, NULL);
+ /* Check the result */
+
+ if (Result != TRUE) {
+ fprintf(stderr,
+ "InnoDB: AWE: Cannot adjust process token privileges, error %u.\n",
+ GetLastError());
+ return(FALSE);
+ } else if (GetLastError() != ERROR_SUCCESS) {
+ fprintf(stderr,
+"InnoDB: AWE: Cannot enable SE_LOCK_MEMORY privilege, error %lu.\n"
+"InnoDB: In Windows XP Home you cannot use AWE. In Windows 2000 and XP\n"
+"InnoDB: Professional you must go to the Control Panel, to\n"
+"InnoDB: Security Settings, to Local Policies, and enable\n"
+"InnoDB: the 'lock pages in memory' privilege for the user who runs\n"
+"InnoDB: the MySQL server.\n", GetLastError());
+
+ return(FALSE);
+ }
+
+ CloseHandle(Token);
+
+ return(TRUE);
+#else
#ifdef __WIN__
-#include <windows.h>
+ fprintf(stderr,
+"InnoDB: AWE: Error: to use AWE you must use a ...-nt MySQL executable.\n");
+#endif
+ return(FALSE);
#endif
+}
-#include "ut0mem.h"
+/********************************************************************
+Allocates physical RAM memory up to 64 GB in an Intel 32-bit x86
+processor. */
+
+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(__NT__)
+ BOOL bResult;
+ ULONG_PTR NumberOfPages; /* Question: why does Windows
+ use the name ULONG_PTR for
+ a scalar integer type? Maybe
+ because we may also refer to
+ &NumberOfPages? */
+ ULONG_PTR 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(ULONG_PTR);
+
+ *page_info = (ULONG_PTR*)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"
+"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.",
+ (ulint)NumberOfPages,
+ (ulint)NumberOfPagesInitial);
+
+ return(FALSE);
+ }
+
+ fprintf(stderr,
+"InnoDB: Using Address Windowing Extensions (AWE); allocated %lu MB\n",
+ n_megabytes);
+
+ return(TRUE);
+#else
+ return(FALSE);
+#endif
+}
+
+/********************************************************************
+Allocates a window in the virtual address space where we can map then
+pages of physical memory. */
+
+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(__NT__)
+ byte* ptr;
+
+ if (size > 0x7FFFFFFFFF) {
+ 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
+ return(NULL);
+#endif
+}
+
+/********************************************************************
+With this function you can map parts of physical memory allocated with
+the ..._allocate_physical_mem to the virtual address space allocated with
+the previous function. Intel implements this so that the process page
+tables are updated accordingly. A test on a 1.5 GHz AMD processor and XP
+showed that this takes < 1 microsecond, much better than the estimated 80 us
+for copying a 16 kB page memory to memory. But, the operation will at least
+partially invalidate the translation lookaside buffer (TLB) of all
+processors. Under a real-world load the performance hit may be bigger. */
+
+ibool
+os_awe_map_physical_mem_to_window(
+/*==============================*/
+ /* out: TRUE if success; the function
+ calls exit(1) in case of an error */
+ byte* ptr, /* in: a page-aligned pointer to
+ somewhere in the virtual address
+ space window; we map the physical mem
+ pages here */
+ ulint n_mem_pages, /* in: number of 4 kB mem pages to
+ map */
+ os_awe_t* page_info) /* in: array of page infos for those
+ pages; each page has one slot in the
+ array */
+{
+#ifdef UNIV_SIMULATE_AWE
+ ulint i;
+ byte** map;
+ byte* page;
+ byte* phys_page;
+
+ ut_a(ptr >= os_awe_simulate_window);
+ ut_a(ptr < os_awe_simulate_window + os_awe_simulate_window_size);
+ ut_a(page_info >= os_awe_simulate_page_info);
+ ut_a(page_info < os_awe_simulate_page_info +
+ (os_awe_simulate_mem_size / 4096));
+
+ /* First look if some other 'physical pages' are mapped at ptr,
+ and copy them back to where they were if yes */
+
+ map = os_awe_simulate_map
+ + ((ulint)(ptr - os_awe_simulate_window)) / 4096;
+ page = ptr;
+
+ for (i = 0; i < n_mem_pages; i++) {
+ if (*map != NULL) {
+ ut_memcpy(*map, page, 4096);
+ }
+ map++;
+ page += 4096;
+ }
+
+ /* Then copy to ptr the 'physical pages' determined by page_info; we
+ assume page_info is a segment of the array we created at the start */
+
+ phys_page = os_awe_simulate_mem
+ + (ulint)(page_info - os_awe_simulate_page_info)
+ * 4096;
+
+ ut_memcpy(ptr, phys_page, n_mem_pages * 4096);
+
+ /* Update the map */
+
+ map = os_awe_simulate_map
+ + ((ulint)(ptr - os_awe_simulate_window)) / 4096;
+
+ for (i = 0; i < n_mem_pages; i++) {
+ *map = phys_page;
+
+ map++;
+ phys_page += 4096;
+ }
+
+ return(TRUE);
+
+#elif defined(__NT__)
+ BOOL bResult;
+ ULONG_PTR n_pages;
+
+ n_pages = (ULONG_PTR)n_mem_pages;
+
+ if (!(ptr >= os_awe_window)) {
+ fprintf(stderr,
+"InnoDB: AWE: Error: trying to map to address %lx but AWE window start %lx\n",
+ (ulint)ptr, (ulint)os_awe_window);
+ ut_a(0);
+ }
+
+ if (!(ptr <= os_awe_window + os_awe_window_size - UNIV_PAGE_SIZE)) {
+ fprintf(stderr,
+"InnoDB: AWE: Error: trying to map to address %lx but AWE window end %lx\n",
+ (ulint)ptr, (ulint)os_awe_window + os_awe_window_size);
+ ut_a(0);
+ }
+
+ if (!(page_info >= os_awe_page_info)) {
+ fprintf(stderr,
+"InnoDB: AWE: Error: trying to map page info at %lx but array start %lx\n",
+ (ulint)page_info, (ulint)os_awe_page_info);
+ ut_a(0);
+ }
+
+ if (!(page_info <= os_awe_page_info + (os_awe_n_pages - 4))) {
+ fprintf(stderr,
+"InnoDB: AWE: Error: trying to map page info at %lx but array end %lx\n",
+ (ulint)page_info, (ulint)(os_awe_page_info + os_awe_n_pages));
+ ut_a(0);
+ }
+
+ bResult = MapUserPhysicalPages((PVOID)ptr, n_pages, page_info);
+
+ if (bResult != TRUE) {
+ ut_print_timestamp(stderr);
+ fprintf(stderr,
+" InnoDB: AWE: Mapping of %lu physical pages to address %lx failed,\n"
+"InnoDB: error %lu.\n"
+"InnoDB: Cannot continue operation.\n",
+ n_mem_pages, (ulint)ptr, (ulint)GetLastError());
+ exit(1);
+ }
+
+ return(TRUE);
+#else
+ return(FALSE);
+#endif
+}
/********************************************************************
Converts the current process id to a number. It is not guaranteed that the