1 using System;
   2 using System.Collections;
   3 using cmsx.machine;
   4 
   5 namespace cmsx.kernel
   6 {
   7     public class AddressSpace
   8     {
   9         static nothrow AddressSpace() : nextAddressSpaceNumber(kernelAddressSpaceNumber + 1u)
  10         {
  11         }
  12         public static nothrow ushort GetNextAddressSpaceNumber()
  13         {
  14             if (nextAddressSpaceNumber == kernelAddressSpaceNumber)
  15             {
  16                 ++nextAddressSpaceNumber;
  17             }
  18             return nextAddressSpaceNumber++;
  19         }
  20         static ushort nextAddressSpaceNumber;
  21     }
  22 
  23     public nothrow ushort GetNextAddressSpaceNumber()
  24     {
  25         return AddressSpace.GetNextAddressSpaceNumber();
  26     }
  27 
  28     public class GlobalMemoryTable
  29     {
  30         static GlobalMemoryTable() : instance(new GlobalMemoryTable())
  31         {
  32         }
  33         public static GlobalMemoryTable& Instance()
  34         {
  35             return *instance;
  36         }
  37         private GlobalMemoryTable()
  38         {
  39         }
  40         public void AddMemoryTable(MemoryTable* memoryTable)
  41         {
  42             addressSpaceMemoryTableMap[memoryTable->addressSpaceNumber] = memoryTable;
  43         }
  44         public void RemoveMemoryTable(MemoryTable* memoryTable)
  45         {
  46             addressSpaceMemoryTableMap.Remove(memoryTable->addressSpaceNumber);
  47         }
  48         public nothrow MemoryTable* GetMemoryTable(ushort addressSpaceNumber) const
  49         {
  50             HashMap<ushortMemoryTable*>.ConstIterator it = addressSpaceMemoryTableMap.CFind(addressSpaceNumber);
  51             if (it != addressSpaceMemoryTableMap.CEnd())
  52             {
  53                 return it->second;
  54             }
  55             else
  56             {
  57                 return null;
  58             }
  59         }
  60         private static UniquePtr<GlobalMemoryTable> instance;
  61         private HashMap<ushortMemoryTable*> addressSpaceMemoryTableMap;
  62     }
  63 
  64     public class MemoryTable
  65     {
  66         public ulong rootPageAddress;
  67         public ushort addressSpaceNumber;
  68         public SegmentDescriptor*[numSegments] segmentDescriptors;
  69         public ulong virtualTranslationRegisterValue;
  70     }
  71 
  72     public nothrow ulong KernelGetMaxStackSize(ushort addressSpaceNumber)
  73     {
  74         MemoryTable* memoryTable = GlobalMemoryTable.Instance().GetMemoryTable(addressSpaceNumber);
  75         if (memoryTable != null)
  76         {
  77             SegmentDescriptor* stackSegmentDescriptor = memoryTable->segmentDescriptors[stackSegmentIndex];
  78             if (stackSegmentDescriptor != null)
  79             {
  80                 return stackSegmentDescriptor->maxLength;
  81             }
  82             else
  83             {
  84                 return 0u;
  85             }
  86         }
  87         else
  88         {
  89             return 0u;
  90         }
  91     }
  92 
  93     public nothrow bool KernelGrowStack(ushort addressSpaceNumber)
  94     {
  95         try
  96         {
  97             MemoryTable* memoryTable = GlobalMemoryTable.Instance().GetMemoryTable(addressSpaceNumber);
  98             if (memoryTable != null)
  99             {
 100                 SegmentDescriptor* stackSegmentDescriptor = memoryTable->segmentDescriptors[stackSegmentIndex];
 101                 if (stackSegmentDescriptor != null)
 102                 {
 103                     if (stackSegmentDescriptor->increment == 0u)
 104                     {
 105                         return false;
 106                     }
 107                     else if (stackSegmentDescriptor->length + stackSegmentDescriptor->increment <= stackSegmentDescriptor->maxLength)
 108                     {
 109                         GrowSegment(GetMachine().GetMemory() *memoryTablestackSegmentIndexstackSegmentDescriptor->increment);
 110                         return true;
 111                     }
 112                     else
 113                     {
 114                         return false;
 115                     }
 116                 }
 117                 else
 118                 {
 119                     return false;
 120                 }
 121             }
 122             else
 123             {
 124                 return false;
 125             }
 126         }
 127         catch (const Exception& ex)
 128         {
 129             Kernel& kernel = Kernel.Instance();
 130             ProcessTable& processTable = kernel.GetProcessTable();
 131             Process* process = processTable.GetRunning();
 132             Debugger* debugger = kernel.GetDebugger();
 133             string errorlf = "KernelGrowStack failed: " + ex.Message() + "\n";
 134             debugger->WriteOutput(cast<byte*>(cast<void*>(errorlf.Chars()))errorlf.Length());
 135             debugger->Run(process);
 136             return false;
 137         }
 138         return false;
 139     }
 140 
 141     public nothrow void DefaultInitializeMemoryTable(Machine& machineMemoryTable& memoryTable)
 142     {
 143         Memory& mem = machine.GetMemory();
 144         memoryTable.rootPageAddress = mem.AllocateRootPage();
 145         memoryTable.addressSpaceNumber = GetNextAddressSpaceNumber();
 146         memoryTable.segmentDescriptors[textSegmentIndex] = CreateSegmentDescriptor(pageSizetextSegmentBaseAddresspageSize);
 147         memoryTable.segmentDescriptors[dataSegmentIndex] = CreateSegmentDescriptor(0udataSegmentBaseAddresspageSize);
 148         memoryTable.segmentDescriptors[poolSegmentIndex] = CreateSegmentDescriptor(0upoolSegmentBaseAddresspageSize);
 149         memoryTable.segmentDescriptors[stackSegmentIndex] = CreateSegmentDescriptor(0ustackSegmentBaseAddresspageSize);
 150         memoryTable.virtualTranslationRegisterValue = MakeVirtualTranslationRegisterValue(memoryTable.rootPageAddressmemoryTable.addressSpaceNumber);
 151         GlobalMemoryTable.Instance().AddMemoryTable(&memoryTable);
 152     }
 153 
 154     public nothrow void InitializeMemoryTable(Machine& machineMemoryTable& memoryTable
 155         ulong textSegmentStartAddressulong textSegmentSizeulong dataSegmentSizeulong poolSegmentSizeulong minStackSegmentSizeulong maxStackSegmentSizeulong stackSegmentIncrement)
 156     {
 157         Memory& mem = machine.GetMemory();
 158         memoryTable.rootPageAddress = mem.AllocateRootPage();
 159         memoryTable.addressSpaceNumber = GetNextAddressSpaceNumber();
 160         if (textSegmentStartAddress == 0u)
 161         {
 162             textSegmentStartAddress = pageSize;
 163         }
 164         memoryTable.segmentDescriptors[textSegmentIndex] = CreateSegmentDescriptor(textSegmentStartAddresstextSegmentBaseAddresstextSegmentSize);
 165         memoryTable.segmentDescriptors[dataSegmentIndex] = CreateSegmentDescriptor(0udataSegmentBaseAddressdataSegmentSize);
 166         memoryTable.segmentDescriptors[poolSegmentIndex] = CreateSegmentDescriptor(0upoolSegmentBaseAddresspoolSegmentSize);
 167         memoryTable.segmentDescriptors[stackSegmentIndex] = CreateSegmentDescriptor(0ustackSegmentBaseAddressminStackSegmentSizemaxStackSegmentSizestackSegmentIncrement);
 168         memoryTable.virtualTranslationRegisterValue = MakeVirtualTranslationRegisterValue(memoryTable.rootPageAddressmemoryTable.addressSpaceNumber);
 169         GlobalMemoryTable.Instance().AddMemoryTable(&memoryTable);
 170     }
 171 
 172     public nothrow void InitializeMemoryTable(Machine& machineMemoryTable& targetMemoryTableconst MemoryTable& sourceMemoryTableulong poolSegmentSize)
 173     {
 174         Memory& mem = machine.GetMemory();
 175         targetMemoryTable.rootPageAddress = mem.AllocateRootPage();
 176         targetMemoryTable.addressSpaceNumber = GetNextAddressSpaceNumber();
 177         ShareSegment(memtextSegmentIndextargetMemoryTablesourceMemoryTableProtection.execute);
 178         targetMemoryTable.segmentDescriptors[dataSegmentIndex] = CreateSegmentDescriptor(
 179             sourceMemoryTable.segmentDescriptors[dataSegmentIndex]->startAddress
 180             sourceMemoryTable.segmentDescriptors[dataSegmentIndex]->baseAddress
 181             sourceMemoryTable.segmentDescriptors[dataSegmentIndex]->length);
 182         targetMemoryTable.segmentDescriptors[poolSegmentIndex] = CreateSegmentDescriptor(0upoolSegmentBaseAddresspoolSegmentSize);
 183         targetMemoryTable.segmentDescriptors[stackSegmentIndex] = CreateSegmentDescriptor(
 184             sourceMemoryTable.segmentDescriptors[stackSegmentIndex]->startAddress
 185             sourceMemoryTable.segmentDescriptors[stackSegmentIndex]->baseAddress
 186             sourceMemoryTable.segmentDescriptors[stackSegmentIndex]->length
 187             sourceMemoryTable.segmentDescriptors[stackSegmentIndex]->maxLength
 188             sourceMemoryTable.segmentDescriptors[stackSegmentIndex]->increment);
 189         targetMemoryTable.virtualTranslationRegisterValue = MakeVirtualTranslationRegisterValue(targetMemoryTable.rootPageAddresstargetMemoryTable.addressSpaceNumber);
 190         GlobalMemoryTable.Instance().AddMemoryTable(&targetMemoryTable);
 191     }
 192 
 193     public nothrow void InitializeMemoryTableForCloning(Machine& machineMemoryTable& memoryTable)
 194     {
 195         Memory& mem = machine.GetMemory();
 196         memoryTable.rootPageAddress = mem.AllocateRootPage();
 197         memoryTable.addressSpaceNumber = GetNextAddressSpaceNumber();
 198         memoryTable.segmentDescriptors[textSegmentIndex] = null;
 199         memoryTable.segmentDescriptors[dataSegmentIndex] = null;
 200         memoryTable.segmentDescriptors[poolSegmentIndex] = null;
 201         memoryTable.segmentDescriptors[stackSegmentIndex] = null;
 202         memoryTable.virtualTranslationRegisterValue = MakeVirtualTranslationRegisterValue(memoryTable.rootPageAddressmemoryTable.addressSpaceNumber);
 203         GlobalMemoryTable.Instance().AddMemoryTable(&memoryTable);
 204     }
 205 
 206     public nothrow void CalculatePageNumbers(const SegmentDescriptor& sdulong& startPageNumberulong& numPages)
 207     {
 208         ulong startAddress = sd.startAddress;
 209         startPageNumber = GetPageNumber(startAddress);
 210         ulong length = sd.length;
 211         ulong segmentStart = startPageNumber * pageSize;
 212         ulong segmentEnd = startAddress + length;
 213         ulong segmentSize = segmentEnd - segmentStart;
 214         numPages = 0u;
 215         if (segmentSize > 0u)
 216         {
 217             numPages = (segmentSize - 1u) / pageSize + 1u;
 218         }
 219     }
 220 
 221     public void AllocateMemoryPages(Memory& memulong rootPageAddressbyte segmentIndexulong startPageNumberulong numPagesushort addressSpaceNumber)
 222     {
 223         Protection protection = MakeDefaultPageProtection(segmentIndex);
 224         ulong firstRootPageEntryNumber = MakeSegmentOffset(segmentIndex);
 225         ulong lastDirectRootPageEntryNumber = firstRootPageEntryNumber + numDirectEntries - 1u;
 226         ulong firstIndirectEntryNumber = lastDirectRootPageEntryNumber + 1u;
 227         ulong singleIndirectEntryNumber = lastDirectRootPageEntryNumber + 1u;
 228         ulong doubleIndirectEntryNumber = lastDirectRootPageEntryNumber + 2u;
 229         ulong tripleIndirectEntryNumber = lastDirectRootPageEntryNumber + 3u;
 230         ulong singleIndirectPageAddress = 0u;
 231         ulong doubleIndirectPageAddress = 0u;
 232         ulong tripleIndirectPageAddress = 0u;
 233         ulong entryNumber = firstRootPageEntryNumber + startPageNumber;
 234         ulong pagesLeft = numPages;
 235         ushort prevDigit0 = 0u;
 236         ushort prevDigit1 = 0u;
 237         ushort prevDigit2 = 0u;
 238         while (pagesLeft > 0u)
 239         {
 240             if (entryNumber >= firstRootPageEntryNumber && entryNumber <= lastDirectRootPageEntryNumber)
 241             {
 242                 ulong entryAddress = rootPageAddress + 8u * entryNumber;
 243                 ulong pageAddress = mem.AllocatePage();
 244                 ulong pte = MakePageTableEntry(pageAddressaddressSpaceNumberprotection);
 245                 WriteMemoryULong(entryAddresspte);
 246                 #if (MEMORY_DEBUG)
 247                     Console.Out() << "entry address: " << ToHexString(entryAddress) << ", page address: " << ToHexString(pageAddress) << ", pte: " << ToHexString(pte) << endl();
 248                 #endif
 249             }
 250             else
 251             {
 252                 if (singleIndirectEntryNumber != 0u)
 253                 {
 254                     #if (MEMORY_DEBUG)
 255                         Console.Out() << "indirect entries:" << endl();
 256                     #endif
 257                     ulong entryAddress = rootPageAddress + 8u * singleIndirectEntryNumber;
 258                     ulong pte = ReadMemoryULong(entryAddress);
 259                     singleIndirectPageAddress = 0u;
 260                     if (pte != 0u)
 261                     {
 262                         ulong pageAddress = 0u;
 263                         ushort pteAddressSpaceNumber = 0u;
 264                         Protection protection = Protection.notPresent;
 265                         UnpackPageTableEntry(ptepageAddresspteAddressSpaceNumberprotection);
 266                         if (protection != Protection.notPresent && pageAddress != 0u)
 267                         {
 268                             singleIndirectPageAddress = pageAddress;
 269                         }
 270                     }
 271                     if (singleIndirectPageAddress == 0u)
 272                     {
 273                         singleIndirectPageAddress = mem.AllocatePage();
 274                         pte = MakePageTableEntry(singleIndirectPageAddressaddressSpaceNumberprotection);
 275                         WriteMemoryULong(entryAddresspte);
 276                     }
 277                     #if (MEMORY_DEBUG)
 278                         Console.Out() << "single indirect entry address: " << ToHexString(entryAddress) << ", page address: " << ToHexString(pageAddress) << ", pte: " << ToHexString(pte) << endl();
 279                     #endif
 280                     singleIndirectEntryNumber = 0u;
 281                 }
 282                 ulong pageNum = entryNumber - firstIndirectEntryNumber;
 283                 ushort digit0 = 0u;
 284                 ushort digit1 = 0u;
 285                 ushort digit2 = 0u;
 286                 ExtractDigitsFromPageNumber(pageNumdigit0digit1digit2);
 287                 #if (MEMORY_DEBUG)
 288                     Console.Out() << "page number: " << ToHexString(pageNum) << ", d0: " << ToHexString(digit0) << ", d1: " << ToHexString(digit1) << 
 289                         ", d2: " << ToHexString(digit2) << endl();
 290                 #endif
 291                 if (digit2 == 0u && digit1 == 0u)
 292                 {
 293                     ulong entryAddress = singleIndirectPageAddress + 8u * digit0;
 294                     ulong pageAddress = mem.AllocatePage();
 295                     ulong pte = MakePageTableEntry(pageAddressaddressSpaceNumberprotection);
 296                     WriteMemoryULong(entryAddresspte);
 297                     #if (MEMORY_DEBUG)
 298                         Console.Out() << "si-entry address: " << ToHexString(entryAddress) << ", page address: " << ToHexString(pageAddress) << ", pte: " << ToHexString(pte) << endl();
 299                     #endif
 300                 }
 301                 else if (digit2 == 0u && digit1 > 0u)
 302                 {
 303                     if (doubleIndirectEntryNumber != 0u)
 304                     {
 305                         ulong entryAddress = rootPageAddress + 8u * doubleIndirectEntryNumber;
 306                         ulong pte = ReadMemoryULong(entryAddress);
 307                         doubleIndirectPageAddress = 0u;
 308                         if (pte != 0u)
 309                         {
 310                             ulong pageAddress = 0u;
 311                             ushort pteAddressSpaceNumber = 0u;
 312                             Protection protection = Protection.notPresent;
 313                             UnpackPageTableEntry(ptepageAddresspteAddressSpaceNumberprotection);
 314                             if (protection != Protection.notPresent && pageAddress != 0u)
 315                             {
 316                                 doubleIndirectPageAddress = pageAddress;
 317                             }
 318                         }
 319                         if (doubleIndirectPageAddress == 0u)
 320                         {
 321                             doubleIndirectPageAddress = mem.AllocatePage();
 322                             pte = MakePageTableEntry(doubleIndirectPageAddressaddressSpaceNumberprotection);
 323                             WriteMemoryULong(entryAddresspte);
 324                         }
 325                         #if (MEMORY_DEBUG)
 326                             Console.Out() << "double indirect entry address: " << ToHexString(entryAddress) << ", page address: " << ToHexString(pageAddress) << ", pte: " << ToHexString(pte) << endl();
 327                         #endif
 328                         doubleIndirectEntryNumber = 0u;
 329                     }
 330                     if (digit1 != prevDigit1)
 331                     {
 332                         ulong entryAddress = doubleIndirectPageAddress + 8u * digit1;
 333                         ulong pte = ReadMemoryULong(entryAddress);
 334                         singleIndirectPageAddress = 0u;
 335                         if (pte != 0u)
 336                         {
 337                             ulong pageAddress = 0u;
 338                             ushort pteAddressSpaceNumber = 0u;
 339                             Protection protection = Protection.notPresent;
 340                             UnpackPageTableEntry(ptepageAddresspteAddressSpaceNumberprotection);
 341                             if (protection != Protection.notPresent && pageAddress != 0u)
 342                             {
 343                                 singleIndirectPageAddress = pageAddress;
 344                             }
 345                         }
 346                         if (singleIndirectPageAddress == 0u)
 347                         {
 348                             singleIndirectPageAddress = mem.AllocatePage();
 349                             pte = MakePageTableEntry(singleIndirectPageAddressaddressSpaceNumberprotection);
 350                             WriteMemoryULong(entryAddresspte);
 351                         }
 352                         #if (MEMORY_DEBUG)
 353                             Console.Out() << "di-entry address: " << ToHexString(entryAddress) << ", page address: " << ToHexString(pageAddress) << ", pte: " << ToHexString(pte) << endl();
 354                         #endif
 355                     }
 356                     ulong siEntryAddress = singleIndirectPageAddress + 8u * digit0;
 357                     ulong siPageAddress = mem.AllocatePage();
 358                     ulong siPte = MakePageTableEntry(siPageAddressaddressSpaceNumberprotection);
 359                     WriteMemoryULong(siEntryAddresssiPte);
 360                     #if (MEMORY_DEBUG)
 361                         Console.Out() << "di-si-entry address: " << ToHexString(siEntryAddress) << ", page address: " << ToHexString(siPageAddress) << ", pte: " << ToHexString(siPte) << endl();
 362                     #endif
 363                 }
 364                 else if (digit2 > 0u)
 365                 {
 366                     if (tripleIndirectEntryNumber != 0u)
 367                     {
 368                         ulong entryAddress = rootPageAddress + 8u * tripleIndirectEntryNumber;
 369                         ulong pte = ReadMemoryULong(entryAddress);
 370                         tripleIndirectPageAddress = 0u;
 371                         if (pte != 0u)
 372                         {
 373                             ulong pageAddress = 0u;
 374                             ushort pteAddressSpaceNumber = 0u;
 375                             Protection protection = Protection.notPresent;
 376                             UnpackPageTableEntry(ptepageAddresspteAddressSpaceNumberprotection);
 377                             if (protection != Protection.notPresent && pageAddress != 0u)
 378                             {
 379                                 tripleIndirectPageAddress = pageAddress;
 380                             }
 381                         }
 382                         if (tripleIndirectPageAddress == 0u)
 383                         {
 384                             tripleIndirectPageAddress = mem.AllocatePage();
 385                             pte = MakePageTableEntry(tripleIndirectPageAddressaddressSpaceNumberprotection);
 386                             WriteMemoryULong(entryAddresspte);
 387                         }
 388                         #if (MEMORY_DEBUG)
 389                             Console.Out() << "triple indirect entry address: " << ToHexString(entryAddress) << ", page address: " << ToHexString(pageAddress) << ", pte: " << ToHexString(pte) << endl();
 390                         #endif
 391                         tripleIndirectEntryNumber = 0u;
 392                     }
 393                     if (digit2 != prevDigit2)
 394                     {
 395                         ulong entryAddress = tripleIndirectPageAddress + 8u * digit2;
 396                         ulong pte = ReadMemoryULong(entryAddress);
 397                         doubleIndirectPageAddress = 0u;
 398                         if (pte != 0u)
 399                         {
 400                             ulong pageAddress = 0u;
 401                             ushort pteAddressSpaceNumber = 0u;
 402                             Protection protection = Protection.notPresent;
 403                             UnpackPageTableEntry(ptepageAddresspteAddressSpaceNumberprotection);
 404                             if (protection != Protection.notPresent && pageAddress != 0u)
 405                             {
 406                                 doubleIndirectPageAddress = pageAddress;
 407                             }
 408                         }
 409                         if (doubleIndirectPageAddress == 0u)
 410                         {
 411                             doubleIndirectPageAddress = mem.AllocatePage();
 412                             pte = MakePageTableEntry(doubleIndirectPageAddressaddressSpaceNumberprotection);
 413                             WriteMemoryULong(entryAddresspte);
 414                         }
 415                         #if (MEMORY_DEBUG)
 416                             Console.Out() << "ti-entry address: " << ToHexString(entryAddress) << ", page address: " << ToHexString(pageAddress) << ", pte: " << ToHexString(pte) << endl();
 417                         #endif
 418                     }
 419                     if (digit1 != prevDigit1)
 420                     {
 421                         ulong entryAddress = doubleIndirectPageAddress + 8u * digit1;
 422                         ulong pte = ReadMemoryULong(entryAddress);
 423                         singleIndirectPageAddress = 0u;
 424                         if (pte != 0u)
 425                         {
 426                             ulong pageAddress = 0u;
 427                             ushort pteAddressSpaceNumber = 0u;
 428                             Protection protection = Protection.notPresent;
 429                             UnpackPageTableEntry(ptepageAddresspteAddressSpaceNumberprotection);
 430                             if (protection != Protection.notPresent && pageAddress != 0u)
 431                             {
 432                                 singleIndirectPageAddress = pageAddress;
 433                             }
 434                         }
 435                         if (singleIndirectPageAddress == 0u)
 436                         {
 437                             singleIndirectPageAddress = mem.AllocatePage();
 438                             pte = MakePageTableEntry(singleIndirectPageAddressaddressSpaceNumberprotection);
 439                             WriteMemoryULong(entryAddresspte);
 440                         }
 441                         #if (MEMORY_DEBUG)
 442                             Console.Out() << "ti-di-entry address: " << ToHexString(entryAddress) << ", page address: " << ToHexString(pageAddress) << ", pte: " << ToHexString(pte) << endl();
 443                         #endif
 444                     }
 445                     ulong siEntryAddress = singleIndirectPageAddress + 8u * digit0;
 446                     ulong siPageAddress = mem.AllocatePage();
 447                     ulong siPte = MakePageTableEntry(siPageAddressaddressSpaceNumberprotection);
 448                     WriteMemoryULong(siEntryAddresssiPte);
 449                     #if (MEMORY_DEBUG)
 450                         Console.Out() << "ti-di-si-entry address: " << ToHexString(siEntryAddress) << ", page address: " << ToHexString(siPageAddress) << ", pte: " << ToHexString(siPte) << endl();
 451                     #endif
 452                 }
 453                 prevDigit0 = digit0;
 454                 prevDigit1 = digit1;
 455                 prevDigit2 = digit2;
 456             }
 457             ++entryNumber;
 458             --pagesLeft;
 459         }
 460     }
 461 
 462     public void FreeMemoryPages(Memory& memulong rootPageAddressbyte segmentIndexulong startPageNumberulong numPages)
 463     {
 464         ulong firstRootPageEntryNumber = MakeSegmentOffset(segmentIndex);
 465         ulong lastDirectRootPageEntryNumber = firstRootPageEntryNumber + numDirectEntries - 1u;
 466         ulong firstIndirectEntryNumber = lastDirectRootPageEntryNumber + 1u;
 467         ulong singleIndirectEntryNumber = lastDirectRootPageEntryNumber + 1u;
 468         ulong doubleIndirectEntryNumber = lastDirectRootPageEntryNumber + 2u;
 469         ulong tripleIndirectEntryNumber = lastDirectRootPageEntryNumber + 3u;
 470         bool singleIndirectEntryAddressInitialized = false;
 471         bool doubleIndirectEntryAddressInitialized = false;
 472         bool tripleIndirectEntryAddressInitialized = false;
 473         ulong singleIndirectPageAddress = 0u;
 474         ulong singleIndirectEntryAddress = 0u;
 475         ulong doubleIndirectPageAddress = 0u;
 476         ulong doubleIndirectEntryAddress = 0u;
 477         ulong diSingleIndirectPageAddress = 0u;
 478         ulong diSingleIndirectEntryAddress = 0u;
 479         ulong diSingleIndirectEntryNumber = 0u;
 480         ulong tripleIndirectPageAddress = 0u;
 481         ulong tripleIndirectEntryAddress = 0u;
 482         ulong tiDoubleIndirectPageAddress = 0u;
 483         ulong tiDoubleIndirectEntryAddress = 0u;
 484         ulong tiDoubleIndirectEntryNumber = 0u;
 485         ulong tiSingleIndirectPageAddress = 0u;
 486         ulong tiSingleIndirectEntryAddress = 0u;
 487         ulong tiSingleIndirectEntryNumber = 0u;
 488         bool freeSingleIndirectPage = false;
 489         bool freeDoubleIndirectPage = false;
 490         bool freeTripleIndirectPage = false;
 491         bool freeDiSingleIndirectPage = false;
 492         bool freeTiDoubleIndirectPage = false;
 493         bool freeTiSingleIndirectPage = false;
 494         ulong entryNumber = firstRootPageEntryNumber + startPageNumber;
 495         ulong pagesLeft = numPages;
 496         ushort prevDigit0 = 0u;
 497         ushort prevDigit1 = 0u;
 498         ushort prevDigit2 = 0u;
 499         while (pagesLeft > 0u)
 500         {
 501             if (entryNumber >= firstRootPageEntryNumber && entryNumber <= lastDirectRootPageEntryNumber)
 502             {
 503                 ulong entryAddress = rootPageAddress + 8u * entryNumber;
 504                 ulong pte = ReadMemoryULong(entryAddress);
 505                 if (pte != 0u)
 506                 {
 507                     ulong pageAddress = 0u;
 508                     ushort pteAddressSpaceNumber = 0u;
 509                     Protection protection = Protection.notPresent;
 510                     UnpackPageTableEntry(ptepageAddresspteAddressSpaceNumberprotection);
 511                     if (protection != Protection.notPresent && pageAddress != 0u)
 512                     {
 513                         #if (MEMORY_DEBUG)
 514                             Console.Out() << "entry address: " << ToHexString(entryAddress) << ", page address: " << ToHexString(pageAddress) << ", pte: " << ToHexString(pte) << endl();
 515                         #endif
 516                         mem.FreePage(pageAddress);
 517                         WriteMemoryULong(entryAddress0u);
 518                     }
 519                 }
 520             }
 521             else
 522             {
 523                 if (!singleIndirectEntryAddressInitialized)
 524                 {
 525                     ulong entryAddress = rootPageAddress + 8u * singleIndirectEntryNumber;
 526                     singleIndirectEntryAddress = entryAddress;
 527                     ulong pte = ReadMemoryULong(entryAddress);
 528                     if (pte != 0u)
 529                     {
 530                         ulong pageAddress = 0u;
 531                         ushort pteAddressSpaceNumber = 0u;
 532                         Protection protection = Protection.notPresent;
 533                         UnpackPageTableEntry(ptepageAddresspteAddressSpaceNumberprotection);
 534                         if (protection != Protection.notPresent && pageAddress != 0u)
 535                         {
 536                             singleIndirectPageAddress = pageAddress;
 537                         }
 538                         else
 539                         {
 540                             singleIndirectPageAddress = 0u;
 541                         }
 542                     }
 543                     else
 544                     {
 545                         singleIndirectPageAddress = 0u;
 546                     }
 547                     singleIndirectEntryAddressInitialized = true;
 548                 }
 549                 ulong pageNum = entryNumber - firstIndirectEntryNumber;
 550                 ushort digit0 = 0u;
 551                 ushort digit1 = 0u;
 552                 ushort digit2 = 0u;
 553                 ExtractDigitsFromPageNumber(pageNumdigit0digit1digit2);
 554                 #if (MEMORY_DEBUG)
 555                     Console.Out() << "page number: " << ToHexString(pageNum) << ", d0: " << ToHexString(digit0) << ", d1: " << ToHexString(digit1) << 
 556                         ", d2: " << ToHexString(digit2) << endl();
 557                 #endif
 558                 if (digit2 == 0u && digit1 == 0u && singleIndirectPageAddress != 0u)
 559                 {
 560                     if (digit0 == 0u)
 561                     {
 562                         freeSingleIndirectPage = true;
 563                     }
 564                     ulong entryAddress = singleIndirectPageAddress + 8u * digit0;
 565                     ulong pte = ReadMemoryULong(entryAddress);
 566                     if (pte != 0u)
 567                     {
 568                         ulong pageAddress = 0u;
 569                         ushort pteAddressSpaceNumber = 0u;
 570                         Protection protection = Protection.notPresent;
 571                         UnpackPageTableEntry(ptepageAddresspteAddressSpaceNumberprotection);
 572                         if (protection != Protection.notPresent && pageAddress != 0u)
 573                         {
 574                             #if (MEMORY_DEBUG)
 575                                 Console.Out() << "entry address: " << ToHexString(entryAddress) << ", page address: " << ToHexString(pageAddress) << ", pte: " << ToHexString(pte) << endl();
 576                             #endif
 577                             mem.FreePage(pageAddress);
 578                             WriteMemoryULong(entryAddress0u);
 579                         }
 580                     }
 581                     if (digit0 == maxDigit && freeSingleIndirectPage)
 582                     {
 583                         mem.FreePage(singleIndirectPageAddress);
 584                         WriteMemoryULong(singleIndirectEntryAddress0u);
 585                         freeSingleIndirectPage = false;
 586                     }
 587                 }
 588                 else if (digit2 == 0u && digit1 > 0u)
 589                 {
 590                     if (digit1 == 1u && digit0 == 0u)
 591                     {
 592                         freeDoubleIndirectPage = true;
 593                     }
 594                     if (!doubleIndirectEntryAddressInitialized)
 595                     {
 596                         ulong entryAddress = rootPageAddress + 8u * doubleIndirectEntryNumber;
 597                         doubleIndirectEntryAddress = entryAddress;
 598                         ulong pte = ReadMemoryULong(entryAddress);
 599                         if (pte != 0u)
 600                         {
 601                             ulong pageAddress = 0u;
 602                             ushort pteAddressSpaceNumber = 0u;
 603                             Protection protection = Protection.notPresent;
 604                             UnpackPageTableEntry(ptepageAddresspteAddressSpaceNumberprotection);
 605                             if (protection != Protection.notPresent && pageAddress != 0u)
 606                             {
 607                                 doubleIndirectPageAddress = pageAddress;
 608                             }
 609                         }
 610                         doubleIndirectEntryAddressInitialized = true;
 611                     }
 612                     if (doubleIndirectPageAddress != 0u)
 613                     {
 614                         if (digit1 != prevDigit1)
 615                         {
 616                             ulong entryAddress = doubleIndirectPageAddress + 8u * digit1;
 617                             diSingleIndirectEntryAddress = entryAddress;
 618                             diSingleIndirectEntryNumber = entryNumber;
 619                             ulong pte = ReadMemoryULong(entryAddress);
 620                             if (pte != 0u)
 621                             {
 622                                 ulong pageAddress = 0u;
 623                                 ushort pteAddressSpaceNumber = 0u;
 624                                 Protection protection = Protection.notPresent;
 625                                 UnpackPageTableEntry(ptepageAddresspteAddressSpaceNumberprotection);
 626                                 if (protection != Protection.notPresent && pageAddress != 0u)
 627                                 {
 628                                     diSingleIndirectPageAddress = pageAddress;
 629                                 }
 630                                 else
 631                                 {
 632                                     diSingleIndirectPageAddress = 0u;
 633                                 }
 634                             }
 635                             else
 636                             {
 637                                 diSingleIndirectPageAddress = 0u;
 638                             }
 639                         }
 640                         if (diSingleIndirectPageAddress != 0u)
 641                         {
 642                             if (digit0 == 0u)
 643                             {
 644                                 freeDiSingleIndirectPage = true;
 645                             }
 646                             ulong entryAddress = diSingleIndirectPageAddress + 8u * digit0;
 647                             ulong pte = ReadMemoryULong(entryAddress);
 648                             if (pte != 0u)
 649                             {
 650                                 ulong pageAddress = 0u;
 651                                 ushort pteAddressSpaceNumber = 0u;
 652                                 Protection protection = Protection.notPresent;
 653                                 UnpackPageTableEntry(ptepageAddresspteAddressSpaceNumberprotection);
 654                                 if (protection != Protection.notPresent && pageAddress != 0u)
 655                                 {
 656                                 #if (MEMORY_DEBUG)
 657                                     Console.Out() << "entry address: " << ToHexString(entryAddress) << ", page address: " << ToHexString(pageAddress) << ", pte: " << ToHexString(pte) << endl();
 658                                 #endif
 659                                     mem.FreePage(pageAddress);
 660                                     WriteMemoryULong(entryAddress0u);
 661                                 }
 662                             }
 663                             if (digit0 == maxDigit && freeDiSingleIndirectPage)
 664                             {
 665                                 mem.FreePage(diSingleIndirectPageAddress);
 666                                 WriteMemoryULong(diSingleIndirectEntryAddress0u);
 667                                 freeDiSingleIndirectPage = false;
 668                             }
 669                         }
 670                         if (digit1 == maxDigit && digit0 == maxDigit && freeDoubleIndirectPage)
 671                         {
 672                             mem.FreePage(doubleIndirectPageAddress);
 673                             WriteMemoryULong(doubleIndirectEntryAddress0u);
 674                             freeDoubleIndirectPage = false;
 675                         }
 676                     }
 677                 }
 678                 else if (digit2 > 0u)
 679                 {
 680                     if (digit2 == 1u && digit1 == 0u && digit0 == 0u)
 681                     {
 682                         freeTripleIndirectPage = true;
 683                     }
 684                     if (!tripleIndirectEntryAddressInitialized)
 685                     {
 686                         ulong entryAddress = rootPageAddress + 8u * tripleIndirectEntryNumber;
 687                         tripleIndirectEntryAddress = entryAddress;
 688                         ulong pte = ReadMemoryULong(entryAddress);
 689                         if (pte != 0u)
 690                         {
 691                             ulong pageAddress = 0u;
 692                             ushort pteAddressSpaceNumber = 0u;
 693                             Protection protection = Protection.notPresent;
 694                             UnpackPageTableEntry(ptepageAddresspteAddressSpaceNumberprotection);
 695                             if (protection != Protection.notPresent && pageAddress != 0u)
 696                             {
 697                                 tripleIndirectPageAddress = pageAddress;
 698                             }
 699                         }
 700                         tripleIndirectEntryAddressInitialized = true;
 701                     }
 702                     if (tripleIndirectPageAddress != 0u)
 703                     {
 704                         if (digit2 != prevDigit2)
 705                         {
 706                             ulong entryAddress = tripleIndirectPageAddress + 8u * digit2;
 707                             tiDoubleIndirectEntryAddress = entryAddress;
 708                             tiDoubleIndirectEntryNumber = entryNumber;
 709                             ulong pte = ReadMemoryULong(entryAddress);
 710                             if (pte != 0u)
 711                             {
 712                                 ulong pageAddress = 0u;
 713                                 ushort pteAddressSpaceNumber = 0u;
 714                                 Protection protection = Protection.notPresent;
 715                                 UnpackPageTableEntry(ptepageAddresspteAddressSpaceNumberprotection);
 716                                 if (protection != Protection.notPresent && pageAddress != 0u)
 717                                 {
 718                                     tiDoubleIndirectPageAddress = pageAddress;
 719                                 }
 720                                 else
 721                                 {
 722                                     tiDoubleIndirectPageAddress = 0u;
 723                                 }
 724                             }
 725                             else
 726                             {
 727                                 tiDoubleIndirectPageAddress = 0u;
 728                             }
 729                         }
 730                         if (tiDoubleIndirectPageAddress != 0u)
 731                         {
 732                             if (digit1 == 0u)
 733                             {
 734                                 freeTiDoubleIndirectPage = true;
 735                             }
 736                             if (digit1 != prevDigit1)
 737                             {
 738                                 ulong entryAddress = tiDoubleIndirectPageAddress + 8u * digit1;
 739                                 tiSingleIndirectEntryAddress = entryAddress;
 740                                 tiSingleIndirectEntryNumber = entryNumber;
 741                                 ulong pte = ReadMemoryULong(entryAddress);
 742                                 if (pte != 0u)
 743                                 {
 744                                     ulong pageAddress = 0u;
 745                                     ushort pteAddressSpaceNumber = 0u;
 746                                     Protection protection = Protection.notPresent;
 747                                     UnpackPageTableEntry(ptepageAddresspteAddressSpaceNumberprotection);
 748                                     if (protection != Protection.notPresent && pageAddress != 0u)
 749                                     {
 750                                         tiSingleIndirectPageAddress = pageAddress;
 751                                     }
 752                                     else
 753                                     {
 754                                         tiSingleIndirectPageAddress = 0u;
 755                                     }
 756                                 }
 757                                 else
 758                                 {
 759                                     tiSingleIndirectPageAddress = 0u;
 760                                 }
 761                             }
 762                             if (tiSingleIndirectPageAddress != 0u)
 763                             {
 764                                 if (digit0 == 0u)
 765                                 {
 766                                     freeTiSingleIndirectPage = true;
 767                                 }
 768                                 ulong entryAddress = tiSingleIndirectPageAddress + 8u * digit0;
 769                                 ulong pte = ReadMemoryULong(entryAddress);
 770                                 if (pte != 0u)
 771                                 {
 772                                     ulong pageAddress = 0u;
 773                                     ushort pteAddressSpaceNumber = 0u;
 774                                     Protection protection = Protection.notPresent;
 775                                     UnpackPageTableEntry(ptepageAddresspteAddressSpaceNumberprotection);
 776                                     if (protection != Protection.notPresent && pageAddress != 0u)
 777                                     {
 778                                     #if (MEMORY_DEBUG)
 779                                         Console.Out() << "entry address: " << ToHexString(entryAddress) << ", page address: " << ToHexString(pageAddress) << ", pte: " << ToHexString(pte) << endl();
 780                                     #endif
 781                                         mem.FreePage(pageAddress);
 782                                         WriteMemoryULong(entryAddress0u);
 783                                     }
 784                                 }
 785                                 if (digit0 == maxDigit && freeTiSingleIndirectPage)
 786                                 {
 787                                     mem.FreePage(tiSingleIndirectPageAddress);
 788                                     WriteMemoryULong(tiSingleIndirectEntryAddress0u);
 789                                     freeTiSingleIndirectPage = false;
 790                                 }
 791                             }
 792                             if (digit1 == maxDigit && digit0 == maxDigit && freeTiDoubleIndirectPage)
 793                             {
 794                                 mem.FreePage(tiDoubleIndirectPageAddress);
 795                                 WriteMemoryULong(tiDoubleIndirectEntryAddress0u);
 796                                 freeTiDoubleIndirectPage = false;
 797                             }
 798                         }
 799                         if (pagesLeft == 1u && freeTripleIndirectPage)
 800                         {
 801                             mem.FreePage(tripleIndirectPageAddress);
 802                             WriteMemoryULong(tripleIndirectEntryAddress0u);
 803                             freeTripleIndirectPage = false;
 804                         }
 805                     }
 806                 }
 807                 prevDigit0 = digit0;
 808                 prevDigit1 = digit1;
 809                 prevDigit2 = digit2;
 810             }
 811             ++entryNumber;
 812             --pagesLeft;
 813         }
 814     }
 815 
 816     public void ShareMemoryPages(Memory& memulong targetRootPageAddressbyte segmentIndexulong startPageNumberulong numPagesushort targetAddressSpaceNumber
 817         ulong sourceRootPageAddressushort sourceAddressSpaceNumberProtection pageProtection)
 818     {
 819         ulong firstRootPageEntryNumber = MakeSegmentOffset(segmentIndex);
 820         ulong lastDirectRootPageEntryNumber = firstRootPageEntryNumber + numDirectEntries - 1u;
 821         ulong firstIndirectEntryNumber = lastDirectRootPageEntryNumber + 1u;
 822         ulong singleIndirectEntryNumber = lastDirectRootPageEntryNumber + 1u;
 823         ulong doubleIndirectEntryNumber = lastDirectRootPageEntryNumber + 2u;
 824         ulong tripleIndirectEntryNumber = lastDirectRootPageEntryNumber + 3u;
 825         ulong sourceSingleIndirectPageAddress = 0u;
 826         ulong targetSingleIndirectPageAddress = 0u;
 827         ulong sourceDoubleIndirectPageAddress = 0u;
 828         ulong targetDoubleIndirectPageAddress = 0u;
 829         ulong sourceTripleIndirectPageAddress = 0u;
 830         ulong targetTripleIndirectPageAddress = 0u;
 831         ulong entryNumber = firstRootPageEntryNumber + startPageNumber;
 832         ulong pagesLeft = numPages;
 833         ushort prevDigit0 = 0u;
 834         ushort prevDigit1 = 0u;
 835         ushort prevDigit2 = 0u;
 836         while (pagesLeft > 0u)
 837         {
 838             if (entryNumber >= firstRootPageEntryNumber && entryNumber <= lastDirectRootPageEntryNumber)
 839             {
 840                 ulong targetEntryAddress = targetRootPageAddress + 8u * entryNumber;
 841                 ulong sourceEntryAddress = sourceRootPageAddress + 8u * entryNumber;
 842                 ulong pte = ReadMemoryULong(sourceEntryAddress);
 843                 if (pte != 0u)
 844                 {
 845                     ulong pageAddress = 0u;
 846                     ushort pteAddressSpaceNumber = 0u;
 847                     Protection protection = Protection.notPresent;
 848                     UnpackPageTableEntry(ptepageAddresspteAddressSpaceNumberprotection);
 849                     if (protection != Protection.notPresent && pageAddress != 0u)
 850                     {
 851                         mem.SharePage(pageAddress);
 852                         if (pageProtection == Protection.copyOnWrite)
 853                         {
 854                             pte = MakePageTableEntry(pageAddresssourceAddressSpaceNumberProtection.copyOnWrite);
 855                             WriteMemoryULong(sourceEntryAddresspte);
 856                         }
 857                         pte = MakePageTableEntry(pageAddresstargetAddressSpaceNumberpageProtection);
 858                         WriteMemoryULong(targetEntryAddresspte);
 859                     }
 860                 }
 861             }
 862             else
 863             {
 864                 if (singleIndirectEntryNumber != 0u)
 865                 {
 866                     ulong targetEntryAddress = targetRootPageAddress + 8u * singleIndirectEntryNumber;
 867                     ulong sourceEntryAddress = sourceRootPageAddress + 8u * singleIndirectEntryNumber;
 868                     ulong pte = ReadMemoryULong(sourceEntryAddress);
 869                     sourceSingleIndirectPageAddress = 0u;
 870                     if (pte != 0u)
 871                     {
 872                         ulong pageAddress = 0u;
 873                         ushort pteAddressSpaceNumber = 0u;
 874                         Protection protection = Protection.notPresent;
 875                         UnpackPageTableEntry(ptepageAddresspteAddressSpaceNumberprotection);
 876                         if (protection != Protection.notPresent && pageAddress != 0u)
 877                         {
 878                             sourceSingleIndirectPageAddress = pageAddress;
 879                         }
 880                     }
 881                     if (sourceSingleIndirectPageAddress != 0u)
 882                     {
 883                         targetSingleIndirectPageAddress = mem.AllocatePage();
 884                         pte = MakePageTableEntry(targetSingleIndirectPageAddresstargetAddressSpaceNumberpageProtection);
 885                         WriteMemoryULong(targetEntryAddresspte);
 886                     }
 887                     singleIndirectEntryNumber = 0u;
 888                 }
 889                 ulong pageNum = entryNumber - firstIndirectEntryNumber;
 890                 ushort digit0 = 0u;
 891                 ushort digit1 = 0u;
 892                 ushort digit2 = 0u;
 893                 ExtractDigitsFromPageNumber(pageNumdigit0digit1digit2);
 894                 if (digit2 == 0u && digit1 == 0u)
 895                 {
 896                     ulong sourceEntryAddress = sourceSingleIndirectPageAddress + 8u * digit0;
 897                     ulong targetEntryAddress = targetSingleIndirectPageAddress + 8u * digit0;
 898                     ulong pte = ReadMemoryULong(sourceEntryAddress);
 899                     if (pte != 0u)
 900                     {
 901                         ulong pageAddress = 0u;
 902                         ushort pteAddressSpaceNumber = 0u;
 903                         Protection protection = Protection.notPresent;
 904                         UnpackPageTableEntry(ptepageAddresspteAddressSpaceNumberprotection);
 905                         if (protection != Protection.notPresent && pageAddress != 0u)
 906                         {
 907                             mem.SharePage(pageAddress);
 908                             if (pageProtection == Protection.copyOnWrite)
 909                             {
 910                                 pte = MakePageTableEntry(pageAddresssourceAddressSpaceNumberProtection.copyOnWrite);
 911                                 WriteMemoryULong(sourceEntryAddresspte);
 912                             }
 913                             pte = MakePageTableEntry(pageAddresstargetAddressSpaceNumberpageProtection);
 914                             WriteMemoryULong(targetEntryAddresspte);
 915                         }
 916                     }
 917                 }
 918                 else if (digit2 == 0u && digit1 > 0u)
 919                 {
 920                     if (doubleIndirectEntryNumber != 0u)
 921                     {
 922                         ulong targetEntryAddress = targetRootPageAddress + 8u * doubleIndirectEntryNumber;
 923                         ulong sourceEntryAddress = sourceRootPageAddress + 8u * doubleIndirectEntryNumber;
 924                         ulong pte = ReadMemoryULong(sourceEntryAddress);
 925                         sourceDoubleIndirectPageAddress = 0u;
 926                         if (pte != 0u)
 927                         {
 928                             ulong pageAddress = 0u;
 929                             ushort pteAddressSpaceNumber = 0u;
 930                             Protection protection = Protection.notPresent;
 931                             UnpackPageTableEntry(ptepageAddresspteAddressSpaceNumberprotection);
 932                             if (protection != Protection.notPresent && pageAddress != 0u)
 933                             {
 934                                 sourceDoubleIndirectPageAddress = pageAddress;
 935                             }
 936                         }
 937                         if (sourceDoubleIndirectPageAddress != 0u)
 938                         {
 939                             targetDoubleIndirectPageAddress = mem.AllocatePage();
 940                             pte = MakePageTableEntry(targetDoubleIndirectPageAddresstargetAddressSpaceNumberpageProtection);
 941                             WriteMemoryULong(targetEntryAddresspte);
 942                         }
 943                         doubleIndirectEntryNumber = 0u;
 944                     }
 945                     if (digit1 != prevDigit1)
 946                     {
 947                         ulong targetEntryAddress = targetDoubleIndirectPageAddress + 8u * digit1;
 948                         ulong sourceEntryAddress = sourceDoubleIndirectPageAddress + 8u * digit1;
 949                         ulong pte = ReadMemoryULong(sourceEntryAddress);
 950                         sourceSingleIndirectPageAddress = 0u;
 951                         if (pte != 0u)
 952                         {
 953                             ulong pageAddress = 0u;
 954                             ushort pteAddressSpaceNumber = 0u;
 955                             Protection protection = Protection.notPresent;
 956                             UnpackPageTableEntry(ptepageAddresspteAddressSpaceNumberprotection);
 957                             if (protection != Protection.notPresent && pageAddress != 0u)
 958                             {
 959                                 sourceSingleIndirectPageAddress = pageAddress;
 960                             }
 961                         }
 962                         if (sourceSingleIndirectPageAddress != 0u)
 963                         {
 964                             targetSingleIndirectPageAddress = mem.AllocatePage();
 965                             pte = MakePageTableEntry(targetSingleIndirectPageAddresstargetAddressSpaceNumberpageProtection);
 966                             WriteMemoryULong(targetEntryAddresspte);
 967                         }
 968                     }
 969                     ulong sourceSiEntryAddress = sourceSingleIndirectPageAddress + 8u * digit0;
 970                     ulong targetSiEntryAddress = targetSingleIndirectPageAddress + 8u * digit0;
 971                     ulong pte = ReadMemoryULong(sourceSiEntryAddress);
 972                     if (pte != 0u)
 973                     {
 974                         ulong pageAddress = 0u;
 975                         ushort pteAddressSpaceNumber = 0u;
 976                         Protection protection = Protection.notPresent;
 977                         UnpackPageTableEntry(ptepageAddresspteAddressSpaceNumberprotection);
 978                         if (protection != Protection.notPresent && pageAddress != 0u)
 979                         {
 980                             mem.SharePage(pageAddress);
 981                             if (pageProtection == Protection.copyOnWrite)
 982                             {
 983                                 pte = MakePageTableEntry(pageAddresssourceAddressSpaceNumberProtection.copyOnWrite);
 984                                 WriteMemoryULong(sourceSiEntryAddresspte);
 985                             }
 986                             pte = MakePageTableEntry(pageAddresstargetAddressSpaceNumberpageProtection);
 987                             WriteMemoryULong(targetSiEntryAddresspte);
 988                         }
 989                     }
 990                 }
 991                 else if (digit2 > 0u)
 992                 {
 993                     if (tripleIndirectEntryNumber != 0u)
 994                     {
 995                         ulong targetEntryAddress = targetRootPageAddress + 8u * tripleIndirectEntryNumber;
 996                         ulong sourceEntryAddress = sourceRootPageAddress + 8u * tripleIndirectEntryNumber;
 997                         ulong pte = ReadMemoryULong(sourceEntryAddress);
 998                         sourceTripleIndirectPageAddress = 0u;
 999                         if (pte != 0u)
1000                         {
1001                             ulong pageAddress = 0u;
1002                             ushort pteAddressSpaceNumber = 0u;
1003                             Protection protection = Protection.notPresent;
1004                             UnpackPageTableEntry(ptepageAddresspteAddressSpaceNumberprotection);
1005                             if (protection != Protection.notPresent && pageAddress != 0u)
1006                             {
1007                                 sourceTripleIndirectPageAddress = pageAddress;
1008                             }
1009                         }
1010                         if (sourceTripleIndirectPageAddress != 0u)
1011                         {
1012                             targetTripleIndirectPageAddress = mem.AllocatePage();
1013                             pte = MakePageTableEntry(targetTripleIndirectPageAddresstargetAddressSpaceNumberpageProtection);
1014                             WriteMemoryULong(targetEntryAddresspte);
1015                         }
1016                         tripleIndirectEntryNumber = 0u;
1017                     }
1018                     if (digit2 != prevDigit2)
1019                     {
1020                         ulong targetEntryAddress = targetTripleIndirectPageAddress + 8u * digit2;
1021                         ulong sourceEntryAddress = sourceTripleIndirectPageAddress + 8u * digit2;
1022                         ulong pte = ReadMemoryULong(sourceEntryAddress);
1023                         sourceDoubleIndirectPageAddress = 0u;
1024                         if (pte != 0u)
1025                         {
1026                             ulong pageAddress = 0u;
1027                             ushort pteAddressSpaceNumber = 0u;
1028                             Protection protection = Protection.notPresent;
1029                             UnpackPageTableEntry(ptepageAddresspteAddressSpaceNumberprotection);
1030                             if (protection != Protection.notPresent && pageAddress != 0u)
1031                             {
1032                                 sourceDoubleIndirectPageAddress = pageAddress;
1033                             }
1034                         }
1035                         if (sourceDoubleIndirectPageAddress != 0u)
1036                         {
1037                             targetDoubleIndirectPageAddress = mem.AllocatePage();
1038                             pte = MakePageTableEntry(targetDoubleIndirectPageAddresstargetAddressSpaceNumberpageProtection);
1039                             WriteMemoryULong(targetEntryAddresspte);
1040                         }
1041                     }
1042                     if (digit1 != prevDigit1)
1043                     {
1044                         ulong targetEntryAddress = targetDoubleIndirectPageAddress + 8u * digit1;
1045                         ulong sourceEntryAddress = sourceDoubleIndirectPageAddress + 8u * digit1;
1046                         ulong pte = ReadMemoryULong(sourceEntryAddress);
1047                         sourceSingleIndirectPageAddress = 0u;
1048                         if (pte != 0u)
1049                         {
1050                             ulong pageAddress = 0u;
1051                             ushort pteAddressSpaceNumber = 0u;
1052                             Protection protection = Protection.notPresent;
1053                             UnpackPageTableEntry(ptepageAddresspteAddressSpaceNumberprotection);
1054                             if (protection != Protection.notPresent && pageAddress != 0u)
1055                             {
1056                                 sourceSingleIndirectPageAddress = pageAddress;
1057                             }
1058                         }
1059                         if (sourceSingleIndirectPageAddress != 0u)
1060                         {
1061                             targetSingleIndirectPageAddress = mem.AllocatePage();
1062                             pte = MakePageTableEntry(targetSingleIndirectPageAddresstargetAddressSpaceNumberpageProtection);
1063                             WriteMemoryULong(targetEntryAddresspte);
1064                         }
1065                     }
1066                     ulong sourceSiEntryAddress = sourceSingleIndirectPageAddress + 8u * digit0;
1067                     ulong targetSiEntryAddress = targetSingleIndirectPageAddress + 8u * digit0;
1068                     ulong pte = ReadMemoryULong(sourceSiEntryAddress);
1069                     if (pte != 0u)
1070                     {
1071                         ulong pageAddress = 0u;
1072                         ushort pteAddressSpaceNumber = 0u;
1073                         Protection protection = Protection.notPresent;
1074                         UnpackPageTableEntry(ptepageAddresspteAddressSpaceNumberprotection);
1075                         if (protection != Protection.notPresent && pageAddress != 0u)
1076                         {
1077                             mem.SharePage(pageAddress);
1078                             if (pageProtection == Protection.copyOnWrite)
1079                             {
1080                                 pte = MakePageTableEntry(pageAddresssourceAddressSpaceNumberProtection.copyOnWrite);
1081                                 WriteMemoryULong(sourceSiEntryAddresspte);
1082                             }
1083                             pte = MakePageTableEntry(pageAddresstargetAddressSpaceNumberpageProtection);
1084                             WriteMemoryULong(targetSiEntryAddresspte);
1085                         }
1086                     }
1087                 }
1088                 prevDigit0 = digit0;
1089                 prevDigit1 = digit1;
1090                 prevDigit2 = digit2;
1091             }
1092             ++entryNumber;
1093             --pagesLeft;
1094         }
1095     }
1096 
1097     public void CopyMemoryPages(Memory& memulong targetRootPageAddressbyte segmentIndexulong startPageNumberulong numPagesushort targetAddressSpaceNumber
1098         ulong sourceRootPageAddressushort sourceAddressSpaceNumberProtection pageProtection)
1099     {
1100         ulong firstRootPageEntryNumber = MakeSegmentOffset(segmentIndex);
1101         ulong lastDirectRootPageEntryNumber = firstRootPageEntryNumber + numDirectEntries - 1u;
1102         ulong firstIndirectEntryNumber = lastDirectRootPageEntryNumber + 1u;
1103         ulong singleIndirectEntryNumber = lastDirectRootPageEntryNumber + 1u;
1104         ulong doubleIndirectEntryNumber = lastDirectRootPageEntryNumber + 2u;
1105         ulong tripleIndirectEntryNumber = lastDirectRootPageEntryNumber + 3u;
1106         ulong sourceSingleIndirectPageAddress = 0u;
1107         ulong targetSingleIndirectPageAddress = 0u;
1108         ulong sourceDoubleIndirectPageAddress = 0u;
1109         ulong targetDoubleIndirectPageAddress = 0u;
1110         ulong sourceTripleIndirectPageAddress = 0u;
1111         ulong targetTripleIndirectPageAddress = 0u;
1112         ulong entryNumber = firstRootPageEntryNumber + startPageNumber;
1113         ulong pagesLeft = numPages;
1114         ushort prevDigit0 = 0u;
1115         ushort prevDigit1 = 0u;
1116         ushort prevDigit2 = 0u;
1117         while (pagesLeft > 0u)
1118         {
1119             if (entryNumber >= firstRootPageEntryNumber && entryNumber <= lastDirectRootPageEntryNumber)
1120             {
1121                 ulong targetEntryAddress = targetRootPageAddress + 8u * entryNumber;
1122                 ulong sourceEntryAddress = sourceRootPageAddress + 8u * entryNumber;
1123                 ulong pte = ReadMemoryULong(sourceEntryAddress);
1124                 if (pte != 0u)
1125                 {
1126                     ulong sourcePageAddress = 0u;
1127                     ushort pteAddressSpaceNumber = 0u;
1128                     Protection protection = Protection.notPresent;
1129                     UnpackPageTableEntry(ptesourcePageAddresspteAddressSpaceNumberprotection);
1130                     if (protection != Protection.notPresent && sourcePageAddress != 0u)
1131                     {
1132                         ulong targetPageAddress = mem.AllocatePage();
1133                         mem.CopyPage(sourcePageAddresstargetPageAddress);
1134                         pte = MakePageTableEntry(targetPageAddresstargetAddressSpaceNumberprotection);
1135                         WriteMemoryULong(targetEntryAddresspte);
1136                     }
1137                 }
1138             }
1139             else
1140             {
1141                 if (singleIndirectEntryNumber != 0u)
1142                 {
1143                     ulong targetEntryAddress = targetRootPageAddress + 8u * singleIndirectEntryNumber;
1144                     ulong sourceEntryAddress = sourceRootPageAddress + 8u * singleIndirectEntryNumber;
1145                     ulong pte = ReadMemoryULong(sourceEntryAddress);
1146                     sourceSingleIndirectPageAddress = 0u;
1147                     if (pte != 0u)
1148                     {
1149                         ulong pageAddress = 0u;
1150                         ushort pteAddressSpaceNumber = 0u;
1151                         Protection protection = Protection.notPresent;
1152                         UnpackPageTableEntry(ptepageAddresspteAddressSpaceNumberprotection);
1153                         if (protection != Protection.notPresent && pageAddress != 0u)
1154                         {
1155                             sourceSingleIndirectPageAddress = pageAddress;
1156                         }
1157                     }
1158                     if (sourceSingleIndirectPageAddress != 0u)
1159                     {
1160                         targetSingleIndirectPageAddress = mem.AllocatePage();
1161                         pte = MakePageTableEntry(targetSingleIndirectPageAddresstargetAddressSpaceNumberpageProtection);
1162                         WriteMemoryULong(targetEntryAddresspte);
1163                     }
1164                     singleIndirectEntryNumber = 0u;
1165                 }
1166                 ulong pageNum = entryNumber - firstIndirectEntryNumber;
1167                 ushort digit0 = 0u;
1168                 ushort digit1 = 0u;
1169                 ushort digit2 = 0u;
1170                 ExtractDigitsFromPageNumber(pageNumdigit0digit1digit2);
1171                 if (digit2 == 0u && digit1 == 0u)
1172                 {
1173                     ulong sourceEntryAddress = sourceSingleIndirectPageAddress + 8u * digit0;
1174                     ulong targetEntryAddress = targetSingleIndirectPageAddress + 8u * digit0;
1175                     ulong pte = ReadMemoryULong(sourceEntryAddress);
1176                     if (pte != 0u)
1177                     {
1178                         ulong sourcePageAddress = 0u;
1179                         ushort pteAddressSpaceNumber = 0u;
1180                         Protection protection = Protection.notPresent;
1181                         UnpackPageTableEntry(ptesourcePageAddresspteAddressSpaceNumberprotection);
1182                         if (protection != Protection.notPresent && sourcePageAddress != 0u)
1183                         {
1184                             ulong targetPageAddress = mem.AllocatePage();
1185                             mem.CopyPage(sourcePageAddresstargetPageAddress);
1186                             pte = MakePageTableEntry(targetPageAddresstargetAddressSpaceNumberprotection);
1187                             WriteMemoryULong(targetEntryAddresspte);
1188                         }
1189                     }
1190                 }
1191                 else if (digit2 == 0u && digit1 > 0u)
1192                 {
1193                     if (doubleIndirectEntryNumber != 0u)
1194                     {
1195                         ulong targetEntryAddress = targetRootPageAddress + 8u * doubleIndirectEntryNumber;
1196                         ulong sourceEntryAddress = sourceRootPageAddress + 8u * doubleIndirectEntryNumber;
1197                         ulong pte = ReadMemoryULong(sourceEntryAddress);
1198                         sourceDoubleIndirectPageAddress = 0u;
1199                         if (pte != 0u)
1200                         {
1201                             ulong pageAddress = 0u;
1202                             ushort pteAddressSpaceNumber = 0u;
1203                             Protection protection = Protection.notPresent;
1204                             UnpackPageTableEntry(ptepageAddresspteAddressSpaceNumberprotection);
1205                             if (protection != Protection.notPresent && pageAddress != 0u)
1206                             {
1207                                 sourceDoubleIndirectPageAddress = pageAddress;
1208                             }
1209                         }
1210                         if (sourceDoubleIndirectPageAddress != 0u)
1211                         {
1212                             targetDoubleIndirectPageAddress = mem.AllocatePage();
1213                             pte = MakePageTableEntry(targetDoubleIndirectPageAddresstargetAddressSpaceNumberpageProtection);
1214                             WriteMemoryULong(targetEntryAddresspte);
1215                         }
1216                         doubleIndirectEntryNumber = 0u;
1217                     }
1218                     if (digit1 != prevDigit1)
1219                     {
1220                         ulong targetEntryAddress = targetDoubleIndirectPageAddress + 8u * digit1;
1221                         ulong sourceEntryAddress = sourceDoubleIndirectPageAddress + 8u * digit1;
1222                         ulong pte = ReadMemoryULong(sourceEntryAddress);
1223                         sourceSingleIndirectPageAddress = 0u;
1224                         if (pte != 0u)
1225                         {
1226                             ulong pageAddress = 0u;
1227                             ushort pteAddressSpaceNumber = 0u;
1228                             Protection protection = Protection.notPresent;
1229                             UnpackPageTableEntry(ptepageAddresspteAddressSpaceNumberprotection);
1230                             if (protection != Protection.notPresent && pageAddress != 0u)
1231                             {
1232                                 sourceSingleIndirectPageAddress = pageAddress;
1233                             }
1234                         }
1235                         if (sourceSingleIndirectPageAddress != 0u)
1236                         {
1237                             targetSingleIndirectPageAddress = mem.AllocatePage();
1238                             pte = MakePageTableEntry(targetSingleIndirectPageAddresstargetAddressSpaceNumberpageProtection);
1239                             WriteMemoryULong(targetEntryAddresspte);
1240                         }
1241                     }
1242                     ulong sourceSiEntryAddress = sourceSingleIndirectPageAddress + 8u * digit0;
1243                     ulong targetSiEntryAddress = targetSingleIndirectPageAddress + 8u * digit0;
1244                     ulong pte = ReadMemoryULong(sourceSiEntryAddress);
1245                     if (pte != 0u)
1246                     {
1247                         ulong sourcePageAddress = 0u;
1248                         ushort pteAddressSpaceNumber = 0u;
1249                         Protection protection = Protection.notPresent;
1250                         UnpackPageTableEntry(ptesourcePageAddresspteAddressSpaceNumberprotection);
1251                         if (protection != Protection.notPresent && sourcePageAddress != 0u)
1252                         {
1253                             ulong targetPageAddress = mem.AllocatePage();
1254                             mem.CopyPage(sourcePageAddresstargetPageAddress);
1255                             pte = MakePageTableEntry(targetPageAddresstargetAddressSpaceNumberprotection);
1256                             WriteMemoryULong(targetSiEntryAddresspte);
1257                         }
1258                     }
1259                 }
1260                 else if (digit2 > 0u)
1261                 {
1262                     if (tripleIndirectEntryNumber != 0u)
1263                     {
1264                         ulong targetEntryAddress = targetRootPageAddress + 8u * tripleIndirectEntryNumber;
1265                         ulong sourceEntryAddress = sourceRootPageAddress + 8u * tripleIndirectEntryNumber;
1266                         ulong pte = ReadMemoryULong(sourceEntryAddress);
1267                         sourceTripleIndirectPageAddress = 0u;
1268                         if (pte != 0u)
1269                         {
1270                             ulong pageAddress = 0u;
1271                             ushort pteAddressSpaceNumber = 0u;
1272                             Protection protection = Protection.notPresent;
1273                             UnpackPageTableEntry(ptepageAddresspteAddressSpaceNumberprotection);
1274                             if (protection != Protection.notPresent && pageAddress != 0u)
1275                             {
1276                                 sourceTripleIndirectPageAddress = pageAddress;
1277                             }
1278                         }
1279                         if (sourceTripleIndirectPageAddress != 0u)
1280                         {
1281                             targetTripleIndirectPageAddress = mem.AllocatePage();
1282                             pte = MakePageTableEntry(targetTripleIndirectPageAddresstargetAddressSpaceNumberpageProtection);
1283                             WriteMemoryULong(targetEntryAddresspte);
1284                         }
1285                         tripleIndirectEntryNumber = 0u;
1286                     }
1287                     if (digit2 != prevDigit2)
1288                     {
1289                         ulong targetEntryAddress = targetTripleIndirectPageAddress + 8u * digit2;
1290                         ulong sourceEntryAddress = sourceTripleIndirectPageAddress + 8u * digit2;
1291                         ulong pte = ReadMemoryULong(sourceEntryAddress);
1292                         sourceDoubleIndirectPageAddress = 0u;
1293                         if (pte != 0u)
1294                         {
1295                             ulong pageAddress = 0u;
1296                             ushort pteAddressSpaceNumber = 0u;
1297                             Protection protection = Protection.notPresent;
1298                             UnpackPageTableEntry(ptepageAddresspteAddressSpaceNumberprotection);
1299                             if (protection != Protection.notPresent && pageAddress != 0u)
1300                             {
1301                                 sourceDoubleIndirectPageAddress = pageAddress;
1302                             }
1303                         }
1304                         if (sourceDoubleIndirectPageAddress != 0u)
1305                         {
1306                             targetDoubleIndirectPageAddress = mem.AllocatePage();
1307                             pte = MakePageTableEntry(targetDoubleIndirectPageAddresstargetAddressSpaceNumberpageProtection);
1308                             WriteMemoryULong(targetEntryAddresspte);
1309                         }
1310                     }
1311                     if (digit1 != prevDigit1)
1312                     {
1313                         ulong targetEntryAddress = targetDoubleIndirectPageAddress + 8u * digit1;
1314                         ulong sourceEntryAddress = sourceDoubleIndirectPageAddress + 8u * digit1;
1315                         ulong pte = ReadMemoryULong(sourceEntryAddress);
1316                         sourceSingleIndirectPageAddress = 0u;
1317                         if (pte != 0u)
1318                         {
1319                             ulong pageAddress = 0u;
1320                             ushort pteAddressSpaceNumber = 0u;
1321                             Protection protection = Protection.notPresent;
1322                             UnpackPageTableEntry(ptepageAddresspteAddressSpaceNumberprotection);
1323                             if (protection != Protection.notPresent && pageAddress != 0u)
1324                             {
1325                                 sourceSingleIndirectPageAddress = pageAddress;
1326                             }
1327                         }
1328                         if (sourceSingleIndirectPageAddress != 0u)
1329                         {
1330                             targetSingleIndirectPageAddress = mem.AllocatePage();
1331                             pte = MakePageTableEntry(targetSingleIndirectPageAddresstargetAddressSpaceNumberpageProtection);
1332                             WriteMemoryULong(targetEntryAddresspte);
1333                         }
1334                     }
1335                     ulong sourceSiEntryAddress = sourceSingleIndirectPageAddress + 8u * digit0;
1336                     ulong targetSiEntryAddress = targetSingleIndirectPageAddress + 8u * digit0;
1337                     ulong pte = ReadMemoryULong(sourceSiEntryAddress);
1338                     if (pte != 0u)
1339                     {
1340                         ulong sourcePageAddress = 0u;
1341                         ushort pteAddressSpaceNumber = 0u;
1342                         Protection protection = Protection.notPresent;
1343                         UnpackPageTableEntry(ptesourcePageAddresspteAddressSpaceNumberprotection);
1344                         if (protection != Protection.notPresent && sourcePageAddress != 0u)
1345                         {
1346                             ulong targetPageAddress = mem.AllocatePage();
1347                             mem.CopyPage(sourcePageAddresstargetPageAddress);
1348                             pte = MakePageTableEntry(targetPageAddresstargetAddressSpaceNumberprotection);
1349                             WriteMemoryULong(targetSiEntryAddresspte);
1350                         }
1351                     }
1352                 }
1353                 prevDigit0 = digit0;
1354                 prevDigit1 = digit1;
1355                 prevDigit2 = digit2;
1356             }
1357             ++entryNumber;
1358             --pagesLeft;
1359         }
1360     }
1361 
1362     public void AllocateMemory(Memory& memconst MemoryTable& memoryTablebool skipTextSegment)
1363     {
1364         mem.ClearTranslationCache(memoryTable.addressSpaceNumber);
1365         for (byte i = 0u; i < numSegments; ++i;)
1366         {
1367             if (skipTextSegment && i == textSegmentIndex) continue;
1368             SegmentDescriptor* sd = memoryTable.segmentDescriptors[i];
1369             if (sd != null)
1370             {
1371                 ulong startPageNumber = 0u;
1372                 ulong numPages = 0u;
1373                 CalculatePageNumbers(*sdstartPageNumbernumPages);
1374                 AllocateMemoryPages(memmemoryTable.rootPageAddressistartPageNumbernumPagesmemoryTable.addressSpaceNumber);
1375             }
1376         }
1377     }
1378 
1379     public void FreeMemory(Memory& memMemoryTable& memoryTable)
1380     {
1381         for (byte i = 0u; i < numSegments; ++i;)
1382         {
1383             SegmentDescriptor* sd = memoryTable.segmentDescriptors[i];
1384             if (sd != null)
1385             {
1386                 #assert(sd->useCount > 0);
1387                 sd->useCount = sd->useCount - 1u;
1388                 if (sd->useCount == 0u)
1389                 {
1390                     ulong startPageNumber = 0u;
1391                     ulong numPages = 0u;
1392                     CalculatePageNumbers(*sdstartPageNumbernumPages);
1393                     FreeMemoryPages(memmemoryTable.rootPageAddressistartPageNumbernumPages);
1394                     FreeSegmentDescriptor(sd);
1395                 }
1396                 memoryTable.segmentDescriptors[i] = null;
1397             }
1398         }
1399         mem.FreeRootPage(memoryTable.rootPageAddress);
1400         memoryTable.rootPageAddress = 0u;
1401         mem.DisposeTranslationCache(memoryTable.addressSpaceNumber);
1402         GlobalMemoryTable.Instance().RemoveMemoryTable(&memoryTable);
1403     }
1404 
1405     public void CloneMemory(Memory& memMemoryTable& targetMemoryTableMemoryTable& sourceMemoryTable)
1406     {
1407         mem.ClearTranslationCache(sourceMemoryTable.addressSpaceNumber);
1408         mem.ClearTranslationCache(targetMemoryTable.addressSpaceNumber);
1409         for (byte i = 0u; i < numSegments; ++i;)
1410         {
1411             SegmentDescriptor* sd = sourceMemoryTable.segmentDescriptors[i];
1412             if (sd != null)
1413             {
1414                 if (i == textSegmentIndex)
1415                 {
1416                     ShareSegment(memitargetMemoryTablesourceMemoryTableMakeDefaultPageProtection(i));
1417                 }
1418                 else
1419                 {
1420                     CopySegment(memitargetMemoryTablesourceMemoryTableMakeDefaultPageProtection(i));
1421                 }
1422             }
1423         }
1424     }
1425 
1426     public void GrowSegment(Memory& memMemoryTable& memoryTablebyte segmentIndexulong numBytes)
1427     {
1428         if (segmentIndex >= numSegments)
1429         {
1430             throw Exception("invalid segment index " + ToString(segmentIndex));
1431         }
1432         if (numBytes > 0u)
1433         {
1434             SegmentDescriptor* sd = memoryTable.segmentDescriptors[segmentIndex];
1435             if (sd == null)
1436             {
1437                 throw Exception("segment desciptor for segment index " + ToString(segmentIndex) + " is null");
1438             }
1439             ulong startPageNumber = 0u;
1440             ulong numPages = 0u;
1441             CalculatePageNumbers(*sdstartPageNumbernumPages);
1442             startPageNumber = startPageNumber + numPages;
1443             numPages = 0u;
1444             if (numBytes > 0)
1445             {
1446                 numPages = (numBytes - 1u) / pageSize + 1u;
1447             }
1448             AllocateMemoryPages(memmemoryTable.rootPageAddresssegmentIndexstartPageNumbernumPagesmemoryTable.addressSpaceNumber);
1449             ulong oldLength = sd->length;
1450             ulong newLength = oldLength + numPages * pageSize;
1451             sd->length = newLength;
1452             mem.ClearTranslationCache(memoryTable.addressSpaceNumber);
1453         }
1454     }
1455 
1456     public void ShrinkSegment(Memory& memMemoryTable& memoryTablebyte segmentIndexulong numBytes)
1457     {
1458         if (segmentIndex >= numSegments)
1459         {
1460             throw Exception("invalid segment index " + ToString(segmentIndex));
1461         }
1462         if (numBytes >= 0)
1463         {
1464             SegmentDescriptor* sd = memoryTable.segmentDescriptors[segmentIndex];
1465             if (sd == null)
1466             {
1467                 throw Exception("segment descriptor for segment index " + ToString(segmentIndex) + " is null");
1468             }
1469             ulong startPageNumber = 0u;
1470             ulong numPages = 0u;
1471             CalculatePageNumbers(*sdstartPageNumbernumPages);
1472             startPageNumber = startPageNumber + numPages;
1473             numPages = 0u;
1474             if (numBytes > 0)
1475             {
1476                 numPages = (numBytes - 1u) / pageSize + 1u;
1477             }
1478             if (startPageNumber < numPages)
1479             {
1480                 throw Exception("internal error: start page number less than number of pages");
1481             }
1482             startPageNumber = startPageNumber - numPages;
1483             FreeMemoryPages(memmemoryTable.rootPageAddresssegmentIndexstartPageNumbernumPages);
1484             ulong oldLength = sd->length;
1485             ulong newLength = oldLength - numPages * pageSize;
1486             sd->length = newLength;
1487             mem.ClearTranslationCache(memoryTable.addressSpaceNumber);
1488         }
1489     }
1490 
1491     public void ShareSegment(Memory& membyte segmentIndexMemoryTable& targetMemoryTableconst MemoryTable& sourceMemoryTableProtection protection)
1492     {
1493         if (segmentIndex >= numSegments)
1494         {
1495             throw Exception("share segment: invalid segment index " + ToString(segmentIndex));
1496         }
1497         if (targetMemoryTable.segmentDescriptors[segmentIndex] != null)
1498         {
1499             throw Exception("internal error: share segment: target segment descriptor not null");
1500         }
1501         SegmentDescriptor* sourceSegmentDescriptor = sourceMemoryTable.segmentDescriptors[segmentIndex];
1502         if (sourceSegmentDescriptor == null)
1503         {
1504             throw Exception("internal error: share segment: source segment descriptor is null");
1505         }
1506         if (targetMemoryTable.rootPageAddress == 0u)
1507         {
1508             targetMemoryTable.rootPageAddress = mem.AllocateRootPage();
1509         }
1510         SegmentDescriptor* targetSegmentDescriptor = CreateSegmentDescriptor(sourceSegmentDescriptor->startAddresssourceSegmentDescriptor->baseAddresssourceSegmentDescriptor->length);
1511         if (targetSegmentDescriptor == null)
1512         {
1513             throw Exception("internal error: share segment: target segment descriptor is null");
1514         }
1515         targetMemoryTable.segmentDescriptors[segmentIndex] = targetSegmentDescriptor;
1516         ulong startPageNumber = 0u;
1517         ulong numPages = 0u;
1518         CalculatePageNumbers(*targetSegmentDescriptorstartPageNumbernumPages);
1519         ShareMemoryPages(memtargetMemoryTable.rootPageAddresssegmentIndexstartPageNumbernumPagestargetMemoryTable.addressSpaceNumber
1520             sourceMemoryTable.rootPageAddresssourceMemoryTable.addressSpaceNumberprotection);
1521     }
1522 
1523     public void CopySegment(Memory& membyte segmentIndexMemoryTable& targetMemoryTableconst MemoryTable& sourceMemoryTableProtection protection)
1524     {
1525         if (segmentIndex >= numSegments)
1526         {
1527             throw Exception("copy segment: invalid segment index " + ToString(segmentIndex));
1528         }
1529         if (targetMemoryTable.segmentDescriptors[segmentIndex] != null)
1530         {
1531             throw Exception("internal error: copy segment: target segment descriptor not null");
1532         }
1533         SegmentDescriptor* sourceSegmentDescriptor = sourceMemoryTable.segmentDescriptors[segmentIndex];
1534         if (sourceSegmentDescriptor == null)
1535         {
1536             throw Exception("internal error: copy segment: source segment descriptor is null");
1537         }
1538         if (targetMemoryTable.rootPageAddress == 0u)
1539         {
1540             targetMemoryTable.rootPageAddress = mem.AllocateRootPage();
1541         }
1542         SegmentDescriptor* targetSegmentDescriptor = CreateSegmentDescriptor(sourceSegmentDescriptor->startAddresssourceSegmentDescriptor->baseAddresssourceSegmentDescriptor->length);
1543         if (targetSegmentDescriptor == null)
1544         {
1545             throw Exception("internal error: copy segment: target segment descriptor is null");
1546         }
1547         targetMemoryTable.segmentDescriptors[segmentIndex] = targetSegmentDescriptor;
1548         ulong startPageNumber = 0u;
1549         ulong numPages = 0u;
1550         CalculatePageNumbers(*targetSegmentDescriptorstartPageNumbernumPages);
1551         CopyMemoryPages(memtargetMemoryTable.rootPageAddresssegmentIndexstartPageNumbernumPagestargetMemoryTable.addressSpaceNumber
1552             sourceMemoryTable.rootPageAddresssourceMemoryTable.addressSpaceNumberprotection);
1553     }
1554 }