os0proc.c
上传用户:romrleung
上传日期:2022-05-23
资源大小:18897k
文件大小:14k
源码类别:

MySQL数据库

开发平台:

Visual C++

  1. /******************************************************
  2. The interface to the operating system
  3. process control primitives
  4. (c) 1995 Innobase Oy
  5. Created 9/30/1995 Heikki Tuuri
  6. *******************************************************/
  7. #include "os0proc.h"
  8. #ifdef UNIV_NONINL
  9. #include "os0proc.ic"
  10. #endif
  11. #include "ut0mem.h"
  12. #include "ut0byte.h"
  13. /*
  14. How to get AWE to compile on Windows?
  15. -------------------------------------
  16. In the project settings of the innobase project the Visual C++ source,
  17. __WIN2000__ has to be defined.
  18. The Visual C++ has to be relatively recent and _WIN32_WINNT has to be
  19. defined to a value >= 0x0500 when windows.h is included.
  20. #define _WIN32_WINNT 0x0500
  21. Where does AWE work?
  22. -------------------
  23. See the error message in os_awe_allocate_physical_mem().
  24. How to assign privileges for mysqld to use AWE?
  25. -----------------------------------------------
  26. See the error message in os_awe_enable_lock_pages_in_mem().
  27. Use Windows AWE functions in this order
  28. ---------------------------------------
  29. (1) os_awe_enable_lock_pages_in_mem();
  30. (2) os_awe_allocate_physical_mem();
  31. (3) os_awe_allocate_virtual_mem_window();
  32. (4) os_awe_map_physical_mem_to_window().
  33. To test 'AWE' in a computer which does not have the AWE API,
  34. you can compile with UNIV_SIMULATE_AWE defined in this file.
  35. */
  36. #ifdef UNIV_SIMULATE_AWE
  37. /* If we simulate AWE, we allocate the 'physical memory' here */
  38. byte* os_awe_simulate_mem;
  39. ulint os_awe_simulate_mem_size;
  40. os_awe_t* os_awe_simulate_page_info;
  41. byte* os_awe_simulate_window;
  42. ulint os_awe_simulate_window_size;
  43. /* In simulated AWE the following contains a NULL pointer or a pointer
  44. to a mapped 'physical page' for each 4 kB page in the AWE window */
  45. byte** os_awe_simulate_map;
  46. #endif
  47. #ifdef __WIN2000__
  48. os_awe_t* os_awe_page_info;
  49. ulint os_awe_n_pages;
  50. byte* os_awe_window;
  51. ulint os_awe_window_size;
  52. #endif
  53. /********************************************************************
  54. Windows AWE support. Tries to enable the "lock pages in memory" privilege for
  55. the current process so that the current process can allocate memory-locked
  56. virtual address space to act as the window where AWE maps physical memory. */
  57. ibool
  58. os_awe_enable_lock_pages_in_mem(void)
  59. /*=================================*/
  60. /* out: TRUE if success, FALSE if error;
  61. prints error info to stderr if no success */
  62. {
  63. #ifdef UNIV_SIMULATE_AWE
  64. return(TRUE);
  65. #elif defined(__WIN2000__)
  66.    struct {
  67.      DWORD  Count;
  68.      LUID_AND_ATTRIBUTES  Privilege[1];
  69.    }  Info;
  70. HANDLE hProcess;
  71.    HANDLE Token;
  72.    BOOL  Result;
  73. hProcess = GetCurrentProcess();
  74.    /* Open the token of the current process */
  75.    Result = OpenProcessToken(hProcess,
  76.                               TOKEN_ADJUST_PRIVILEGES,
  77.                               &Token);
  78.    if (Result != TRUE) {
  79.      fprintf(stderr,
  80. "InnoDB: AWE: Cannot open process token, error %lun",
  81. (ulint)GetLastError());
  82.      return(FALSE);
  83.    }
  84.    Info.Count = 1;
  85.      Info.Privilege[0].Attributes = SE_PRIVILEGE_ENABLED;
  86.    /* Get the local unique identifier (LUID) of the SE_LOCK_MEMORY
  87. privilege */
  88.    Result = LookupPrivilegeValue(NULL, SE_LOCK_MEMORY_NAME,
  89.                                   &(Info.Privilege[0].Luid));
  90.    if (Result != TRUE)  {
  91.      fprintf(stderr,
  92. "InnoDB: AWE: Cannot get local privilege value for %s, error %lu.n",
  93. SE_LOCK_MEMORY_NAME, (ulint)GetLastError());
  94.      return(FALSE);
  95.    }
  96.    /* Try to adjust the privilege */
  97.    Result = AdjustTokenPrivileges(Token, FALSE,
  98.                                    (PTOKEN_PRIVILEGES)&Info,
  99.                                    0, NULL, NULL);
  100.    /* Check the result */
  101.    if (Result != TRUE)  {
  102.      fprintf(stderr,
  103. "InnoDB: AWE: Cannot adjust process token privileges, error %u.n",
  104. GetLastError());
  105.      return(FALSE);
  106.    } else if (GetLastError() != ERROR_SUCCESS) {
  107.        fprintf(stderr,
  108. "InnoDB: AWE: Cannot enable SE_LOCK_MEMORY privilege, error %lu.n"
  109. "InnoDB: In Windows XP Home you cannot use AWE. In Windows 2000 and XPn"
  110. "InnoDB: Professional you must go to the Control Panel, ton"
  111. "InnoDB: Security Settings, to Local Policies, and enablen"
  112. "InnoDB: the 'lock pages in memory' privilege for the user who runsn"
  113. "InnoDB: the MySQL server.n", GetLastError());
  114. return(FALSE);
  115. }
  116. CloseHandle(Token);
  117. return(TRUE);
  118. #else
  119. #ifdef __WIN__
  120. fprintf(stderr,
  121. "InnoDB: AWE: Error: to use AWE you must use a ...-nt MySQL executable.n");
  122. #endif
  123. return(FALSE);
  124. #endif
  125. }
  126. /********************************************************************
  127. Allocates physical RAM memory up to 64 GB in an Intel 32-bit x86
  128. processor. */
  129. ibool
  130. os_awe_allocate_physical_mem(
  131. /*=========================*/
  132. /* out: TRUE if success */
  133. os_awe_t** page_info, /* out, own: array of opaque data containing
  134. the info for allocated physical memory pages;
  135. each allocated 4 kB physical memory page has
  136. one slot of type os_awe_t in the array */
  137. ulint   n_megabytes) /* in: number of megabytes to allocate */
  138. {
  139. #ifdef UNIV_SIMULATE_AWE
  140. os_awe_simulate_page_info = ut_malloc(sizeof(os_awe_t) *
  141. n_megabytes * ((1024 * 1024) / OS_AWE_X86_PAGE_SIZE));
  142. os_awe_simulate_mem = ut_align(ut_malloc(
  143. 4096 + 1024 * 1024 * n_megabytes),
  144. 4096);
  145. os_awe_simulate_mem_size = n_megabytes * 1024 * 1024;
  146. *page_info = os_awe_simulate_page_info;
  147. return(TRUE);
  148. #elif defined(__WIN2000__)
  149. BOOL bResult;
  150.    os_awe_t  NumberOfPages; /* Question: why does Windows
  151.    use the name ULONG_PTR for
  152.    a scalar integer type? Maybe
  153.    because we may also refer to
  154.    &NumberOfPages? */
  155.    os_awe_t  NumberOfPagesInitial;
  156.    SYSTEM_INFO  sSysInfo;
  157.    int  PFNArraySize;
  158. if (n_megabytes > 64 * 1024) {
  159. fprintf(stderr,
  160. "InnoDB: AWE: Error: tried to allocate %lu MB.n"
  161. "InnoDB: AWE cannot allocate more than 64 GB in any computer.n", n_megabytes);
  162. return(FALSE);
  163. }
  164.    GetSystemInfo(&sSysInfo);  /* fill the system information structure */
  165.    if ((ulint)OS_AWE_X86_PAGE_SIZE != (ulint)sSysInfo.dwPageSize) {
  166. fprintf(stderr,
  167. "InnoDB: AWE: Error: this computer has a page size of %lu.n"
  168. "InnoDB: Should be 4096 bytes for InnoDB AWE support to work.n",
  169. (ulint)sSysInfo.dwPageSize);
  170. return(FALSE);
  171. }
  172.    /* Calculate the number of pages of memory to request */
  173.    NumberOfPages = n_megabytes * ((1024 * 1024) / OS_AWE_X86_PAGE_SIZE);
  174.  
  175.   /* Calculate the size of page_info for allocated physical pages */
  176.    PFNArraySize = NumberOfPages * sizeof(os_awe_t);
  177.     *page_info = (os_awe_t*)HeapAlloc(GetProcessHeap(), 0, PFNArraySize);
  178. if (*page_info == NULL) {
  179.      fprintf(stderr,
  180. "InnoDB: AWE: Failed to allocate page info array from process heap, error %lun",
  181. (ulint)GetLastError());
  182.      return(FALSE);
  183.    }
  184. ut_total_allocated_memory += PFNArraySize;
  185.    /* Enable this process' privilege to lock pages to physical memory */
  186. if (!os_awe_enable_lock_pages_in_mem()) {
  187. return(FALSE);
  188. }
  189.    /* Allocate the physical memory */
  190.    NumberOfPagesInitial = NumberOfPages;
  191. os_awe_page_info = *page_info;
  192. os_awe_n_pages = (ulint)NumberOfPages;
  193. /* Compilation note: if the compiler complains the function is not
  194. defined, see the note at the start of this file */
  195.   bResult = AllocateUserPhysicalPages(GetCurrentProcess(),
  196.                                        &NumberOfPages,
  197.                                        *page_info);
  198.    if (bResult != TRUE) {
  199.      fprintf(stderr,
  200. "InnoDB: AWE: Cannot allocate physical pages, error %lu.n",
  201. (ulint)GetLastError());
  202.      return(FALSE);
  203.    }
  204.    if (NumberOfPagesInitial != NumberOfPages) {
  205.      fprintf(stderr,
  206. "InnoDB: AWE: Error: allocated only %lu pages of %lu requested.n"
  207. "InnoDB: Check that you have enough free RAM.n"
  208. "InnoDB: In Windows XP Professional and 2000 Professionaln"
  209. "InnoDB: Windows PAE size is max 4 GB. In 2000 and .NETn"
  210. "InnoDB: Advanced Servers and 2000 Datacenter Server it is 32 GB,n"
  211. "InnoDB: and in .NET Datacenter Server it is 64 GB.n"
  212. "InnoDB: A Microsoft web page said that the processor must be an Inteln"
  213. "InnoDB: processor.n",
  214. (ulint)NumberOfPages,
  215. (ulint)NumberOfPagesInitial);
  216.      return(FALSE);
  217.    }
  218. fprintf(stderr,
  219. "InnoDB: Using Address Windowing Extensions (AWE); allocated %lu MBn",
  220. n_megabytes);
  221. return(TRUE);
  222. #else
  223. return(FALSE);
  224. #endif
  225. }
  226. /********************************************************************
  227. Allocates a window in the virtual address space where we can map then
  228. pages of physical memory. */
  229. byte*
  230. os_awe_allocate_virtual_mem_window(
  231. /*===============================*/
  232. /* out, own: allocated memory, or NULL if did not
  233. succeed */
  234. ulint size) /* in: virtual memory allocation size in bytes, must
  235. be < 2 GB */
  236. {
  237. #ifdef UNIV_SIMULATE_AWE
  238. ulint i;
  239. os_awe_simulate_window = ut_align(ut_malloc(4096 + size), 4096);
  240. os_awe_simulate_window_size = size;
  241. os_awe_simulate_map = ut_malloc(sizeof(byte*) * (size / 4096));
  242. for (i = 0; i < (size / 4096); i++) {
  243. *(os_awe_simulate_map + i) = NULL;
  244. }
  245. return(os_awe_simulate_window);
  246. #elif defined(__WIN2000__)
  247. byte* ptr;
  248. if (size > (ulint)0x7FFFFFFFUL) {
  249. fprintf(stderr,
  250. "InnoDB: AWE: Cannot allocate %lu bytes of virtual memoryn", size);
  251. return(NULL);
  252. }
  253. ptr = VirtualAlloc(NULL, (SIZE_T)size, MEM_RESERVE | MEM_PHYSICAL,
  254. PAGE_READWRITE);
  255. if (ptr == NULL) {
  256. fprintf(stderr,
  257. "InnoDB: AWE: Cannot allocate %lu bytes of virtual memory, error %lun",
  258. size, (ulint)GetLastError());
  259. return(NULL);
  260. }
  261. os_awe_window = ptr;
  262. os_awe_window_size = size;
  263. ut_total_allocated_memory += size;
  264. return(ptr);
  265. #else
  266. return(NULL);
  267. #endif
  268. }
  269. /********************************************************************
  270. With this function you can map parts of physical memory allocated with
  271. the ..._allocate_physical_mem to the virtual address space allocated with
  272. the previous function. Intel implements this so that the process page
  273. tables are updated accordingly. A test on a 1.5 GHz AMD processor and XP
  274. showed that this takes < 1 microsecond, much better than the estimated 80 us
  275. for copying a 16 kB page memory to memory. But, the operation will at least
  276. partially invalidate the translation lookaside buffer (TLB) of all
  277. processors. Under a real-world load the performance hit may be bigger. */
  278. ibool
  279. os_awe_map_physical_mem_to_window(
  280. /*==============================*/
  281. /* out: TRUE if success; the function
  282. calls exit(1) in case of an error */
  283. byte* ptr, /* in: a page-aligned pointer to
  284. somewhere in the virtual address
  285. space window; we map the physical mem
  286. pages here */
  287. ulint n_mem_pages, /* in: number of 4 kB mem pages to
  288. map */
  289. os_awe_t* page_info) /* in: array of page infos for those
  290. pages; each page has one slot in the
  291. array */
  292. {
  293. #ifdef UNIV_SIMULATE_AWE
  294. ulint i;
  295. byte** map;
  296. byte* page;
  297. byte* phys_page;
  298. ut_a(ptr >= os_awe_simulate_window);
  299. ut_a(ptr < os_awe_simulate_window + os_awe_simulate_window_size);
  300. ut_a(page_info >= os_awe_simulate_page_info);
  301. ut_a(page_info < os_awe_simulate_page_info +
  302.   (os_awe_simulate_mem_size / 4096));
  303. /* First look if some other 'physical pages' are mapped at ptr,
  304. and copy them back to where they were if yes */
  305. map = os_awe_simulate_map
  306. + ((ulint)(ptr - os_awe_simulate_window)) / 4096;
  307. page = ptr;
  308. for (i = 0; i < n_mem_pages; i++) {
  309. if (*map != NULL) {
  310. ut_memcpy(*map, page, 4096);
  311. }
  312. map++;
  313. page += 4096;
  314. }
  315. /* Then copy to ptr the 'physical pages' determined by page_info; we
  316. assume page_info is a segment of the array we created at the start */
  317. phys_page = os_awe_simulate_mem
  318. + (ulint)(page_info - os_awe_simulate_page_info)
  319.   * 4096;
  320. ut_memcpy(ptr, phys_page, n_mem_pages * 4096);
  321. /* Update the map */
  322. map = os_awe_simulate_map
  323. + ((ulint)(ptr - os_awe_simulate_window)) / 4096;
  324. for (i = 0; i < n_mem_pages; i++) {
  325. *map = phys_page;
  326. map++;
  327. phys_page += 4096;
  328. }
  329. return(TRUE);
  330. #elif defined(__WIN2000__)
  331. BOOL bResult;
  332. os_awe_t n_pages;
  333. n_pages = (os_awe_t)n_mem_pages;
  334. if (!(ptr >= os_awe_window)) {
  335. fprintf(stderr,
  336. "InnoDB: AWE: Error: trying to map to address %lx but AWE window start %lxn",
  337. (ulint)ptr, (ulint)os_awe_window);
  338. ut_a(0);
  339. }
  340. if (!(ptr <= os_awe_window + os_awe_window_size - UNIV_PAGE_SIZE)) {
  341. fprintf(stderr,
  342. "InnoDB: AWE: Error: trying to map to address %lx but AWE window end %lxn",
  343. (ulint)ptr, (ulint)os_awe_window + os_awe_window_size);
  344. ut_a(0);
  345. }
  346. if (!(page_info >= os_awe_page_info)) {
  347. fprintf(stderr,
  348. "InnoDB: AWE: Error: trying to map page info at %lx but array start %lxn",
  349. (ulint)page_info, (ulint)os_awe_page_info);
  350. ut_a(0);
  351. }
  352. if (!(page_info <= os_awe_page_info + (os_awe_n_pages - 4))) {
  353. fprintf(stderr,
  354. "InnoDB: AWE: Error: trying to map page info at %lx but array end %lxn",
  355. (ulint)page_info, (ulint)(os_awe_page_info + os_awe_n_pages));
  356. ut_a(0);
  357. }
  358. bResult = MapUserPhysicalPages((PVOID)ptr, n_pages, page_info);
  359. if (bResult != TRUE) {
  360. ut_print_timestamp(stderr);
  361. fprintf(stderr,
  362. "  InnoDB: AWE: Mapping of %lu physical pages to address %lx failed,n"
  363. "InnoDB: error %lu.n"
  364. "InnoDB: Cannot continue operation.n",
  365. n_mem_pages, (ulint)ptr, (ulint)GetLastError());
  366. exit(1);
  367. }
  368. return(TRUE);
  369. #else
  370. return(FALSE);
  371. #endif
  372. }
  373. /********************************************************************
  374. Converts the current process id to a number. It is not guaranteed that the
  375. number is unique. In Linux returns the 'process number' of the current
  376. thread. That number is the same as one sees in 'top', for example. In Linux
  377. the thread id is not the same as one sees in 'top'. */
  378. ulint
  379. os_proc_get_number(void)
  380. /*====================*/
  381. {
  382. #ifdef __WIN__
  383. return((ulint)GetCurrentProcessId());
  384. #else
  385. return((ulint)getpid());
  386. #endif
  387. }
  388. /********************************************************************
  389. Allocates non-cacheable memory. */
  390. void*
  391. os_mem_alloc_nocache(
  392. /*=================*/
  393. /* out: allocated memory */
  394. ulint n) /* in: number of bytes */
  395. {
  396. #ifdef __WIN__
  397. void* ptr;
  398.        ptr = VirtualAlloc(NULL, n, MEM_COMMIT,
  399. PAGE_READWRITE | PAGE_NOCACHE);
  400. ut_a(ptr);
  401. return(ptr);
  402. #else
  403. return(ut_malloc(n));
  404. #endif
  405. }
  406. /********************************************************************
  407. Sets the priority boost for threads released from waiting within the current
  408. process. */
  409. void
  410. os_process_set_priority_boost(
  411. /*==========================*/
  412. ibool do_boost) /* in: TRUE if priority boost should be done,
  413. FALSE if not */
  414. {
  415. #ifdef __WIN__
  416. ibool no_boost;
  417. if (do_boost) {
  418. no_boost = FALSE;
  419. } else {
  420. no_boost = TRUE;
  421. }
  422. ut_a(TRUE == 1);
  423. /* Does not do anything currently!
  424. SetProcessPriorityBoost(GetCurrentProcess(), no_boost);
  425. */
  426. fputs("Warning: process priority boost setting currently not functional!n",
  427. stderr);
  428. #else
  429. UT_NOT_USED(do_boost);
  430. #endif
  431. }