Changeset 4496 for trunk/src/kernel32/mmap.cpp
- Timestamp:
- Oct 18, 2000, 7:09:34 PM (25 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/kernel32/mmap.cpp
r4230 r4496 1 /* $Id: mmap.cpp,v 1.4 4 2000-09-10 21:54:07sandervl Exp $ */1 /* $Id: mmap.cpp,v 1.45 2000-10-18 17:09:33 sandervl Exp $ */ 2 2 3 3 /* … … 34 34 #include <winimagepeldr.h> 35 35 36 #define DBG_LOCALLOG 36 #define DBG_LOCALLOG DBG_mmap 37 37 #include "dbglocal.h" 38 38 … … 69 69 70 70 if(lpszName) { 71 72 73 } 74 else 71 lpszMapName = (char *)_smalloc(strlen(lpszName)+1); 72 strcpy(lpszMapName, lpszName); 73 } 74 else lpszMapName = NULL; 75 75 } 76 76 //****************************************************************************** … … 105 105 { 106 106 #if 0 107 107 if(DuplicateHandle(mProcessId, hMemFile, GetCurrentProcess(), 108 108 &hMemFile, 0, FALSE, DUPLICATE_SAME_ACCESS) == FALSE) 109 109 #else 110 111 112 113 114 115 elsedwOdinOptions = DUPLICATE_ACCESS_READWRITE | DUPLICATE_SHARE_DENYNONE;116 117 110 DWORD dwOdinOptions; 111 112 if(!(mProtFlags & PAGE_READWRITE)) { 113 dwOdinOptions = DUPLICATE_ACCESS_READ | DUPLICATE_SHARE_DENYNONE; 114 } 115 else dwOdinOptions = DUPLICATE_ACCESS_READWRITE | DUPLICATE_SHARE_DENYNONE; 116 117 if(HMDuplicateHandleOdin(mProcessId, hMemFile, GetCurrentProcess(), 118 118 &hMemFile, 0, FALSE, DUPLICATE_SAME_ACCESS, dwOdinOptions) == FALSE) 119 119 #endif 120 121 122 123 124 125 126 127 128 129 130 120 { 121 dprintf(("Win32MemMap::Init: DuplicateHandle failed!")); 122 goto fail; 123 } 124 mSize = SetFilePointer(hMemFile, 0, NULL, FILE_BEGIN); 125 mSize = SetFilePointer(hMemFile, 0, NULL, FILE_END); 126 if(mSize == -1) { 127 dprintf(("Win32MemMap::init: SetFilePointer failed to set pos end")); 128 goto fail; 129 } 130 //SvL: Temporary limitation of size (Warp Server Advanced doesn't allow 131 131 // one to reserve more than 450 MB (unless you override the virtual 132 132 // memory max limit) of continuous memory; (Warp 4 much less)) 133 134 135 133 if(mSize > 64*1024*1024) { 134 mSize = 64*1024*1024; 135 } 136 136 } 137 137 … … 154 154 mapMutex.enter(); 155 155 if(lpszMapName) { 156 156 free(lpszMapName); 157 157 } 158 158 if(pMapping && !image) { 159 160 161 162 elseVirtualFree(pMapping, mSize, MEM_RELEASE);163 164 159 if(lpszMapName) { 160 OSLibDosFreeMem(pMapping); 161 } 162 else VirtualFree(pMapping, mSize, MEM_RELEASE); 163 164 pMapping = NULL; 165 165 } 166 166 if(hMemFile != -1) { 167 CloseHandle(hMemFile); 168 hMemFile = -1; 167 dprintf(("Win32MemMap dtor: closing memory file %x", hMemFile)); 168 CloseHandle(hMemFile); 169 hMemFile = -1; 169 170 } 170 171 mapMutex.leave(); … … 174 175 175 176 if(map == this) { 176 177 memmaps = next; 177 178 } 178 179 else { 179 180 181 182 183 184 185 186 187 elsedprintf(("Win32MemMap::~Win32MemMap: map not found!! (%x)", this));180 while(map->next) { 181 if(map->next == this) 182 break; 183 map = map->next; 184 } 185 if(map->next) { 186 map->next = next; 187 } 188 else dprintf(("Win32MemMap::~Win32MemMap: map not found!! (%x)", this)); 188 189 } 189 190 globalmapMutex.leave(&hGlobalMapMutex); 191 } 192 //****************************************************************************** 193 //If memory map has no more views left, then we can safely delete it when 194 //it's handle is closed 195 //****************************************************************************** 196 void Win32MemMap::close() 197 { 198 fClosed = TRUE; 199 if(nrMappings == 0) { 200 delete this; 201 } 190 202 } 191 203 //****************************************************************************** … … 205 217 206 218 if(image) { 207 219 return image->commitPage(pageAddr, fWriteAccess); 208 220 } 209 221 newProt = mProtFlags & (PAGE_READONLY | PAGE_READWRITE | PAGE_WRITECOPY); 210 222 211 223 dprintf(("Win32MemMap::commitPage %x (faultaddr %x)", pageAddr, lpPageFaultAddr)); 212 if(hMemFile != -1) 224 if(hMemFile != -1) 213 225 { 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 226 int faultsize = nrpages*PAGE_SIZE; 227 228 offset = pageAddr - (ULONG)pMapping; 229 if(offset + faultsize > mSize) { 230 faultsize = mSize - offset; 231 } 232 233 while(faultsize) { 234 if(VirtualQuery((LPSTR)pageAddr, &memInfo, sizeof(MEMORY_BASIC_INFORMATION)) == 0) { 235 dprintf(("Win32MemMap::commitPage: VirtualQuery (%x,%x) failed for %x", pageAddr, nrpages*PAGE_SIZE)); 236 goto fail; 237 } 238 memInfo.RegionSize = min(memInfo.RegionSize, faultsize); 239 //Only changes the state of the pages with the same attribute flags 240 //(returned in memInfo.RegionSize) 241 //If it's smaller than the mNrPages, it simply means one or more of the 242 //other pages have already been committed 243 if(!(memInfo.State & MEM_COMMIT)) 244 { 245 if(VirtualAlloc((LPVOID)pageAddr, memInfo.RegionSize, MEM_COMMIT, PAGE_READWRITE) == FALSE) { 246 goto fail; 247 } 248 if(!fWriteAccess) { 249 offset = pageAddr - (ULONG)pMapping; 250 size = memInfo.RegionSize; 251 if(offset + size > mSize) { 252 dprintf(("Adjusting size from %d to %d", size, mSize - offset)); 253 size = mSize - offset; 254 } 255 if(SetFilePointer(hMemFile, offset, NULL, FILE_BEGIN) != offset) { 256 dprintf(("Win32MemMap::commitPage: SetFilePointer failed to set pos to %x", offset)); 257 goto fail; 258 } 259 if(ReadFile(hMemFile, (LPSTR)pageAddr, size, &nrBytesRead, NULL) == FALSE) { 260 dprintf(("Win32MemMap::commitPage: ReadFile failed for %x", pageAddr)); 261 goto fail; 262 } 263 if(nrBytesRead != size) { 264 dprintf(("Win32MemMap::commitPage: ReadFile didn't read all bytes for %x", pageAddr)); 265 goto fail; 266 } 267 } 268 if(newProt != PAGE_READWRITE) { 269 if(VirtualProtect((LPVOID)pageAddr, memInfo.RegionSize, newProt, &oldProt) == FALSE) { 270 goto fail; 271 } 272 } 273 } 274 faultsize -= memInfo.RegionSize; 275 pageAddr += memInfo.RegionSize; 276 } 265 277 } 266 278 else { 267 268 while(sizeleft) 269 270 271 272 273 274 275 276 277 278 if(VirtualAlloc((LPVOID)pageAddr, memInfo.RegionSize, MEM_COMMIT, newProt) == FALSE) 279 280 281 282 283 284 279 ULONG sizeleft = nrpages*PAGE_SIZE; 280 while(sizeleft) 281 { 282 if(VirtualQuery((LPSTR)pageAddr, &memInfo, sizeof(MEMORY_BASIC_INFORMATION)) == 0) { 283 dprintf(("Win32MemMap::commitPage: VirtualQuery (%x,%x) failed", pageAddr, sizeleft)); 284 goto fail; 285 } 286 memInfo.RegionSize = min(memInfo.RegionSize, sizeleft); 287 288 if(!(memInfo.State & MEM_COMMIT)) 289 {//if it's already committed, then the app tried to write to it 290 if(VirtualAlloc((LPVOID)pageAddr, memInfo.RegionSize, MEM_COMMIT, newProt) == FALSE) 291 goto fail; 292 } 293 memInfo.RegionSize = (memInfo.RegionSize+PAGE_SIZE-1) & ~0xfff; 294 pageAddr += memInfo.RegionSize; 295 sizeleft -= memInfo.RegionSize; 296 } 285 297 } 286 298 … … 299 311 300 312 if(nrMappings == 0) 301 313 goto fail; 302 314 303 315 delete view; 304 316 305 317 if(--nrMappings == 0) { 306 307 318 VirtualFree(pMapping, mSize, MEM_RELEASE); 319 pMapping = NULL; 308 320 } 309 321 mapMutex.leave(); 310 322 311 323 //if there are no more mappings left and the memory map's handle has been 312 324 //closed, then delete the object 313 325 if(nrMappings == 0 && fClosed) { 314 326 delete this; 315 327 } 316 328 return TRUE; 317 329 fail: 318 330 mapMutex.leave(); 331 if(nrMappings == 0 && fClosed) { 332 delete this; 333 } 319 334 return FALSE; 320 335 } … … 333 348 // Docs say FILE_MAP_ALL_ACCESS is same as FILE_MAP_WRITE. Doesn't match reality though. 334 349 if(fdwAccess & ~FILE_MAP_ALL_ACCESS) 335 350 goto parmfail; 336 351 if((fdwAccess & FILE_MAP_WRITE) && !(mProtFlags & PAGE_READWRITE)) 337 352 goto parmfail; 338 353 if((fdwAccess & FILE_MAP_READ) && !(mProtFlags & (PAGE_READWRITE|PAGE_READONLY))) 339 354 goto parmfail; 340 355 341 356 //@@@PH … … 345 360 346 361 if(offset+size > mSize && (!(fdwAccess & FILE_MAP_WRITE) || hMemFile == -1)) 347 362 goto parmfail; 348 363 349 364 //SvL: TODO: Doesn't work for multiple views 350 365 if(offset+size > mSize) { 351 366 mSize = offset+size; 352 367 } 353 368 … … 355 370 #if 0 356 371 if(mProtFlags & SEC_COMMIT) 357 372 fAlloc |= MEM_COMMIT; 358 373 else 359 374 if(mProtFlags & SEC_RESERVE) 360 375 fAlloc |= MEM_RESERVE; 361 376 #else 362 377 fAlloc = MEM_RESERVE; … … 365 380 //Memory has already been allocated for executable image maps (only used internally) 366 381 if(!pMapping && nrMappings == 0) {//if not mapped, reserve/commit entire view 367 368 369 382 //SvL: Always read/write access or else ReadFile will crash once we 383 // start committing pages. 384 // This is most likely an OS/2 bug and doesn't happen in Aurora 370 385 // when allocating memory with the PAG_ANY bit set. (without this 371 386 // flag it will also crash) 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 387 if(hMemFile == -1 && lpszMapName) { 388 pMapping = VirtualAllocShared(mSize, fAlloc, PAGE_READWRITE, lpszMapName); 389 } 390 else { 391 pMapping = VirtualAlloc(0, mSize, fAlloc, PAGE_READWRITE); 392 } 393 if(pMapping == NULL) { 394 dprintf(("Win32MemMap::mapFileView: VirtualAlloc %x %x %x failed!", mSize, fAlloc, memFlags)); 395 goto fail; 396 } 397 //Windows NT seems to commit memory for memory maps, regardsless of the SEC_COMMIT flag 398 if((hMemFile == -1 && !image)) {//commit memory 399 VirtualAlloc(pMapping, mSize, MEM_COMMIT, PAGE_READWRITE); 400 } 401 if(hMemFile != -1 && (mProtFlags & SEC_COMMIT)) { 402 DWORD nrPages = mSize >> PAGE_SHIFT; 403 if(mSize & 0xFFF) 404 nrPages++; 405 406 commitPage(0, FALSE, nrPages); 407 } 393 408 } 394 409 mapview = new Win32MemMapView(this, offset, (size == 0) ? mSize : size, fdwAccess); 395 410 if(mapview == NULL) { 396 411 goto fail; 397 412 } 398 413 if(mapview->everythingOk() == FALSE) { 399 400 401 414 dprintf(("Win32MemMap::mapFileView: !mapview->everythingOk")); 415 delete mapview; 416 goto fail; 402 417 } 403 418 nrMappings++; … … 428 443 429 444 if(image) //no flushing for image maps 430 445 return TRUE; 431 446 432 447 dprintf(("Win32MemMap::flushView: %x %x", lpvBase, cbFlush)); 433 448 if(nrMappings == 0) 434 449 goto parmfail; 435 450 436 451 if(cbFlush == 0) 437 452 cbFlush = mSize; 438 453 439 454 if(lpvBase < pMapping || (ULONG)lpvBase+cbFlush > (ULONG)pMapping+mSize) 440 455 goto parmfail; 441 456 442 457 if(mProtFlags & PAGE_READONLY) 443 458 goto parmfail; 444 459 445 460 if(hMemFile == -1) 446 461 goto success; //TODO: Return an error here? 447 462 448 463 while(cbFlush) { 449 450 451 452 453 464 if(VirtualQuery((LPSTR)lpvBase, &memInfo, sizeof(MEMORY_BASIC_INFORMATION)) == 0) { 465 dprintf(("Win32MemMap::flushView: VirtualQuery (%x,%x) failed for %x", lpvBase, cbFlush, (ULONG)lpvBase+i*PAGE_SIZE)); 466 goto fail; 467 } 468 //If a page (or range of pages) is reserved or write protected, we 454 469 //won't bother flushing it to disk 455 470 if(memInfo.State & MEM_COMMIT && 456 471 memInfo.AllocationProtect & (PAGE_READWRITE|PAGE_WRITECOPY|PAGE_EXECUTE_READWRITE|PAGE_EXECUTE_WRITECOPY)) 457 472 {//committed and allowed for writing? 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 473 offset = (ULONG)lpvBase - (ULONG)pMapping; 474 size = memInfo.RegionSize; 475 if(size > cbFlush) { 476 size = cbFlush; 477 } 478 dprintf(("Win32MemMap::flushView for offset %x, size %d", offset, size)); 479 480 if(SetFilePointer(hMemFile, offset, NULL, FILE_BEGIN) != offset) { 481 dprintf(("Win32MemMap::flushView: SetFilePointer failed to set pos to %x", offset)); 482 goto fail; 483 } 484 if(WriteFile(hMemFile, (LPSTR)lpvBase, size, &nrBytesWritten, NULL) == FALSE) { 485 dprintf(("Win32MemMap::flushView: WriteFile failed for %x", (ULONG)lpvBase)); 486 goto fail; 487 } 488 if(nrBytesWritten != size) { 489 dprintf(("Win32MemMap::flushView: WriteFile didn't write all bytes for %x", (ULONG)lpvBase)); 490 goto fail; 491 } 492 } 493 lpvBase = (LPVOID)((ULONG)lpvBase + memInfo.RegionSize); 494 495 if(cbFlush < memInfo.RegionSize) 496 break; 497 498 cbFlush -= memInfo.RegionSize; 484 499 } 485 500 success: … … 496 511 { 497 512 if(lpszName == NULL) 498 513 return NULL; 499 514 500 515 globalmapMutex.enter(VMUTEX_WAIT_FOREVER, &hGlobalMapMutex); … … 502 517 503 518 if(map != NULL) { 504 505 506 507 508 519 while(map) { 520 if(map->lpszMapName && !strcmp(map->lpszMapName, lpszName)) 521 break; 522 map = map->next; 523 } 509 524 } 510 525 globalmapMutex.leave(&hGlobalMapMutex); … … 520 535 521 536 if(map != NULL) { 522 523 537 while(map) { 538 if(map->pMapping && (ULONG)map->pMapping <= address && 524 539 (ULONG)map->pMapping + map->mSize > address) 525 526 527 528 529 540 { 541 break; 542 } 543 map = map->next; 544 } 530 545 } 531 546 globalmapMutex.leave(&hGlobalMapMutex); … … 542 557 globalviewMutex.enter(); 543 558 while(map) { 544 545 546 547 548 549 550 551 if(!map->isClosed()) 552 553 554 555 556 557 558 Win32MemMapView::deleteViews(map);559 560 559 nextmap = map->next; 560 if(map->getProcessId() == processId) { 561 //Delete map directly for executable images (only used internally) 562 if(map->getImage()) { 563 delete map; 564 } 565 else { 566 if(!map->isClosed()) 567 CloseHandle(memmaps->hMemMap); 568 else delete map; 569 } 570 } 571 else { 572 //delete all views created by this process for this map 573 Win32MemMapView::deleteViews(map); 574 } 575 map = nextmap; 561 576 } 562 577 globalviewMutex.leave(); … … 579 594 switch(fdwAccess) { 580 595 case FILE_MAP_READ: 581 582 583 596 accessAttr = PAG_READ; 597 mfAccess = MEMMAP_ACCESS_READ; 598 break; 584 599 case FILE_MAP_ALL_ACCESS: 585 600 case FILE_MAP_WRITE: 586 601 case FILE_MAP_WRITE|FILE_MAP_READ: 587 602 case FILE_MAP_COPY: 588 589 590 603 accessAttr = (PAG_READ|PAG_WRITE); 604 mfAccess = MEMMAP_ACCESS_READ | MEMMAP_ACCESS_WRITE; 605 break; 591 606 } 592 607 if(map->getMemName() != NULL && map->getFileHandle() == -1) { 593 594 595 596 597 598 599 600 } 601 608 //shared memory map, so map it into our address space 609 if(OSLibDosGetNamedSharedMem((LPVOID *)&viewaddr, map->getMemName()) != OSLIB_NOERROR) { 610 dprintf(("new OSLibDosGetNamedSharedMem FAILED")); 611 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 612 errorState = 1; 613 return; 614 } 615 } 616 602 617 //view == memory mapping for executable images (only used internally) 603 618 if(map->getImage()) { 604 619 pMapView = map->getMappingAddr(); 605 620 } 606 621 else { 607 608 609 610 611 612 622 if(OSLibDosAliasMem(viewaddr, size, &pMapView, accessAttr) != OSLIB_NOERROR) { 623 dprintf(("new OSLibDosAliasMem FAILED")); 624 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 625 errorState = 1; 626 return; 627 } 613 628 } 614 629 … … 617 632 globalviewMutex.enter(); 618 633 if(tmpview == NULL || tmpview->getViewAddr() > pMapView) { 619 620 634 next = mapviews; 635 mapviews = this; 621 636 } 622 637 else { 623 624 625 626 627 628 629 630 638 while(tmpview->next) { 639 if(tmpview->next->getViewAddr() > pMapView) { 640 break; 641 } 642 tmpview = tmpview->next; 643 } 644 next = tmpview->next; 645 tmpview->next = this; 631 646 } 632 647 globalviewMutex.leave(); … … 637 652 { 638 653 if(errorState != 0) 639 654 return; 640 655 641 656 dprintf(("Win32MemMapView dtor: deleting view %x %x", mOffset, mSize)); 642 657 643 658 if(mfAccess & MEMMAP_ACCESS_WRITE) 644 659 mParentMap->flushView(mOffset, mSize); 645 660 646 661 //Don't free memory for executable image map views (only used internally) 647 662 if(!mParentMap->getImage()) 648 663 OSLibDosFreeMem(pMapView); 649 664 650 665 globalviewMutex.enter(); … … 652 667 653 668 if(view == this) { 654 669 mapviews = next; 655 670 } 656 671 else { 657 658 659 660 661 662 663 664 665 elsedprintf(("Win32MemMapView::~Win32MemMapView: map not found!! (%x)", this));672 while(view->next) { 673 if(view->next == this) 674 break; 675 view = view->next; 676 } 677 if(view->next) { 678 view->next = next; 679 } 680 else dprintf(("Win32MemMapView::~Win32MemMapView: map not found!! (%x)", this)); 666 681 } 667 682 globalviewMutex.leave(); … … 675 690 676 691 if(view != NULL) { 677 678 679 680 681 682 683 684 685 686 692 while(view) { 693 nextview = view->next; 694 if(view->getParentMap() == map) 695 { 696 globalviewMutex.leave(); 697 delete view; 698 globalviewMutex.enter(); 699 } 700 view = nextview; 701 } 687 702 } 688 703 globalviewMutex.leave(); … … 700 715 701 716 if(view != NULL) { 702 703 717 while(view && (ULONG)view->getViewAddr() <= address) { 718 if((ULONG)view->getViewAddr() <= address && 704 719 (ULONG)view->getViewAddr() + view->getSize() > address && 705 720 view->getAccessFlags() >= accessType) 706 707 708 709 710 711 712 713 721 { 722 *offset = view->getOffset() + (address - (ULONG)view->getViewAddr()); 723 goto success; 724 } 725 view = view->next; 726 } 727 //failure if we get here 728 view = NULL; 714 729 } 715 730 success: 716 731 if(view && !view->getParentMap()->isImageMap()) 717 732 dprintf(("findMapByView %x %x -> %x off %x", address, accessType, view->getViewAddr(), *offset)); 718 733 719 734 globalviewMutex.leave(); … … 729 744 globalviewMutex.enter(); 730 745 if(view != NULL) { 731 732 733 734 735 736 737 746 while(view) { 747 if(view->getViewAddr() == address) 748 { 749 break; 750 } 751 view = view->next; 752 } 738 753 } 739 754 globalviewMutex.leave();
Note:
See TracChangeset
for help on using the changeset viewer.