public unsafe void DisposeThreadSafety() { var nativeBlocks = new NativeHeapMemoryBlock[20]; var memoryMappedBlocks = new MemoryMappedFileBlock[20]; var pinnedObjects = new PinnedObject[20]; for (int i = 0; i < nativeBlocks.Length; i++) { nativeBlocks[i] = new NativeHeapMemoryBlock(10); } for (int i = 0; i < memoryMappedBlocks.Length; i++) { memoryMappedBlocks[i] = new MemoryMappedFileBlock(new TestOnceDisposable(), new TestSafeBuffer(), offset: 0, size: 1); } for (int i = 0; i < memoryMappedBlocks.Length; i++) { pinnedObjects[i] = new PinnedObject(new byte[4]); } var worker = new ThreadStart(() => { for (int k = 0; k < 2; k++) { for (int i = 0; i < nativeBlocks.Length; i++) { nativeBlocks[i].Dispose(); Thread.Yield(); } for (int i = 0; i < memoryMappedBlocks.Length; i++) { memoryMappedBlocks[i].Dispose(); Thread.Yield(); } for (int i = 0; i < pinnedObjects.Length; i++) { pinnedObjects[i].Dispose(); Thread.Yield(); } } }); var t1 = new Thread(worker); var t2 = new Thread(worker); var t3 = new Thread(worker); var t4 = new Thread(worker); t1.Start(); t2.Start(); t3.Start(); t4.Start(); t1.Join(); t2.Join(); t3.Join(); t4.Join(); }
// internal for testing internal static unsafe NativeHeapMemoryBlock DecodeEmbeddedPortablePdbDebugDirectoryData(AbstractMemoryBlock block) { NativeHeapMemoryBlock?decompressed; var headerReader = block.GetReader(); if (headerReader.ReadUInt32() != PortablePdbVersions.DebugDirectoryEmbeddedSignature) { throw new BadImageFormatException(SR.UnexpectedEmbeddedPortablePdbDataSignature); } int decompressedSize = headerReader.ReadInt32(); try { decompressed = new NativeHeapMemoryBlock(decompressedSize); } catch { throw new BadImageFormatException(SR.DataTooBig); } bool success = false; try { var compressed = new ReadOnlyUnmanagedMemoryStream(headerReader.CurrentPointer, headerReader.RemainingBytes); var deflate = new DeflateStream(compressed, CompressionMode.Decompress, leaveOpen: true); if (decompressedSize > 0) { int actualLength; try { #if NETCOREAPP3_0_OR_GREATER actualLength = deflate.TryReadAll(new Span <byte>(decompressed.Pointer, decompressed.Size)); #else using var decompressedStream = new UnmanagedMemoryStream(decompressed.Pointer, decompressed.Size, decompressed.Size, FileAccess.Write); deflate.CopyTo(decompressedStream); actualLength = (int)decompressedStream.Position; #endif } catch (Exception e) { throw new BadImageFormatException(e.Message, e.InnerException); } if (actualLength != decompressed.Size) { throw new BadImageFormatException(SR.SizeMismatch); } } // Check that there is no more compressed data left, // in case the decompressed size specified in the header is smaller // than the actual decompressed size of the data. if (deflate.ReadByte() != -1) { throw new BadImageFormatException(SR.SizeMismatch); } success = true; } finally { if (!success) { decompressed.Dispose(); } } return(decompressed); }