1 /** 2 * Operating system specific routines. 3 * 4 * Placed here to avoid cluttering 5 * up code with OS files. 6 * 7 * Compiler implementation of the 8 * $(LINK2 https://www.dlang.org, D programming language). 9 * 10 * Copyright: Copyright (C) 1994-1998 by Symantec 11 * Copyright (C) 2000-2023 by The D Language Foundation, All Rights Reserved 12 * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) 13 * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) 14 * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/backend/os.d, backend/os.d) 15 */ 16 17 module dmd.backend.os; 18 19 import core.stdc.stdio; 20 import core.stdc.time; 21 import core.stdc.stdlib; 22 import core.stdc.string; 23 24 version (Posix) 25 { 26 import core.stdc.errno; 27 import core.sys.posix.fcntl; 28 import core.sys.posix.pthread; 29 import core.sys.posix.sys.stat; 30 import core.sys.posix.sys.types; 31 import core.sys.posix.unistd; 32 //#define GetLastError() errno 33 } 34 else version (Windows) 35 { 36 import core.sys.windows.stat; 37 import core.sys.windows.winbase; 38 import core.sys.windows.windef; 39 } 40 41 version (CRuntime_Microsoft) 42 enum NEEDS_WIN32_NON_MS = false; 43 else version (Win32) 44 enum NEEDS_WIN32_NON_MS = true; 45 else 46 enum NEEDS_WIN32_NON_MS = false; 47 48 version (Win64) 49 enum NEEDS_WIN32_NOT_WIN64 = false; 50 else version (Win32) 51 enum NEEDS_WIN32_NOT_WIN64 = true; 52 else 53 enum NEEDS_WIN32_NOT_WIN64 = false; 54 55 56 extern(C++): 57 58 nothrow: 59 @safe: 60 61 version (CRuntime_Microsoft) 62 { 63 import core.stdc.stdlib; 64 } 65 //debug = printf; 66 version (Windows) 67 { 68 extern(C++) void dll_printf(const char *format,...); 69 alias printf = dll_printf; 70 } 71 72 /*********************************** 73 * Called when there is an error returned by the operating system. 74 * This function does not return. 75 */ 76 void os_error(int line = __LINE__) 77 { 78 version(Windows) 79 debug(printf) printf("System error: %ldL\n", GetLastError()); 80 assert(0); 81 } 82 83 static if (NEEDS_WIN32_NOT_WIN64) 84 { 85 86 private __gshared HANDLE hHeap; 87 88 @trusted 89 void *globalrealloc(void *oldp,size_t newsize) 90 { 91 static if (0) 92 { 93 void *p; 94 95 // Initialize heap 96 if (!hHeap) 97 { hHeap = HeapCreate(0,0x10000,0); 98 if (!hHeap) 99 os_error(); 100 } 101 102 newsize = (newsize + 3) & ~3L; // round up to dwords 103 if (newsize == 0) 104 { 105 if (oldp && HeapFree(hHeap,0,oldp) == false) 106 os_error(); 107 p = NULL; 108 } 109 else if (!oldp) 110 { 111 p = newsize ? HeapAlloc(hHeap,0,newsize) : null; 112 } 113 else 114 p = HeapReAlloc(hHeap,0,oldp,newsize); 115 } 116 else static if (1) 117 { 118 MEMORY_BASIC_INFORMATION query; 119 void *p; 120 BOOL bSuccess; 121 122 if (!oldp) 123 p = VirtualAlloc (null, newsize, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); 124 else 125 { 126 VirtualQuery (oldp, &query, query.sizeof); 127 if (!newsize) 128 { 129 p = null; 130 goto L1; 131 } 132 else 133 { newsize = (newsize + 0xFFFF) & ~0xFFFFL; 134 135 if (query.RegionSize >= newsize) 136 p = oldp; 137 else 138 { p = VirtualAlloc(null,newsize,MEM_COMMIT | MEM_RESERVE,PAGE_READWRITE); 139 if (p) 140 memcpy(p,oldp,query.RegionSize); 141 L1: 142 bSuccess = VirtualFree(oldp,query.RegionSize,MEM_DECOMMIT); 143 if (bSuccess) 144 bSuccess = VirtualFree(oldp,0,MEM_RELEASE); 145 if (!bSuccess) 146 os_error(); 147 } 148 } 149 } 150 } 151 else 152 { 153 void *p; 154 155 if (!oldp) 156 p = cast(void *)GlobalAlloc (0, newsize); 157 else if (!newsize) 158 { GlobalFree(oldp); 159 p = null; 160 } 161 else 162 p = cast(void *)GlobalReAlloc(oldp,newsize,0); 163 } 164 debug(printf) printf("globalrealloc(oldp = %p, size = x%x) = %p\n",oldp,newsize,p); 165 return p; 166 } 167 168 /***************************************** 169 * Functions to manage allocating a single virtual address space. 170 */ 171 172 @trusted 173 void *vmem_reserve(void *ptr,uint size) 174 { void *p; 175 176 version(none) 177 { 178 p = VirtualAlloc(ptr,size,MEM_RESERVE,PAGE_READWRITE); 179 debug(printf) printf("vmem_reserve(ptr = %p, size = x%lx) = %p\n",ptr,size,p); 180 } 181 else 182 { 183 debug(printf) printf("vmem_reserve(ptr = %p, size = x%lx) = %p\n",ptr,size,p); 184 p = VirtualAlloc(ptr,size,MEM_RESERVE,PAGE_READWRITE); 185 if (!p) 186 os_error(); 187 } 188 return p; 189 } 190 191 /***************************************** 192 * Commit memory. 193 * Returns: 194 * 0 failure 195 * !=0 success 196 */ 197 198 @trusted 199 int vmem_commit(void *ptr, uint size) 200 { int i; 201 202 debug(printf) printf("vmem_commit(ptr = %p,size = x%lx)\n",ptr,size); 203 i = cast(int) VirtualAlloc(ptr,size,MEM_COMMIT,PAGE_READWRITE); 204 if (i == 0) 205 debug(printf) printf("failed to commit\n"); 206 return i; 207 } 208 209 @trusted 210 void vmem_decommit(void *ptr,uint size) 211 { 212 debug(printf) printf("vmem_decommit(ptr = %p, size = x%lx)\n",ptr,size); 213 if (ptr) 214 { if (!VirtualFree(ptr, size, MEM_DECOMMIT)) 215 os_error(); 216 } 217 } 218 219 @trusted 220 void vmem_release(void *ptr, uint size) 221 { 222 debug(printf) printf("vmem_release(ptr = %p, size = x%lx)\n",ptr,size); 223 if (ptr) 224 { 225 if (!VirtualFree(ptr, 0, MEM_RELEASE)) 226 os_error(); 227 } 228 } 229 230 /******************************************** 231 * Map file for read, copy on write, into virtual address space. 232 * Input: 233 * ptr address to map file to, if NULL then pick an address 234 * size length of the file 235 * flag 0 read / write 236 * 1 read / copy on write 237 * 2 read only 238 * Returns: 239 * NULL failure 240 * ptr pointer to start of mapped file 241 */ 242 243 private __gshared HANDLE hFile = INVALID_HANDLE_VALUE; 244 private __gshared HANDLE hFileMap = null; 245 private __gshared void *pview; 246 private __gshared void *preserve; 247 private __gshared size_t preserve_size; 248 249 @trusted 250 void *vmem_mapfile(const char *filename,void *ptr, uint size,int flag) 251 { 252 OSVERSIONINFO OsVerInfo; 253 254 OsVerInfo.dwOSVersionInfoSize = OsVerInfo.sizeof; 255 GetVersionEx(&OsVerInfo); 256 257 debug(printf) printf("vmem_mapfile(filename = '%s', ptr = %p, size = x%lx, flag = %d)\n", 258 filename,ptr,size,flag); 259 260 hFile = CreateFileA(filename, GENERIC_READ | GENERIC_WRITE, 261 FILE_SHARE_READ | FILE_SHARE_WRITE, null, 262 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, null); 263 if (hFile == INVALID_HANDLE_VALUE) 264 goto L1; // failure 265 debug(printf) printf(" file created\n"); 266 267 // Windows 95 does not implement PAGE_WRITECOPY (unfortunately treating 268 // it just like PAGE_READWRITE). 269 if (flag == 1 && OsVerInfo.dwPlatformId == 1) // Windows 95, 98, ME 270 hFileMap = null; 271 else 272 hFileMap = CreateFileMappingA(hFile,null, 273 (flag == 1) ? PAGE_WRITECOPY : PAGE_READWRITE,0,size,null); 274 275 if (hFileMap == null) // mapping failed 276 { 277 version(all) 278 { 279 // Win32s seems to always fail here. 280 DWORD nbytes; 281 282 debug(printf) printf(" mapping failed\n"); 283 // If it was NT failing, assert. 284 assert(OsVerInfo.dwPlatformId != VER_PLATFORM_WIN32_NT); 285 286 // To work around, just read the file into memory. 287 assert(flag == 1); 288 preserve = vmem_reserve(ptr,size); 289 if (!preserve) 290 goto L2; 291 if (!vmem_commit(preserve,size)) 292 { 293 vmem_release(preserve,size); 294 preserve = null; 295 goto L2; 296 } 297 preserve_size = size; 298 if (!ReadFile(hFile,preserve,size,&nbytes,null)) 299 os_error(); 300 assert(nbytes == size); 301 if (CloseHandle(hFile) != true) 302 os_error(); 303 hFile = INVALID_HANDLE_VALUE; 304 return preserve; 305 } 306 else 307 { 308 // Instead of working around, we should find out why it failed. 309 os_error(); 310 } 311 312 } 313 else 314 { 315 debug(printf) printf(" mapping created\n"); 316 pview = MapViewOfFileEx(hFileMap,flag ? FILE_MAP_COPY : FILE_MAP_WRITE, 317 0,0,size,ptr); 318 if (pview == null) // mapping view failed 319 { //os_error(); 320 goto L3; 321 } 322 } 323 debug(printf) printf(" pview = %p\n",pview); 324 325 return pview; 326 327 L3: 328 if (CloseHandle(hFileMap) != true) 329 os_error(); 330 hFileMap = null; 331 L2: 332 if (CloseHandle(hFile) != true) 333 os_error(); 334 hFile = INVALID_HANDLE_VALUE; 335 L1: 336 return null; // failure 337 } 338 339 /***************************** 340 * Set size of mapped file. 341 */ 342 343 @trusted 344 void vmem_setfilesize(uint size) 345 { 346 if (hFile != INVALID_HANDLE_VALUE) 347 { if (SetFilePointer(hFile,size,null,FILE_BEGIN) == 0xFFFFFFFF) 348 os_error(); 349 if (SetEndOfFile(hFile) == false) 350 os_error(); 351 } 352 } 353 354 /***************************** 355 * Unmap previous file mapping. 356 */ 357 358 @trusted 359 void vmem_unmapfile() 360 { 361 debug(printf) printf("vmem_unmapfile()\n"); 362 363 vmem_decommit(preserve,preserve_size); 364 vmem_release(preserve,preserve_size); 365 preserve = null; 366 preserve_size = 0; 367 368 version(none) 369 { 370 if (pview) 371 { int i; 372 373 i = UnmapViewOfFile(pview); 374 debug(printf) printf("i = x%x\n",i); 375 if (i == false) 376 os_error(); 377 } 378 } 379 else 380 { 381 // Note that under Windows 95, UnmapViewOfFile() seems to return random 382 // values, not TRUE or FALSE. 383 if (pview && UnmapViewOfFile(pview) == false) 384 os_error(); 385 } 386 pview = null; 387 388 if (hFileMap != null && CloseHandle(hFileMap) != true) 389 os_error(); 390 hFileMap = null; 391 392 if (hFile != INVALID_HANDLE_VALUE && CloseHandle(hFile) != true) 393 os_error(); 394 hFile = INVALID_HANDLE_VALUE; 395 } 396 397 /**************************************** 398 * Determine a base address that we can use for mapping files to. 399 */ 400 401 @trusted 402 void *vmem_baseaddr() 403 { 404 OSVERSIONINFO OsVerInfo; 405 void *p; 406 407 OsVerInfo.dwOSVersionInfoSize = OsVerInfo.sizeof; 408 GetVersionEx(&OsVerInfo); 409 410 // These values for the address were determined by trial and error. 411 switch (OsVerInfo.dwPlatformId) 412 { 413 case VER_PLATFORM_WIN32s: // Win32s 414 // The fact that this is a different address than other 415 // WIN32 implementations causes us a lot of grief. 416 p = cast(void *) 0xC0000000; 417 break; 418 419 case 1: //VER_PLATFORM_WIN32_WINDOWS: // Windows 95 420 // I've found 0x90000000..0xB work. All others fail. 421 default: // unknown 422 p = cast(void *) 0x90000000; 423 break; 424 425 case VER_PLATFORM_WIN32_NT: // Windows NT 426 // Pick a value that is not coincident with the base address 427 // of any commonly used system DLLs. 428 p = cast(void *) 0x38000000; 429 break; 430 } 431 432 return p; 433 } 434 435 /******************************************** 436 * Calculate the amount of memory to reserve, adjusting 437 * *psize downwards. 438 */ 439 440 @trusted 441 void vmem_reservesize(uint *psize) 442 { 443 MEMORYSTATUS ms; 444 OSVERSIONINFO OsVerInfo; 445 446 uint size; 447 448 ms.dwLength = ms.sizeof; 449 GlobalMemoryStatus(&ms); 450 debug(printf) printf("dwMemoryLoad x%lx\n",ms.dwMemoryLoad); 451 debug(printf) printf("dwTotalPhys x%lx\n",ms.dwTotalPhys); 452 debug(printf) printf("dwAvailPhys x%lx\n",ms.dwAvailPhys); 453 debug(printf) printf("dwTotalPageFile x%lx\n",ms.dwTotalPageFile); 454 debug(printf) printf("dwAvailPageFile x%lx\n",ms.dwAvailPageFile); 455 debug(printf) printf("dwTotalVirtual x%lx\n",ms.dwTotalVirtual); 456 debug(printf) printf("dwAvailVirtual x%lx\n",ms.dwAvailVirtual); 457 458 459 OsVerInfo.dwOSVersionInfoSize = OsVerInfo.sizeof; 460 GetVersionEx(&OsVerInfo); 461 462 switch (OsVerInfo.dwPlatformId) 463 { 464 case VER_PLATFORM_WIN32s: // Win32s 465 case 1: //VER_PLATFORM_WIN32_WINDOWS: // Windows 95 466 default: // unknown 467 size = (ms.dwAvailPageFile < ms.dwAvailVirtual) 468 ? ms.dwAvailPageFile 469 : ms.dwAvailVirtual; 470 size = cast(ulong)size * 8 / 10; 471 size &= ~0xFFFF; 472 if (size < *psize) 473 *psize = size; 474 break; 475 476 case VER_PLATFORM_WIN32_NT: // Windows NT 477 // NT can expand the paging file 478 break; 479 } 480 481 } 482 483 /******************************************** 484 * Return amount of physical memory. 485 */ 486 487 @trusted 488 uint vmem_physmem() 489 { 490 MEMORYSTATUS ms; 491 492 ms.dwLength = ms.sizeof; 493 GlobalMemoryStatus(&ms); 494 return ms.dwTotalPhys; 495 } 496 497 ////////////////////////////////////////////////////////////// 498 499 /*************************************************** 500 * Load library. 501 */ 502 503 private __gshared HINSTANCE hdll; 504 505 @trusted 506 void os_loadlibrary(const char *dllname) 507 { 508 hdll = LoadLibrary(cast(LPCTSTR) dllname); 509 if (!hdll) 510 os_error(); 511 } 512 513 /************************************************* 514 */ 515 516 @trusted 517 void os_freelibrary() 518 { 519 if (hdll) 520 { 521 if (FreeLibrary(hdll) != true) 522 os_error(); 523 hdll = null; 524 } 525 } 526 527 /************************************************* 528 */ 529 530 @trusted 531 void *os_getprocaddress(const char *funcname) 532 { void *fp; 533 534 //printf("getprocaddress('%s')\n",funcname); 535 assert(hdll); 536 fp = cast(void *)GetProcAddress(hdll,cast(LPCSTR)funcname); 537 if (!fp) 538 os_error(); 539 return fp; 540 } 541 542 ////////////////////////////////////////////////////////////// 543 544 545 /********************************* 546 */ 547 548 @trusted 549 void os_term() 550 { 551 if (hHeap) 552 { if (HeapDestroy(hHeap) == false) 553 { hHeap = null; 554 os_error(); 555 } 556 hHeap = null; 557 } 558 os_freelibrary(); 559 } 560 561 /*************************************************** 562 * Do our own storage allocator (being suspicious of the library one). 563 */ 564 565 version(all) 566 { 567 void os_heapinit() { } 568 void os_heapterm() { } 569 570 } 571 else 572 { 573 static HANDLE hHeap; 574 575 void os_heapinit() 576 { 577 hHeap = HeapCreate(0,0x10000,0); 578 if (!hHeap) 579 os_error(); 580 } 581 582 void os_heapterm() 583 { 584 if (hHeap) 585 { if (HeapDestroy(hHeap) == false) 586 os_error(); 587 } 588 } 589 590 extern(Windows) void * calloc(size_t x,size_t y) 591 { size_t size; 592 593 size = x * y; 594 return size ? HeapAlloc(hHeap,HEAP_ZERO_MEMORY,size) : null; 595 } 596 597 extern(Windows) void free(void *p) 598 { 599 if (p && HeapFree(hHeap,0,p) == false) 600 os_error(); 601 } 602 603 extern(Windows) void * malloc(size_t size) 604 { 605 return size ? HeapAlloc(hHeap,0,size) : null; 606 } 607 608 extern(Windows) void * realloc(void *p,size_t newsize) 609 { 610 if (newsize == 0) 611 free(p); 612 else if (!p) 613 p = malloc(newsize); 614 else 615 p = HeapReAlloc(hHeap,0,p,newsize); 616 return p; 617 } 618 619 } 620 621 ////////////////////////////////////////// 622 // Return a value that will hopefully be unique every time 623 // we call it. 624 625 @trusted 626 uint os_unique() 627 { 628 ulong x; 629 630 QueryPerformanceCounter(cast(LARGE_INTEGER *)&x); 631 return cast(uint)x; 632 } 633 634 } // Win32 635 636 /******************************************* 637 * Return !=0 if file exists. 638 * 0: file doesn't exist 639 * 1: normal file 640 * 2: directory 641 */ 642 643 @trusted 644 int os_file_exists(const char *name) 645 { 646 version(Windows) 647 { 648 DWORD dw; 649 int result; 650 651 dw = GetFileAttributesA(name); 652 if (dw == -1L) 653 result = 0; 654 else if (dw & FILE_ATTRIBUTE_DIRECTORY) 655 result = 2; 656 else 657 result = 1; 658 return result; 659 } 660 else version(Posix) 661 { 662 stat_t buf; 663 664 return stat(name,&buf) == 0; /* file exists if stat succeeded */ 665 666 } 667 else 668 { 669 return filesize(name) != -1L; 670 } 671 } 672 673 /************************************** 674 * Get file size of open file. Return -1L on error. 675 */ 676 677 static if(NEEDS_WIN32_NON_MS) 678 { 679 extern extern (C) void*[] _osfhnd; 680 } 681 682 @trusted 683 long os_file_size(int fd) 684 { 685 static if (NEEDS_WIN32_NON_MS) 686 { 687 return GetFileSize(_osfhnd[fd],null); 688 } 689 else 690 { 691 version(Windows) 692 { 693 return GetFileSize(cast(void*)_get_osfhandle(fd),null); 694 } 695 else 696 { 697 stat_t buf; 698 return (fstat(fd,&buf)) ? -1L : buf.st_size; 699 } 700 } 701 } 702 703 /************************************************** 704 * For 16 bit programs, we need the 16 bit filename. 705 * Returns: 706 * malloc'd string, NULL if none 707 */ 708 709 version(Windows) 710 { 711 @trusted 712 char *file_8dot3name(const char *filename) 713 { 714 HANDLE h; 715 WIN32_FIND_DATAA fileinfo; 716 char *buf; 717 size_t i; 718 719 h = FindFirstFileA(filename,&fileinfo); 720 if (h == INVALID_HANDLE_VALUE) 721 return null; 722 if (fileinfo.cAlternateFileName[0]) 723 { 724 for (i = strlen(filename); i > 0; i--) 725 if (filename[i] == '\\' || filename[i] == ':') 726 { i++; 727 break; 728 } 729 buf = cast(char *) malloc(i + 14); 730 if (buf) 731 { 732 memcpy(buf,filename,i); 733 strcpy(buf + i,fileinfo.cAlternateFileName.ptr); 734 } 735 } 736 else 737 buf = strdup(filename); 738 FindClose(h); 739 return buf; 740 } 741 } 742 743 /********************************************** 744 * Write a file. 745 * Returns: 746 * 0 success 747 */ 748 749 @trusted 750 int file_write(char *name, void *buffer, uint len) 751 { 752 version(Posix) 753 { 754 int fd; 755 ssize_t numwritten; 756 757 fd = open(name, O_CREAT | O_WRONLY | O_TRUNC, 758 S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); 759 if (fd == -1) 760 goto err; 761 762 numwritten = .write(fd, buffer, len); 763 if (len != numwritten) 764 goto err2; 765 766 if (close(fd) == -1) 767 goto err; 768 769 return 0; 770 771 err2: 772 close(fd); 773 err: 774 return 1; 775 } 776 else version(Windows) 777 { 778 HANDLE h; 779 DWORD numwritten; 780 781 h = CreateFileA(cast(LPCSTR)name,GENERIC_WRITE,0,null,CREATE_ALWAYS, 782 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,null); 783 if (h == INVALID_HANDLE_VALUE) 784 { 785 if (GetLastError() == ERROR_PATH_NOT_FOUND) 786 { 787 if (!file_createdirs(name)) 788 { 789 h = CreateFileA(cast(LPCSTR)name, GENERIC_WRITE, 0, null, CREATE_ALWAYS, 790 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,null); 791 if (h != INVALID_HANDLE_VALUE) 792 goto Lok; 793 } 794 } 795 goto err; 796 } 797 798 Lok: 799 if (WriteFile(h,buffer,len,&numwritten,null) != true) 800 goto err2; 801 802 if (len != numwritten) 803 goto err2; 804 805 if (!CloseHandle(h)) 806 goto err; 807 return 0; 808 809 err2: 810 CloseHandle(h); 811 err: 812 return 1; 813 } 814 } 815 816 /******************************** 817 * Create directories up to filename. 818 * Input: 819 * name path/filename 820 * Returns: 821 * 0 success 822 * !=0 failure 823 */ 824 825 @trusted 826 int file_createdirs(char *name) 827 { 828 version(Posix) 829 { 830 return 1; 831 } 832 else version(Windows) 833 { 834 auto len = strlen(name); 835 char *path = cast(char *)alloca(len + 1); 836 char *p; 837 838 memcpy(path, name, len + 1); 839 840 for (p = path + len; ; p--) 841 { 842 if (p == path) 843 goto Lfail; 844 switch (*p) 845 { 846 case ':': 847 case '/': 848 case '\\': 849 *p = 0; 850 if (!CreateDirectory(cast(LPTSTR)path, null)) 851 { // Failed 852 if (file_createdirs(path)) 853 goto Lfail; 854 if (!CreateDirectory(cast(LPTSTR)path, null)) 855 goto Lfail; 856 } 857 return 0; 858 default: 859 continue; 860 } 861 } 862 863 Lfail: 864 return 1; 865 } 866 } 867 868 /*********************************** 869 * Returns: 870 * result of C library clock() 871 */ 872 873 int os_clock() 874 { 875 return cast(int) clock(); 876 } 877 878 /*********************************** 879 * Return size of OS critical section. 880 * NOTE: can't use the sizeof() calls directly since cross compiling is 881 * supported and would end up using the host sizes rather than the target 882 * sizes. 883 */ 884 885 886 887 version(Windows) 888 { 889 int os_critsecsize32() 890 { 891 return 24; // sizeof(CRITICAL_SECTION) for 32 bit Windows 892 } 893 894 int os_critsecsize64() 895 { 896 return 40; // sizeof(CRITICAL_SECTION) for 64 bit Windows 897 } 898 } 899 else version(linux) 900 { 901 int os_critsecsize32() 902 { 903 return 24; // sizeof(pthread_mutex_t) on 32 bit 904 } 905 906 int os_critsecsize64() 907 { 908 return 40; // sizeof(pthread_mutex_t) on 64 bit 909 } 910 } 911 912 else version(FreeBSD) 913 { 914 int os_critsecsize32() 915 { 916 return 4; // sizeof(pthread_mutex_t) on 32 bit 917 } 918 919 int os_critsecsize64() 920 { 921 return 8; // sizeof(pthread_mutex_t) on 64 bit 922 } 923 } 924 925 else version(OpenBSD) 926 { 927 int os_critsecsize32() 928 { 929 return 4; // sizeof(pthread_mutex_t) on 32 bit 930 } 931 932 int os_critsecsize64() 933 { 934 return 8; // sizeof(pthread_mutex_t) on 64 bit 935 } 936 } 937 else version(DragonFlyBSD) 938 { 939 int os_critsecsize32() 940 { 941 return 4; // sizeof(pthread_mutex_t) on 32 bit 942 } 943 944 int os_critsecsize64() 945 { 946 return 8; // sizeof(pthread_mutex_t) on 64 bit 947 } 948 } 949 950 else version (OSX) 951 { 952 int os_critsecsize32() 953 { 954 version(X86_64) 955 { 956 assert(pthread_mutex_t.sizeof == 64); 957 } 958 else 959 { 960 assert(pthread_mutex_t.sizeof == 44); 961 } 962 return 44; 963 } 964 965 int os_critsecsize64() 966 { 967 return 64; 968 } 969 } 970 971 else version(Solaris) 972 { 973 int os_critsecsize32() 974 { 975 assert(pthread_mutex_t.sizeof == 24); 976 return 24; 977 } 978 979 int os_critsecsize64() 980 { 981 assert(pthread_mutex_t.sizeof == 24); 982 return 24; 983 } 984 } 985 986 /* This is the magic program to get the size on Posix systems: 987 988 #if 0 989 #include <stdio.h> 990 #include <pthread.h> 991 992 int main() 993 { 994 printf("%d\n", (int)sizeof(pthread_mutex_t)); 995 return 0; 996 } 997 #endif 998 999 #endif 1000 */