Imported Upstream version 4.4.0.40
Former-commit-id: 6427cc082e74df30afc535fd906a3494b74b0817
This commit is contained in:
parent
f3e3aab35a
commit
a632333cc7
@ -84,8 +84,8 @@ DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
|
||||
$(top_srcdir)/configure $(am__configure_deps) \
|
||||
$(srcdir)/config.h.in mkinstalldirs \
|
||||
$(srcdir)/mono-uninstalled.pc.in COPYING.LIB ChangeLog NEWS \
|
||||
compile config.guess config.rpath config.sub install-sh \
|
||||
missing ltmain.sh
|
||||
compile config.guess config.rpath config.sub depcomp \
|
||||
install-sh missing ltmain.sh
|
||||
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
|
||||
am__aclocal_m4_deps = $(top_srcdir)/m4/iconv.m4 \
|
||||
$(top_srcdir)/m4/lib-ld.m4 $(top_srcdir)/m4/lib-link.m4 \
|
||||
|
@ -1 +1 @@
|
||||
79ba3854a41b122e90badfb88a8aba24b6abc54c
|
||||
25ac5dd52e897440dac529dfcfe2034bdae89d53
|
@ -1 +1 @@
|
||||
568cb227ed520bd10d312bf4a66ccba0f772b016
|
||||
3decb1ccc1162ebbe9663424f20f2ace97e2921f
|
@ -293,8 +293,10 @@ namespace System.Diagnostics {
|
||||
internal void WaitUtilEOF() {
|
||||
if( eofEvent != null) {
|
||||
eofEvent.WaitOne();
|
||||
#if !MONO
|
||||
eofEvent.Close();
|
||||
eofEvent = null;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -142,6 +142,11 @@ instead of going through the operating system symbol lookup operation.
|
||||
.I llvm-path=<PREFIX>
|
||||
Same for the llvm tools 'opt' and 'llc'.
|
||||
.TP
|
||||
.I gen-seq-points-file=FILE.msym
|
||||
Instructs the AOT compiler to generate offline sequence points .msym files.
|
||||
The path is optional, if none is passed then a .msym file will be generated
|
||||
next to the input assembly.
|
||||
.TP
|
||||
.I mtriple=<TRIPLE>
|
||||
Use the GNU style target triple <TRIPLE> to determine some code generation options, i.e.
|
||||
--mtriple=armv7-linux-gnueabi will generate code that targets ARMv7. This is currently
|
||||
|
@ -34,7 +34,7 @@ static class Consts
|
||||
// Use these assembly version constants to make code more maintainable.
|
||||
//
|
||||
|
||||
public const string MonoVersion = "4.3.2.0";
|
||||
public const string MonoVersion = "4.4.0.0";
|
||||
public const string MonoCompany = "Mono development team";
|
||||
public const string MonoProduct = "Mono Common Language Infrastructure";
|
||||
public const string MonoCopyright = "(c) Various Mono authors";
|
||||
|
@ -153,7 +153,7 @@ namespace Microsoft.Build.Tasks
|
||||
throw;
|
||||
}
|
||||
|
||||
Log.LogErrorWithCodeFromResources ("XmlPeek.ArgumentError", e.Message);
|
||||
Log.LogError ("MSB3741: Unable to load arguments for the XmlPeek task. {0}", e.Message);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -169,7 +169,7 @@ namespace Microsoft.Build.Tasks
|
||||
throw;
|
||||
}
|
||||
|
||||
Log.LogErrorWithCodeFromResources ("XmlPeekPoke.InputFileError", _xmlInputPath.ItemSpec, e.Message);
|
||||
Log.LogError ("MSB3733: Input file \"{0}\" cannot be opened. {1}", _xmlInputPath.ItemSpec, e.Message);
|
||||
return false;
|
||||
} finally {
|
||||
xmlinput.CloseReader ();
|
||||
@ -185,7 +185,7 @@ namespace Microsoft.Build.Tasks
|
||||
throw;
|
||||
}
|
||||
|
||||
Log.LogErrorWithCodeFromResources ("XmlPeekPoke.XPathError", _query, e.Message);
|
||||
Log.LogError ("MSB3734: XPath Query \"{0}\" cannot be loaded. {1}", _query, e.Message);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -199,14 +199,14 @@ namespace Microsoft.Build.Tasks
|
||||
throw;
|
||||
}
|
||||
|
||||
Log.LogErrorWithCodeFromResources ("XmlPeek.NamespacesError", e.Message);
|
||||
Log.LogError ("MSB3742: Unable to process the Namespaces argument for the XmlPeek task. {0}", e.Message);
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
expr.SetContext (xmlNamespaceManager);
|
||||
} catch (XPathException e) {
|
||||
Log.LogErrorWithCodeFromResources ("XmlPeek.XPathContextError", e.Message);
|
||||
Log.LogError ("MSB3743: Unable to set XPath expression's Context. {0}", e.Message);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -228,12 +228,12 @@ namespace Microsoft.Build.Tasks
|
||||
_result [i++] = new TaskItem (item);
|
||||
|
||||
// This can be logged a lot, so low importance
|
||||
Log.LogMessageFromResources (MessageImportance.Low, "XmlPeek.Found", item);
|
||||
Log.LogMessage (MessageImportance.Low, "Found \"{0}\".", item);
|
||||
}
|
||||
|
||||
if (_result.Length == 0) {
|
||||
// Logged no more than once per execute of this task
|
||||
Log.LogMessageFromResources ("XmlPeek.NotFound");
|
||||
Log.LogMessage ("The specified XPath query did not capture any nodes.");
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -21,5 +21,5 @@ EXTRA_DISTFILES = Mono.Security.Interface/README.md
|
||||
|
||||
#
|
||||
# Update this comment to trigger a build in System
|
||||
# +1
|
||||
# +2
|
||||
#
|
||||
|
@ -49,7 +49,7 @@ namespace Mono.Security.Interface
|
||||
set { checkCertRevocationStatus = value; }
|
||||
}
|
||||
|
||||
public bool UseServicePointManagerCallback {
|
||||
public bool? UseServicePointManagerCallback {
|
||||
get { return useServicePointManagerCallback; }
|
||||
set { useServicePointManagerCallback = value; }
|
||||
}
|
||||
@ -89,7 +89,7 @@ namespace Mono.Security.Interface
|
||||
bool cloned = false;
|
||||
bool checkCertName = true;
|
||||
bool checkCertRevocationStatus = false;
|
||||
bool useServicePointManagerCallback = true;
|
||||
bool? useServicePointManagerCallback = null;
|
||||
bool skipSystemValidators = false;
|
||||
bool callbackNeedsChain = true;
|
||||
ICertificateValidator certificateValidator;
|
||||
|
@ -128,12 +128,25 @@ namespace Mono.Security.X509 {
|
||||
|
||||
string filename = Path.Combine (_storePath, GetUniqueName (certificate));
|
||||
if (!File.Exists (filename)) {
|
||||
using (FileStream fs = File.Create (filename)) {
|
||||
byte[] data = certificate.RawData;
|
||||
fs.Write (data, 0, data.Length);
|
||||
fs.Close ();
|
||||
filename = Path.Combine (_storePath, GetUniqueNameWithSerial (certificate));
|
||||
if (!File.Exists (filename)) {
|
||||
using (FileStream fs = File.Create (filename)) {
|
||||
byte[] data = certificate.RawData;
|
||||
fs.Write (data, 0, data.Length);
|
||||
fs.Close ();
|
||||
}
|
||||
ClearCertificates (); // We have modified the store on disk. So forget the old state.
|
||||
}
|
||||
} else {
|
||||
string newfilename = Path.Combine (_storePath, GetUniqueNameWithSerial (certificate));
|
||||
if (GetUniqueNameWithSerial (LoadCertificate (filename)) != GetUniqueNameWithSerial (certificate)) {
|
||||
using (FileStream fs = File.Create (newfilename)) {
|
||||
byte[] data = certificate.RawData;
|
||||
fs.Write (data, 0, data.Length);
|
||||
fs.Close ();
|
||||
}
|
||||
ClearCertificates (); // We have modified the store on disk. So forget the old state.
|
||||
}
|
||||
ClearCertificates (); // We have modified the store on disk. So forget the old state.
|
||||
}
|
||||
#if !NET_2_1
|
||||
// Try to save privateKey if available..
|
||||
@ -164,10 +177,16 @@ namespace Mono.Security.X509 {
|
||||
|
||||
public void Remove (X509Certificate certificate)
|
||||
{
|
||||
string filename = Path.Combine (_storePath, GetUniqueName (certificate));
|
||||
string filename = Path.Combine (_storePath, GetUniqueNameWithSerial (certificate));
|
||||
if (File.Exists (filename)) {
|
||||
File.Delete (filename);
|
||||
ClearCertificates (); // We have modified the store on disk. So forget the old state.
|
||||
} else {
|
||||
filename = Path.Combine (_storePath, GetUniqueName (certificate));
|
||||
if (File.Exists (filename)) {
|
||||
File.Delete (filename);
|
||||
ClearCertificates (); // We have modified the store on disk. So forget the old state.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -182,10 +201,15 @@ namespace Mono.Security.X509 {
|
||||
|
||||
// private stuff
|
||||
|
||||
private string GetUniqueName (X509Certificate certificate)
|
||||
private string GetUniqueNameWithSerial (X509Certificate certificate)
|
||||
{
|
||||
return GetUniqueName (certificate, certificate.SerialNumber);
|
||||
}
|
||||
|
||||
private string GetUniqueName (X509Certificate certificate, byte[] serial = null)
|
||||
{
|
||||
string method;
|
||||
byte[] name = GetUniqueName (certificate.Extensions);
|
||||
byte[] name = GetUniqueName (certificate.Extensions, serial);
|
||||
if (name == null) {
|
||||
method = "tbp"; // thumbprint
|
||||
name = certificate.Hash;
|
||||
@ -208,7 +232,7 @@ namespace Mono.Security.X509 {
|
||||
return GetUniqueName (method, name, ".crl");
|
||||
}
|
||||
|
||||
private byte[] GetUniqueName (X509ExtensionCollection extensions)
|
||||
private byte[] GetUniqueName (X509ExtensionCollection extensions, byte[] serial = null)
|
||||
{
|
||||
// We prefer Subject Key Identifier as the unique name
|
||||
// as it will provide faster lookups
|
||||
@ -217,7 +241,14 @@ namespace Mono.Security.X509 {
|
||||
return null;
|
||||
|
||||
SubjectKeyIdentifierExtension ski = new SubjectKeyIdentifierExtension (ext);
|
||||
return ski.Identifier;
|
||||
if (serial == null) {
|
||||
return ski.Identifier;
|
||||
} else {
|
||||
byte[] uniqueWithSerial = new byte[ski.Identifier.Length + serial.Length];
|
||||
System.Buffer.BlockCopy (ski.Identifier, 0, uniqueWithSerial, 0, ski.Identifier.Length );
|
||||
System.Buffer.BlockCopy (serial, 0, uniqueWithSerial, ski.Identifier.Length, serial.Length );
|
||||
return uniqueWithSerial;
|
||||
}
|
||||
}
|
||||
|
||||
private string GetUniqueName (string method, byte[] name, string fileExtension)
|
||||
|
@ -22,7 +22,7 @@ namespace SharpCompress.Writer.Zip
|
||||
byte[] encodedFilename = Encoding.UTF8.GetBytes(FileName);
|
||||
byte[] encodedComment = Encoding.UTF8.GetBytes(Comment);
|
||||
|
||||
outputStream.Write(new byte[] {80, 75, 1, 2, 0x3F, 0, 0x0A, 0}, 0, 8);
|
||||
outputStream.Write(new byte[] {80, 75, 1, 2, 0x14, 0, 0x0A, 0}, 0, 8);
|
||||
HeaderFlags flags = HeaderFlags.UTF8;
|
||||
if (!outputStream.CanSeek)
|
||||
{
|
||||
|
@ -142,7 +142,7 @@ namespace SharpCompress.Writer.Zip
|
||||
byte[] encodedFilename = encoding.GetBytes(filename);
|
||||
|
||||
OutputStream.Write(BitConverter.GetBytes(ZipHeaderFactory.ENTRY_HEADER_BYTES), 0, 4);
|
||||
OutputStream.Write(new byte[] {63, 0}, 0, 2); //version
|
||||
OutputStream.Write(new byte[] {20, 0}, 0, 2); //version
|
||||
HeaderFlags flags = encoding == Encoding.UTF8 ? HeaderFlags.UTF8 : (HeaderFlags)0;
|
||||
if (!OutputStream.CanSeek)
|
||||
{
|
||||
|
@ -114,6 +114,51 @@ namespace MonoTests.System.IO.Compression
|
||||
File.Delete ("test.zip");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ZipOpenAndReopenEntry()
|
||||
{
|
||||
try {
|
||||
File.Copy("archive.zip", "test.zip", overwrite: true);
|
||||
using (var archive = new ZipArchive(File.Open("test.zip", FileMode.Open),
|
||||
ZipArchiveMode.Update))
|
||||
{
|
||||
var entry = archive.GetEntry("foo.txt");
|
||||
Assert.IsNotNull(entry);
|
||||
|
||||
var stream = entry.Open();
|
||||
|
||||
try {
|
||||
stream = entry.Open();
|
||||
} catch (global::System.IO.IOException ex) {
|
||||
return;
|
||||
}
|
||||
|
||||
Assert.Fail();
|
||||
}
|
||||
} finally {
|
||||
File.Delete ("test.zip");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
[Test]
|
||||
public void ZipOpenCloseAndReopenEntry()
|
||||
{
|
||||
File.Copy("archive.zip", "test.zip", overwrite: true);
|
||||
using (var archive = new ZipArchive(File.Open("test.zip", FileMode.Open),
|
||||
ZipArchiveMode.Update))
|
||||
{
|
||||
var entry = archive.GetEntry("foo.txt");
|
||||
Assert.IsNotNull(entry);
|
||||
|
||||
var stream = entry.Open();
|
||||
stream.Dispose();
|
||||
stream = entry.Open();
|
||||
}
|
||||
|
||||
File.Delete ("test.zip");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ZipGetEntryDeleteReadMode()
|
||||
{
|
||||
|
@ -29,10 +29,96 @@ using SharpCompress.Archive;
|
||||
|
||||
namespace System.IO.Compression
|
||||
{
|
||||
internal class ZipArchiveEntryStream : Stream, IDisposable
|
||||
{
|
||||
private readonly ZipArchiveEntry entry;
|
||||
private readonly Stream stream;
|
||||
|
||||
public override bool CanRead {
|
||||
get {
|
||||
return stream.CanRead;
|
||||
}
|
||||
}
|
||||
|
||||
public override bool CanSeek {
|
||||
get {
|
||||
return stream.CanSeek;
|
||||
}
|
||||
}
|
||||
|
||||
public override bool CanWrite {
|
||||
get {
|
||||
return stream.CanWrite;
|
||||
}
|
||||
}
|
||||
|
||||
public override long Length {
|
||||
get {
|
||||
return stream.Length;
|
||||
}
|
||||
}
|
||||
|
||||
public override long Position {
|
||||
get {
|
||||
return stream.Position;
|
||||
}
|
||||
set {
|
||||
stream.Position = value;
|
||||
}
|
||||
}
|
||||
|
||||
public ZipArchiveEntryStream(ZipArchiveEntry entry, Stream stream)
|
||||
{
|
||||
this.entry = entry;
|
||||
this.stream = stream;
|
||||
}
|
||||
|
||||
public override void Flush ()
|
||||
{
|
||||
stream.Flush();
|
||||
}
|
||||
|
||||
public override long Seek (long offset, SeekOrigin origin)
|
||||
{
|
||||
return stream.Seek(offset, origin);
|
||||
}
|
||||
|
||||
public override void SetLength (long value)
|
||||
{
|
||||
stream.SetLength(value);
|
||||
}
|
||||
|
||||
public override int Read (byte[] buffer, int offset, int count)
|
||||
{
|
||||
return stream.Read(buffer, offset, count);
|
||||
}
|
||||
|
||||
public override void Write (byte[] buffer, int offset, int count)
|
||||
{
|
||||
stream.Write(buffer, offset, count);
|
||||
}
|
||||
|
||||
public new void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
base.Dispose();
|
||||
}
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
entry.openStream = null;
|
||||
stream.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class ZipArchiveEntry
|
||||
{
|
||||
readonly SharpCompress.Archive.Zip.ZipArchiveEntry entry;
|
||||
private Stream openStream;
|
||||
internal ZipArchiveEntryStream openStream;
|
||||
private bool wasDeleted;
|
||||
|
||||
internal ZipArchiveEntry(ZipArchive archive, SharpCompress.Archive.Zip.ZipArchiveEntry entry)
|
||||
@ -112,7 +198,7 @@ namespace System.IO.Compression
|
||||
if (Archive.Mode == ZipArchiveMode.Create && openStream != null)
|
||||
throw new IOException("The archive for this entry was opened with the Create mode, and this entry has already been written to.");
|
||||
|
||||
openStream = entry.OpenEntryStream();
|
||||
openStream = new ZipArchiveEntryStream(this, entry.OpenEntryStream());
|
||||
|
||||
return openStream;
|
||||
}
|
||||
|
@ -442,7 +442,7 @@ namespace System.Json
|
||||
{
|
||||
if (value == null)
|
||||
throw new ArgumentNullException ("value");
|
||||
return Convert.ToUInt16 (((JsonPrimitive) value).Value, NumberFormatInfo.InvariantInfo);
|
||||
return Convert.ToUInt32 (((JsonPrimitive) value).Value, NumberFormatInfo.InvariantInfo);
|
||||
}
|
||||
|
||||
public static implicit operator ulong (JsonValue value)
|
||||
|
@ -112,6 +112,30 @@ namespace MonoTests.System
|
||||
Assert.AreEqual (number, jvalue); // should be exactly the same
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CheckIntegers ()
|
||||
{
|
||||
Assert.AreEqual (sbyte.MinValue, (sbyte) JsonValue.Parse (new JsonPrimitive (sbyte.MinValue).ToString ()));
|
||||
Assert.AreEqual (sbyte.MaxValue, (sbyte) JsonValue.Parse (new JsonPrimitive (sbyte.MaxValue).ToString ()));
|
||||
Assert.AreEqual (byte.MinValue, (byte) JsonValue.Parse (new JsonPrimitive (byte.MinValue).ToString ()));
|
||||
Assert.AreEqual (byte.MaxValue, (byte) JsonValue.Parse (new JsonPrimitive (byte.MaxValue).ToString ()));
|
||||
|
||||
Assert.AreEqual (short.MinValue, (short) JsonValue.Parse (new JsonPrimitive (short.MinValue).ToString ()));
|
||||
Assert.AreEqual (short.MaxValue, (short) JsonValue.Parse (new JsonPrimitive (short.MaxValue).ToString ()));
|
||||
Assert.AreEqual (ushort.MinValue, (ushort) JsonValue.Parse (new JsonPrimitive (ushort.MinValue).ToString ()));
|
||||
Assert.AreEqual (ushort.MaxValue, (ushort) JsonValue.Parse (new JsonPrimitive (ushort.MaxValue).ToString ()));
|
||||
|
||||
Assert.AreEqual (int.MinValue, (int) JsonValue.Parse (new JsonPrimitive (int.MinValue).ToString ()));
|
||||
Assert.AreEqual (int.MaxValue, (int) JsonValue.Parse (new JsonPrimitive (int.MaxValue).ToString ()));
|
||||
Assert.AreEqual (uint.MinValue, (uint) JsonValue.Parse (new JsonPrimitive (uint.MinValue).ToString ()));
|
||||
Assert.AreEqual (uint.MaxValue, (uint) JsonValue.Parse (new JsonPrimitive (uint.MaxValue).ToString ()));
|
||||
|
||||
Assert.AreEqual (long.MinValue, (long) JsonValue.Parse (new JsonPrimitive (long.MinValue).ToString ()));
|
||||
Assert.AreEqual (long.MaxValue, (long) JsonValue.Parse (new JsonPrimitive (long.MaxValue).ToString ()));
|
||||
Assert.AreEqual (ulong.MinValue, (ulong) JsonValue.Parse (new JsonPrimitive (ulong.MinValue).ToString ()));
|
||||
Assert.AreEqual (ulong.MaxValue, (ulong) JsonValue.Parse (new JsonPrimitive (ulong.MaxValue).ToString ()));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CheckNumbers ()
|
||||
{
|
||||
@ -262,3 +286,10 @@ namespace MonoTests.System
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// vim: noexpandtab
|
||||
// Local Variables:
|
||||
// tab-width: 4
|
||||
// c-basic-offset: 4
|
||||
// indent-tabs-mode: t
|
||||
// End:
|
||||
|
@ -0,0 +1 @@
|
||||
#include System.Net.Http.dll.sources
|
@ -0,0 +1 @@
|
||||
#include System.Net.Http.dll.sources
|
@ -237,23 +237,29 @@ namespace Mono.Security.Cryptography {
|
||||
|
||||
private static RSA user;
|
||||
private static RSA machine;
|
||||
private readonly static object user_lock = new object ();
|
||||
private readonly static object machine_lock = new object ();
|
||||
|
||||
private static RSA GetKey (DataProtectionScope scope)
|
||||
{
|
||||
switch (scope) {
|
||||
case DataProtectionScope.CurrentUser:
|
||||
if (user == null) {
|
||||
CspParameters csp = new CspParameters ();
|
||||
csp.KeyContainerName = "DAPI";
|
||||
user = new RSACryptoServiceProvider (1536, csp);
|
||||
lock (user_lock) {
|
||||
CspParameters csp = new CspParameters ();
|
||||
csp.KeyContainerName = "DAPI";
|
||||
user = new RSACryptoServiceProvider (1536, csp);
|
||||
}
|
||||
}
|
||||
return user;
|
||||
case DataProtectionScope.LocalMachine:
|
||||
if (machine == null) {
|
||||
CspParameters csp = new CspParameters ();
|
||||
csp.KeyContainerName = "DAPI";
|
||||
csp.Flags = CspProviderFlags.UseMachineKeyStore;
|
||||
machine = new RSACryptoServiceProvider (1536, csp);
|
||||
lock (machine_lock) {
|
||||
CspParameters csp = new CspParameters ();
|
||||
csp.KeyContainerName = "DAPI";
|
||||
csp.Flags = CspProviderFlags.UseMachineKeyStore;
|
||||
machine = new RSACryptoServiceProvider (1536, csp);
|
||||
}
|
||||
}
|
||||
return machine;
|
||||
default:
|
||||
|
@ -12,6 +12,9 @@
|
||||
using NUnit.Framework;
|
||||
|
||||
using System;
|
||||
using System.Text;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using System.Security.Cryptography;
|
||||
|
||||
namespace MonoTests.System.Security.Cryptography {
|
||||
@ -64,6 +67,31 @@ namespace MonoTests.System.Security.Cryptography {
|
||||
ProtectUnprotect (notMuchEntropy, DataProtectionScope.LocalMachine);
|
||||
}
|
||||
|
||||
[Test] // https://bugzilla.xamarin.com/show_bug.cgi?id=38933
|
||||
public void ProtectCurrentUserMultiThread ()
|
||||
{
|
||||
string data = "Hello World";
|
||||
string entropy = "This is a long string with no meaningful content.";
|
||||
var entropyBytes = Encoding.UTF8.GetBytes (entropy);
|
||||
var dataBytes = Encoding.UTF8.GetBytes (data);
|
||||
var tasks = new List<Task> ();
|
||||
|
||||
for (int i = 0; i < 20; i++)
|
||||
{
|
||||
tasks.Add (new Task (() => {
|
||||
byte[] encryptedBytes = ProtectedData.Protect (dataBytes, entropyBytes, DataProtectionScope.CurrentUser);
|
||||
Assert.IsFalse (IsEmpty (encryptedBytes), "#1");
|
||||
|
||||
byte[] decryptedBytes = ProtectedData.Unprotect (encryptedBytes, entropyBytes, DataProtectionScope.CurrentUser);
|
||||
string decryptedString = Encoding.UTF8.GetString(decryptedBytes);
|
||||
Assert.AreEqual (data, decryptedString, "#2");
|
||||
}, TaskCreationOptions.LongRunning));
|
||||
}
|
||||
|
||||
foreach (var t in tasks) t.Start ();
|
||||
Task.WaitAll (tasks.ToArray ());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DataProtectionScope_All ()
|
||||
{
|
||||
|
@ -160,7 +160,7 @@ namespace Mono.Net.Security
|
||||
certValidationCallback = new ServerCertValidationCallback (callback);
|
||||
}
|
||||
certSelectionCallback = Private.CallbackHelpers.MonoToInternal (settings.ClientCertificateSelectionCallback);
|
||||
fallbackToSPM = settings.UseServicePointManagerCallback;
|
||||
fallbackToSPM = settings.UseServicePointManagerCallback ?? stream != null;
|
||||
}
|
||||
|
||||
if (stream != null) {
|
||||
@ -264,7 +264,7 @@ namespace Mono.Net.Security
|
||||
leaf = certs [0];
|
||||
|
||||
if (tlsStream != null)
|
||||
request.ServicePoint.SetServerCertificate (leaf);
|
||||
request.ServicePoint.UpdateServerCertificate (leaf);
|
||||
|
||||
if (leaf == null) {
|
||||
errors |= SslPolicyErrors.RemoteCertificateNotAvailable;
|
||||
|
@ -109,13 +109,19 @@ namespace Mono.Net.Security
|
||||
ServicePointManager.CheckCertificateRevocationList);
|
||||
|
||||
status = WebExceptionStatus.Success;
|
||||
} catch (Exception ex) {
|
||||
status = WebExceptionStatus.SecureChannelFailure;
|
||||
throw;
|
||||
} finally {
|
||||
if (CertificateValidationFailed)
|
||||
status = WebExceptionStatus.TrustFailure;
|
||||
|
||||
request.ServicePoint.SetClientCertificate (sslStream.InternalLocalCertificate);
|
||||
if (status != WebExceptionStatus.Success)
|
||||
if (status == WebExceptionStatus.Success)
|
||||
request.ServicePoint.UpdateClientCertificate (sslStream.InternalLocalCertificate);
|
||||
else {
|
||||
request.ServicePoint.UpdateClientCertificate (null);
|
||||
sslStream = null;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
|
@ -74,7 +74,7 @@ namespace System.Diagnostics {
|
||||
public bool LoadUserProfile;
|
||||
};
|
||||
|
||||
IntPtr process_handle;
|
||||
SafeProcessHandle process_handle;
|
||||
int pid;
|
||||
int enable_raising_events;
|
||||
Thread background_wait_for_exit_thread;
|
||||
@ -82,13 +82,14 @@ namespace System.Diagnostics {
|
||||
EventHandler exited_event;
|
||||
|
||||
/* Private constructor called from other methods */
|
||||
private Process(IntPtr handle, int id) {
|
||||
private Process (SafeProcessHandle handle, int id) {
|
||||
process_handle = handle;
|
||||
pid=id;
|
||||
}
|
||||
|
||||
public Process ()
|
||||
{
|
||||
process_handle = new SafeProcessHandle ();
|
||||
}
|
||||
|
||||
[MonoTODO]
|
||||
@ -117,14 +118,21 @@ namespace System.Diagnostics {
|
||||
[MonitoringDescription ("The exit code of the process.")]
|
||||
public int ExitCode {
|
||||
get {
|
||||
if (process_handle == IntPtr.Zero)
|
||||
if (process_handle.IsInvalid)
|
||||
throw new InvalidOperationException ("Process has not been started.");
|
||||
|
||||
int code = ExitCode_internal (process_handle);
|
||||
if (code == 259)
|
||||
throw new InvalidOperationException ("The process must exit before getting the requested information.");
|
||||
bool release = false;
|
||||
try {
|
||||
process_handle.DangerousAddRef (ref release);
|
||||
int code = ExitCode_internal (process_handle.DangerousGetHandle ());
|
||||
if (code == 259)
|
||||
throw new InvalidOperationException ("The process must exit before getting the requested information.");
|
||||
|
||||
return code;
|
||||
return code;
|
||||
} finally {
|
||||
if (release)
|
||||
process_handle.DangerousRelease ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -138,14 +146,21 @@ namespace System.Diagnostics {
|
||||
[MonitoringDescription ("The exit time of the process.")]
|
||||
public DateTime ExitTime {
|
||||
get {
|
||||
if (process_handle == IntPtr.Zero)
|
||||
if (process_handle.IsInvalid)
|
||||
throw new InvalidOperationException ("Process has not been started.");
|
||||
|
||||
if (!HasExited)
|
||||
throw new InvalidOperationException ("The process must exit before " +
|
||||
"getting the requested information.");
|
||||
|
||||
return(DateTime.FromFileTime(ExitTime_internal(process_handle)));
|
||||
bool release = false;
|
||||
try {
|
||||
process_handle.DangerousAddRef (ref release);
|
||||
return(DateTime.FromFileTime(ExitTime_internal(process_handle.DangerousGetHandle ())));
|
||||
} finally {
|
||||
if (release)
|
||||
process_handle.DangerousRelease ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -153,9 +168,9 @@ namespace System.Diagnostics {
|
||||
[MonitoringDescription ("Handle for this process.")]
|
||||
public IntPtr Handle {
|
||||
get {
|
||||
if (process_handle == IntPtr.Zero)
|
||||
if (process_handle.IsInvalid)
|
||||
throw new InvalidOperationException ("No process is associated with this object.");
|
||||
return(process_handle);
|
||||
return process_handle.DangerousGetHandle ();
|
||||
}
|
||||
}
|
||||
|
||||
@ -172,16 +187,18 @@ namespace System.Diagnostics {
|
||||
[MonitoringDescription ("Determines if the process is still running.")]
|
||||
public bool HasExited {
|
||||
get {
|
||||
if (process_handle == IntPtr.Zero)
|
||||
if (process_handle.IsInvalid)
|
||||
throw new InvalidOperationException ("Process has not been started.");
|
||||
|
||||
int exitcode = ExitCode_internal (process_handle);
|
||||
bool release = false;
|
||||
try {
|
||||
process_handle.DangerousAddRef (ref release);
|
||||
|
||||
if(exitcode==259) {
|
||||
/* STILL_ACTIVE */
|
||||
return(false);
|
||||
} else {
|
||||
return(true);
|
||||
/* STILL_ACTIVE = 259 */
|
||||
return ExitCode_internal (process_handle.DangerousGetHandle ()) != 259;
|
||||
} finally {
|
||||
if (release)
|
||||
process_handle.DangerousRelease ();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -247,23 +264,33 @@ namespace System.Diagnostics {
|
||||
"The process " + ProcessName +
|
||||
" (ID " + Id + ") has exited");
|
||||
|
||||
int min;
|
||||
int max;
|
||||
bool ok=GetWorkingSet_internal(process_handle, out min, out max);
|
||||
if(ok==false) {
|
||||
throw new Win32Exception();
|
||||
}
|
||||
bool release = false;
|
||||
try {
|
||||
process_handle.DangerousAddRef (ref release);
|
||||
|
||||
return((IntPtr)max);
|
||||
int min, max;
|
||||
if (!GetWorkingSet_internal(process_handle.DangerousGetHandle (), out min, out max))
|
||||
throw new Win32Exception();
|
||||
|
||||
return((IntPtr)max);
|
||||
} finally {
|
||||
if (release)
|
||||
process_handle.DangerousRelease ();
|
||||
}
|
||||
}
|
||||
set {
|
||||
if(HasExited) {
|
||||
throw new InvalidOperationException("The process " + ProcessName + " (ID " + Id + ") has exited");
|
||||
}
|
||||
|
||||
bool ok=SetWorkingSet_internal(process_handle, 0, value.ToInt32(), false);
|
||||
if(ok==false) {
|
||||
throw new Win32Exception();
|
||||
bool release = false;
|
||||
try {
|
||||
process_handle.DangerousAddRef (ref release);
|
||||
if(!SetWorkingSet_internal (process_handle.DangerousGetHandle (), 0, value.ToInt32(), false))
|
||||
throw new Win32Exception();
|
||||
} finally {
|
||||
if (release)
|
||||
process_handle.DangerousRelease ();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -277,12 +304,19 @@ namespace System.Diagnostics {
|
||||
"The process " + ProcessName +
|
||||
" (ID " + Id + ") has exited");
|
||||
|
||||
int min;
|
||||
int max;
|
||||
bool ok= GetWorkingSet_internal (process_handle, out min, out max);
|
||||
if(!ok)
|
||||
throw new Win32Exception();
|
||||
return ((IntPtr) min);
|
||||
bool release = false;
|
||||
try {
|
||||
process_handle.DangerousAddRef (ref release);
|
||||
|
||||
int min, max;
|
||||
if(!GetWorkingSet_internal (process_handle.DangerousGetHandle (), out min, out max))
|
||||
throw new Win32Exception();
|
||||
|
||||
return ((IntPtr) min);
|
||||
} finally {
|
||||
if (release)
|
||||
process_handle.DangerousRelease ();
|
||||
}
|
||||
}
|
||||
set {
|
||||
if(HasExited)
|
||||
@ -290,9 +324,16 @@ namespace System.Diagnostics {
|
||||
"The process " + ProcessName +
|
||||
" (ID " + Id + ") has exited");
|
||||
|
||||
bool ok = SetWorkingSet_internal (process_handle, value.ToInt32(), 0, true);
|
||||
if (!ok)
|
||||
throw new Win32Exception();
|
||||
bool release = false;
|
||||
try {
|
||||
process_handle.DangerousAddRef (ref release);
|
||||
|
||||
if (!SetWorkingSet_internal (process_handle.DangerousGetHandle (), value.ToInt32(), 0, true))
|
||||
throw new Win32Exception();
|
||||
} finally {
|
||||
if (release)
|
||||
process_handle.DangerousRelease ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -310,7 +351,7 @@ namespace System.Diagnostics {
|
||||
get {
|
||||
if (module_collection == null)
|
||||
module_collection = new ProcessModuleCollection(
|
||||
GetModules_internal (process_handle));
|
||||
GetModules_internal (process_handle.DangerousGetHandle ()));
|
||||
return(module_collection);
|
||||
}
|
||||
}
|
||||
@ -452,14 +493,24 @@ namespace System.Diagnostics {
|
||||
[MonitoringDescription ("The relative process priority.")]
|
||||
public ProcessPriorityClass PriorityClass {
|
||||
get {
|
||||
if (process_handle == IntPtr.Zero)
|
||||
if (process_handle.IsInvalid)
|
||||
throw new InvalidOperationException ("Process has not been started.");
|
||||
|
||||
int error;
|
||||
int prio = GetPriorityClass (process_handle, out error);
|
||||
if (prio == 0)
|
||||
throw new Win32Exception (error);
|
||||
return (ProcessPriorityClass) prio;
|
||||
bool release = false;
|
||||
try {
|
||||
process_handle.DangerousAddRef (ref release);
|
||||
|
||||
int error;
|
||||
int prio = GetPriorityClass (process_handle.DangerousGetHandle (), out error);
|
||||
|
||||
if (prio == 0)
|
||||
throw new Win32Exception (error);
|
||||
|
||||
return (ProcessPriorityClass) prio;
|
||||
} finally {
|
||||
if (release)
|
||||
process_handle.DangerousRelease ();
|
||||
}
|
||||
}
|
||||
set {
|
||||
if (!Enum.IsDefined (typeof (ProcessPriorityClass), value))
|
||||
@ -467,22 +518,27 @@ namespace System.Diagnostics {
|
||||
"value", (int) value,
|
||||
typeof (ProcessPriorityClass));
|
||||
|
||||
if (process_handle == IntPtr.Zero)
|
||||
if (process_handle.IsInvalid)
|
||||
throw new InvalidOperationException ("Process has not been started.");
|
||||
|
||||
int error;
|
||||
if (!SetPriorityClass (process_handle, (int) value, out error)) {
|
||||
CheckExited ();
|
||||
throw new Win32Exception (error);
|
||||
bool release = false;
|
||||
try {
|
||||
process_handle.DangerousAddRef (ref release);
|
||||
|
||||
int error;
|
||||
if (!SetPriorityClass (process_handle.DangerousGetHandle (), (int) value, out error)) {
|
||||
if (HasExited)
|
||||
throw new InvalidOperationException (String.Format ("Cannot process request because the process ({0}) has exited.", Id));
|
||||
|
||||
throw new Win32Exception (error);
|
||||
}
|
||||
} finally {
|
||||
if (release)
|
||||
process_handle.DangerousRelease ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CheckExited () {
|
||||
if (HasExited)
|
||||
throw new InvalidOperationException (String.Format ("Cannot process request because the process ({0}) has exited.", Id));
|
||||
}
|
||||
|
||||
[MethodImplAttribute(MethodImplOptions.InternalCall)]
|
||||
static extern int GetPriorityClass (IntPtr handle, out int error);
|
||||
|
||||
@ -514,7 +570,15 @@ namespace System.Diagnostics {
|
||||
[MonitoringDescription ("The amount of processing time spent in the OS core for this process.")]
|
||||
public TimeSpan PrivilegedProcessorTime {
|
||||
get {
|
||||
return new TimeSpan (Times (process_handle, 1));
|
||||
bool release = false;
|
||||
try {
|
||||
process_handle.DangerousAddRef (ref release);
|
||||
|
||||
return new TimeSpan (Times (process_handle.DangerousGetHandle (), 1));
|
||||
} finally {
|
||||
if (release)
|
||||
process_handle.DangerousRelease ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -529,10 +593,20 @@ namespace System.Diagnostics {
|
||||
get {
|
||||
if(process_name==null) {
|
||||
|
||||
if (process_handle == IntPtr.Zero)
|
||||
if (process_handle.IsInvalid)
|
||||
throw new InvalidOperationException ("No process is associated with this object.");
|
||||
|
||||
process_name=ProcessName_internal(process_handle);
|
||||
bool release = false;
|
||||
try {
|
||||
process_handle.DangerousAddRef (ref release);
|
||||
|
||||
process_name=ProcessName_internal(process_handle.DangerousGetHandle ());
|
||||
} finally {
|
||||
if (release)
|
||||
process_handle.DangerousRelease ();
|
||||
}
|
||||
|
||||
|
||||
/* If process_name is _still_
|
||||
* null, assume the process
|
||||
* has exited
|
||||
@ -682,7 +756,15 @@ namespace System.Diagnostics {
|
||||
[MonitoringDescription ("The time this process started.")]
|
||||
public DateTime StartTime {
|
||||
get {
|
||||
return(DateTime.FromFileTime(StartTime_internal(process_handle)));
|
||||
bool release = false;
|
||||
try {
|
||||
process_handle.DangerousAddRef (ref release);
|
||||
|
||||
return(DateTime.FromFileTime(StartTime_internal(process_handle.DangerousGetHandle ())));
|
||||
} finally {
|
||||
if (release)
|
||||
process_handle.DangerousRelease ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -708,7 +790,15 @@ namespace System.Diagnostics {
|
||||
[MonitoringDescription ("The total CPU time spent for this process.")]
|
||||
public TimeSpan TotalProcessorTime {
|
||||
get {
|
||||
return new TimeSpan (Times (process_handle, 2));
|
||||
bool release = false;
|
||||
try {
|
||||
process_handle.DangerousAddRef (ref release);
|
||||
|
||||
return new TimeSpan (Times (process_handle.DangerousGetHandle (), 2));
|
||||
} finally {
|
||||
if (release)
|
||||
process_handle.DangerousRelease ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -716,7 +806,15 @@ namespace System.Diagnostics {
|
||||
[MonitoringDescription ("The CPU time spent for this process in user mode.")]
|
||||
public TimeSpan UserProcessorTime {
|
||||
get {
|
||||
return new TimeSpan (Times (process_handle, 0));
|
||||
bool release = false;
|
||||
try {
|
||||
process_handle.DangerousAddRef (ref release);
|
||||
|
||||
return new TimeSpan (Times (process_handle.DangerousGetHandle (), 0));
|
||||
} finally {
|
||||
if (release)
|
||||
process_handle.DangerousRelease ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -781,14 +879,21 @@ namespace System.Diagnostics {
|
||||
/* int kill -> 1 KILL, 2 CloseMainWindow */
|
||||
bool Close (int signo)
|
||||
{
|
||||
if (process_handle == IntPtr.Zero)
|
||||
if (process_handle.IsInvalid)
|
||||
throw new SystemException ("No process to kill.");
|
||||
|
||||
int exitcode = ExitCode_internal (process_handle);
|
||||
if (exitcode != 259)
|
||||
throw new InvalidOperationException ("The process already finished.");
|
||||
bool release = false;
|
||||
try {
|
||||
process_handle.DangerousAddRef (ref release);
|
||||
|
||||
return Kill_internal (process_handle, signo);
|
||||
if (ExitCode_internal (process_handle.DangerousGetHandle ()) != 259)
|
||||
throw new InvalidOperationException ("The process already finished.");
|
||||
|
||||
return Kill_internal (process_handle.DangerousGetHandle (), signo);
|
||||
} finally {
|
||||
if (release)
|
||||
process_handle.DangerousRelease ();
|
||||
}
|
||||
}
|
||||
|
||||
public bool CloseMainWindow ()
|
||||
@ -814,7 +919,7 @@ namespace System.Diagnostics {
|
||||
if (proc == IntPtr.Zero)
|
||||
throw new SystemException("Can't find current process");
|
||||
|
||||
return (new Process (proc, pid));
|
||||
return (new Process (new SafeProcessHandle (proc), pid));
|
||||
}
|
||||
|
||||
public static Process GetProcessById(int processId)
|
||||
@ -824,7 +929,7 @@ namespace System.Diagnostics {
|
||||
if (proc == IntPtr.Zero)
|
||||
throw new ArgumentException ("Can't find process with ID " + processId.ToString ());
|
||||
|
||||
return (new Process (proc, processId));
|
||||
return (new Process (new SafeProcessHandle (proc), processId));
|
||||
}
|
||||
|
||||
[MonoTODO ("There is no support for retrieving process information from a remote machine")]
|
||||
@ -957,7 +1062,7 @@ namespace System.Diagnostics {
|
||||
throw new Win32Exception (-proc_info.pid);
|
||||
}
|
||||
|
||||
process.process_handle = proc_info.process_handle;
|
||||
process.process_handle = new SafeProcessHandle (proc_info.process_handle);
|
||||
process.pid = proc_info.pid;
|
||||
process.StartBackgroundWaitForExit ();
|
||||
return(ret);
|
||||
@ -1097,7 +1202,7 @@ namespace System.Diagnostics {
|
||||
}
|
||||
}
|
||||
|
||||
process.process_handle = proc_info.process_handle;
|
||||
process.process_handle = new SafeProcessHandle (proc_info.process_handle);
|
||||
process.pid = proc_info.pid;
|
||||
|
||||
if (startInfo.RedirectStandardInput) {
|
||||
@ -1174,9 +1279,8 @@ namespace System.Diagnostics {
|
||||
|
||||
public bool Start ()
|
||||
{
|
||||
if (process_handle != IntPtr.Zero) {
|
||||
Process_free_internal (process_handle);
|
||||
process_handle = IntPtr.Zero;
|
||||
if (!process_handle.IsInvalid) {
|
||||
process_handle.Dispose ();
|
||||
}
|
||||
return Start_common(start_info, this);
|
||||
}
|
||||
@ -1188,7 +1292,7 @@ namespace System.Diagnostics {
|
||||
|
||||
Process process = new Process();
|
||||
process.StartInfo = startInfo;
|
||||
if (Start_common(startInfo, process) && process.process_handle != IntPtr.Zero)
|
||||
if (Start_common(startInfo, process) && !process.process_handle.IsInvalid)
|
||||
return process;
|
||||
return null;
|
||||
}
|
||||
@ -1274,11 +1378,19 @@ namespace System.Diagnostics {
|
||||
if (ms == int.MaxValue)
|
||||
ms = -1;
|
||||
|
||||
if (process_handle == IntPtr.Zero)
|
||||
if (process_handle.IsInvalid)
|
||||
throw new InvalidOperationException ("No process is associated with this object.");
|
||||
|
||||
if (!WaitForExit_internal (process_handle, ms))
|
||||
return false;
|
||||
bool release = false;
|
||||
try {
|
||||
process_handle.DangerousAddRef (ref release);
|
||||
|
||||
if (!WaitForExit_internal (process_handle.DangerousGetHandle (), ms))
|
||||
return false;
|
||||
} finally {
|
||||
if (release)
|
||||
process_handle.DangerousRelease ();
|
||||
}
|
||||
|
||||
#if MONO_FEATURE_PROCESS_START
|
||||
if (async_output != null)
|
||||
@ -1309,7 +1421,15 @@ namespace System.Diagnostics {
|
||||
// The internal call is only implemented properly on Windows.
|
||||
[MonoTODO]
|
||||
public bool WaitForInputIdle(int milliseconds) {
|
||||
return WaitForInputIdle_internal (process_handle, milliseconds);
|
||||
bool release = false;
|
||||
try {
|
||||
process_handle.DangerousAddRef (ref release);
|
||||
|
||||
return WaitForInputIdle_internal (process_handle.DangerousGetHandle (), milliseconds);
|
||||
} finally {
|
||||
if (release)
|
||||
process_handle.DangerousRelease ();
|
||||
}
|
||||
}
|
||||
|
||||
private static bool IsLocalMachine (string machineName)
|
||||
@ -1344,7 +1464,7 @@ namespace System.Diagnostics {
|
||||
[ComVisibleAttribute(false)]
|
||||
public void BeginOutputReadLine ()
|
||||
{
|
||||
if (process_handle == IntPtr.Zero || output_stream == null || StartInfo.RedirectStandardOutput == false)
|
||||
if (process_handle.IsInvalid || output_stream == null || StartInfo.RedirectStandardOutput == false)
|
||||
throw new InvalidOperationException ("Standard output has not been redirected or process has not been started.");
|
||||
|
||||
if ((async_mode & AsyncModes.SyncOutput) != 0)
|
||||
@ -1376,7 +1496,7 @@ namespace System.Diagnostics {
|
||||
[ComVisibleAttribute(false)]
|
||||
public void CancelOutputRead ()
|
||||
{
|
||||
if (process_handle == IntPtr.Zero || output_stream == null || StartInfo.RedirectStandardOutput == false)
|
||||
if (process_handle.IsInvalid || output_stream == null || StartInfo.RedirectStandardOutput == false)
|
||||
throw new InvalidOperationException ("Standard output has not been redirected or process has not been started.");
|
||||
|
||||
if ((async_mode & AsyncModes.SyncOutput) != 0)
|
||||
@ -1393,7 +1513,7 @@ namespace System.Diagnostics {
|
||||
[ComVisibleAttribute(false)]
|
||||
public void BeginErrorReadLine ()
|
||||
{
|
||||
if (process_handle == IntPtr.Zero || error_stream == null || StartInfo.RedirectStandardError == false)
|
||||
if (process_handle.IsInvalid || error_stream == null || StartInfo.RedirectStandardError == false)
|
||||
throw new InvalidOperationException ("Standard error has not been redirected or process has not been started.");
|
||||
|
||||
if ((async_mode & AsyncModes.SyncError) != 0)
|
||||
@ -1425,7 +1545,7 @@ namespace System.Diagnostics {
|
||||
[ComVisibleAttribute(false)]
|
||||
public void CancelErrorRead ()
|
||||
{
|
||||
if (process_handle == IntPtr.Zero || error_stream == null || StartInfo.RedirectStandardError == false)
|
||||
if (process_handle.IsInvalid || error_stream == null || StartInfo.RedirectStandardError == false)
|
||||
throw new InvalidOperationException ("Standard error has not been redirected or process has not been started.");
|
||||
|
||||
if ((async_mode & AsyncModes.SyncOutput) != 0)
|
||||
@ -1468,7 +1588,7 @@ namespace System.Diagnostics {
|
||||
[MonitoringDescription ("Raised when this process exits.")]
|
||||
public event EventHandler Exited {
|
||||
add {
|
||||
if (process_handle != IntPtr.Zero && HasExited) {
|
||||
if (!process_handle.IsInvalid && HasExited) {
|
||||
value.BeginInvoke (null, null, null, null);
|
||||
} else {
|
||||
exited_event += value;
|
||||
@ -1483,7 +1603,7 @@ namespace System.Diagnostics {
|
||||
|
||||
// Closes the system process handle
|
||||
[MethodImplAttribute(MethodImplOptions.InternalCall)]
|
||||
private extern void Process_free_internal(IntPtr handle);
|
||||
private static extern void Process_free_internal(IntPtr handle);
|
||||
|
||||
int disposed;
|
||||
|
||||
@ -1519,9 +1639,8 @@ namespace System.Diagnostics {
|
||||
|
||||
// Release unmanaged resources
|
||||
|
||||
if (process_handle!=IntPtr.Zero) {
|
||||
Process_free_internal (process_handle);
|
||||
process_handle = IntPtr.Zero;
|
||||
if (!process_handle.IsInvalid) {
|
||||
process_handle.Dispose ();
|
||||
}
|
||||
|
||||
base.Dispose (disposing);
|
||||
@ -1572,20 +1691,31 @@ namespace System.Diagnostics {
|
||||
|
||||
void StartBackgroundWaitForExit ()
|
||||
{
|
||||
IntPtr handle = process_handle;
|
||||
SafeProcessHandle handle = process_handle;
|
||||
|
||||
if (enable_raising_events == 0)
|
||||
return;
|
||||
if (exited_event == null)
|
||||
return;
|
||||
if (handle == IntPtr.Zero)
|
||||
if (handle.IsInvalid)
|
||||
return;
|
||||
if (background_wait_for_exit_thread != null)
|
||||
return;
|
||||
|
||||
Thread t = new Thread (_ => {
|
||||
if (!WaitForExit_internal (handle, -1))
|
||||
return;
|
||||
bool release = false;
|
||||
try {
|
||||
handle.DangerousAddRef (ref release);
|
||||
|
||||
if (!WaitForExit_internal (handle.DangerousGetHandle (), -1))
|
||||
return;
|
||||
} catch (ObjectDisposedException) {
|
||||
if (release)
|
||||
throw;
|
||||
} finally {
|
||||
if (release)
|
||||
handle.DangerousRelease ();
|
||||
}
|
||||
|
||||
if (EnableRaisingEvents)
|
||||
OnExited ();
|
||||
@ -1612,6 +1742,26 @@ namespace System.Diagnostics {
|
||||
// closed, so no need to override dispose (bug #464628).
|
||||
}
|
||||
}
|
||||
|
||||
class SafeProcessHandle : SafeHandleZeroOrMinusOneIsInvalid
|
||||
{
|
||||
internal SafeProcessHandle ()
|
||||
: base (false)
|
||||
{
|
||||
}
|
||||
|
||||
internal SafeProcessHandle (IntPtr handle)
|
||||
: base (true)
|
||||
{
|
||||
SetHandle (handle);
|
||||
}
|
||||
|
||||
override protected bool ReleaseHandle ()
|
||||
{
|
||||
Process_free_internal (handle);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1 +1 @@
|
||||
8d48b675ae8cf9ed8a03cab67569bb1c49d9033d
|
||||
0f1c977a71d57169dc91c54c8baa329f65d18b38
|
@ -593,6 +593,7 @@ namespace System.Net
|
||||
CheckRequestStarted ();
|
||||
proxy = value;
|
||||
servicePoint = null; // we may need a new one
|
||||
GetServicePoint ();
|
||||
}
|
||||
}
|
||||
|
||||
@ -969,11 +970,17 @@ namespace System.Net
|
||||
}
|
||||
}
|
||||
|
||||
if (!requestSent) {
|
||||
if (requestSent)
|
||||
return;
|
||||
|
||||
try {
|
||||
requestSent = true;
|
||||
redirects = 0;
|
||||
servicePoint = GetServicePoint ();
|
||||
abortHandler = servicePoint.SendRequest (this, connectionGroup);
|
||||
} catch (Exception ex) {
|
||||
aread.SetCompleted (synch, ex);
|
||||
aread.DoCallback ();
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -49,8 +49,6 @@ namespace System.Net
|
||||
DateTime idleSince;
|
||||
DateTime lastDnsResolve;
|
||||
Version protocolVersion;
|
||||
X509Certificate certificate;
|
||||
X509Certificate clientCertificate;
|
||||
IPHostEntry host;
|
||||
bool usesProxy;
|
||||
Dictionary<string,WebConnectionGroup> groups;
|
||||
@ -92,14 +90,6 @@ namespace System.Net
|
||||
set { endPointCallback = value; }
|
||||
}
|
||||
|
||||
public X509Certificate Certificate {
|
||||
get { return certificate; }
|
||||
}
|
||||
|
||||
public X509Certificate ClientCertificate {
|
||||
get { return clientCertificate; }
|
||||
}
|
||||
|
||||
[MonoTODO]
|
||||
public int ConnectionLeaseTimeout
|
||||
{
|
||||
@ -413,20 +403,55 @@ namespace System.Net
|
||||
return false;
|
||||
}
|
||||
|
||||
internal void SetServerCertificate (X509Certificate server)
|
||||
//
|
||||
// Copied from the referencesource
|
||||
//
|
||||
|
||||
object m_ServerCertificateOrBytes;
|
||||
object m_ClientCertificateOrBytes;
|
||||
|
||||
/// <devdoc>
|
||||
/// <para>
|
||||
/// Gets the certificate received for this <see cref='System.Net.ServicePoint'/>.
|
||||
/// </para>
|
||||
/// </devdoc>
|
||||
public X509Certificate Certificate {
|
||||
get {
|
||||
object chkCert = m_ServerCertificateOrBytes;
|
||||
if (chkCert != null && chkCert.GetType() == typeof(byte[]))
|
||||
return (X509Certificate)(m_ServerCertificateOrBytes = new X509Certificate((byte[]) chkCert));
|
||||
else
|
||||
return chkCert as X509Certificate;
|
||||
}
|
||||
}
|
||||
internal void UpdateServerCertificate(X509Certificate certificate)
|
||||
{
|
||||
var cloned = server != null ? new X509Certificate (server) : null;
|
||||
var old = Interlocked.Exchange (ref certificate, cloned);
|
||||
if (old != null)
|
||||
old.Dispose ();
|
||||
if (certificate != null)
|
||||
m_ServerCertificateOrBytes = certificate.GetRawCertData();
|
||||
else
|
||||
m_ServerCertificateOrBytes = null;
|
||||
}
|
||||
|
||||
internal void SetClientCertificate (X509Certificate clientCertificate)
|
||||
/// <devdoc>
|
||||
/// <para>
|
||||
/// Gets the Client Certificate sent by us to the Server.
|
||||
/// </para>
|
||||
/// </devdoc>
|
||||
public X509Certificate ClientCertificate {
|
||||
get {
|
||||
object chkCert = m_ClientCertificateOrBytes;
|
||||
if (chkCert != null && chkCert.GetType() == typeof(byte[]))
|
||||
return (X509Certificate)(m_ClientCertificateOrBytes = new X509Certificate((byte[]) chkCert));
|
||||
else
|
||||
return chkCert as X509Certificate;
|
||||
}
|
||||
}
|
||||
internal void UpdateClientCertificate(X509Certificate certificate)
|
||||
{
|
||||
var cloned = clientCertificate != null ? new X509Certificate (clientCertificate) : null;
|
||||
var old = Interlocked.Exchange (ref clientCertificate, cloned);
|
||||
if (old != null)
|
||||
old.Dispose ();
|
||||
if (certificate != null)
|
||||
m_ClientCertificateOrBytes = certificate.GetRawCertData();
|
||||
else
|
||||
m_ClientCertificateOrBytes = null;
|
||||
}
|
||||
|
||||
internal bool CallEndPointDelegate (Socket sock, IPEndPoint remote)
|
||||
|
@ -114,7 +114,7 @@ namespace System.Net
|
||||
|
||||
// Static properties
|
||||
|
||||
private static ICertificatePolicy policy = new DefaultCertificatePolicy ();
|
||||
private static ICertificatePolicy policy;
|
||||
private static int defaultConnectionLimit = DefaultPersistentConnectionLimit;
|
||||
private static int maxServicePointIdleTime = 100000; // 100 seconds
|
||||
private static int maxServicePoints = 0;
|
||||
@ -174,7 +174,11 @@ namespace System.Net
|
||||
|
||||
[Obsolete ("Use ServerCertificateValidationCallback instead", false)]
|
||||
public static ICertificatePolicy CertificatePolicy {
|
||||
get { return policy; }
|
||||
get {
|
||||
if (policy == null)
|
||||
Interlocked.CompareExchange (ref policy, new DefaultCertificatePolicy (), null);
|
||||
return policy;
|
||||
}
|
||||
set { policy = value; }
|
||||
}
|
||||
|
||||
@ -328,7 +332,7 @@ namespace System.Net
|
||||
usesProxy = true;
|
||||
bool isSecure = address.Scheme == "https";
|
||||
address = proxy.GetProxy (address);
|
||||
if (address.Scheme != "http" && !isSecure)
|
||||
if (address.Scheme != "http")
|
||||
throw new NotSupportedException ("Proxy scheme not supported.");
|
||||
|
||||
if (isSecure && address.Scheme == "http")
|
||||
|
@ -419,6 +419,7 @@ namespace System.Net
|
||||
status = tlsStream.ExceptionStatus;
|
||||
else if (!request.Aborted)
|
||||
status = WebExceptionStatus.ConnectFailure;
|
||||
connect_exception = ex;
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -992,9 +993,6 @@ namespace System.Net
|
||||
|
||||
internal bool EndWrite (HttpWebRequest request, bool throwOnError, IAsyncResult result)
|
||||
{
|
||||
if (request.FinishedReading)
|
||||
return true;
|
||||
|
||||
Stream s = null;
|
||||
lock (this) {
|
||||
if (status == WebExceptionStatus.RequestCanceled)
|
||||
|
@ -397,6 +397,22 @@ namespace MonoTests.System.IO.Compression
|
||||
compressing.Close ();
|
||||
backing.Close ();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Bug34916_Inflate ()
|
||||
{
|
||||
var base64String = @"H4sIAAAAAAAAA6yVu27bQBBF/4VtZGHeD3ZJmhTp5C5IIUiEIcCWDEUugiD/nmEQwYRNURFAsuFwd2exZ++d+farud89davT+um5aRsC1DuEO+R7lJayRV9m5gegFqBZNB83m5fjevOzadGWUPHjaXd62XYVEy3Z04wiMTKIX0dfV0G/6FO3Pu72D/+iL916W9GbOV/X58SaS6zEKKyoGUA1eNg/nLfF2jUEBBNMtT4Wzeq567Z9HkZkE1Osf93msN/+WO32m+7zsavsh30/BUU8fy+uUCC+QIHpPQW1RAXkEGWUmSnUy2iUYSMYOGpARYViiIHcqY5kExS8rg2vY8gLGEjeYsClBVE4ORQHz3kxsEF4iS01xzBIZkgYQcYQQ7C54LQaIrxWn5+4ioT1BiRQN8Fh6MrOPjOS9Eh3M8YRJJQMZioJkUODFA8RNJ9AYuYBNyGJW5D0oi3/EpZ3dWYk5X5PN81RJGJgDATMQ5X02nFS1imVlMGvu0XwBg5/K1hY1U8tecxcNDy1/FAnG+OAQSi9PliHRaNUiuoxQYFB6T8oyAUKEu9LJ6oipbr1spyZArhWX6qbi7EOUrs7SCAoDNVgzKagMlUz+q6DQ4N8/yM=";
|
||||
|
||||
byte[] byteArray = Convert.FromBase64String(base64String);
|
||||
string unZipped = null;
|
||||
|
||||
using (var zippedMemoryStream = new MemoryStream (byteArray))
|
||||
using (var gZipStream = new GZipStream (zippedMemoryStream, CompressionMode.Decompress))
|
||||
using (var unzippedMemStream = new MemoryStream())
|
||||
using (var unZippedStream = new StreamReader (gZipStream, Encoding.UTF8)) {
|
||||
unZipped = unZippedStream.ReadToEnd ();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1 +1 @@
|
||||
2f85b7b795ef33f0b58ccc3b51269444520bdab9
|
||||
a0e19d4f2d15d6d856fcf37ff33c86c1173274d5
|
1
mcs/class/System/xammac_net_4_5_System.dll.sources
Normal file
1
mcs/class/System/xammac_net_4_5_System.dll.sources
Normal file
@ -0,0 +1 @@
|
||||
#include System.dll.sources
|
@ -288,7 +288,8 @@ namespace System
|
||||
var Istart = 0;
|
||||
while (Istart < str.Length && !char.IsLetterOrDigit(str[Istart])) Istart++;
|
||||
var Iend = str.Length - 1;
|
||||
while (Iend > Istart && !char.IsLetterOrDigit(str[Iend])) Iend--;
|
||||
while (Iend > Istart && !char.IsLetterOrDigit(str[Iend]) && str[Iend] != ')') // zone name can include parentheses like "Central Standard Time (Mexico)"
|
||||
Iend--;
|
||||
|
||||
return str.Substring (Istart, Iend-Istart+1);
|
||||
}
|
||||
|
@ -395,6 +395,96 @@ namespace MonoTests.System.Threading {
|
||||
}
|
||||
}
|
||||
|
||||
#if MONO_FEATURE_THREAD_SUSPEND_RESUME
|
||||
[Test]
|
||||
public void WaitOneWithTimeoutAndSpuriousWake ()
|
||||
{
|
||||
/* This is to test that WaitEvent.WaitOne is not going to wait largely
|
||||
* more than its timeout. In this test, it shouldn't wait more than
|
||||
* 1500 milliseconds, with its timeout being 1000ms */
|
||||
|
||||
using (ManualResetEvent mre = new ManualResetEvent (false))
|
||||
using (ManualResetEvent ready = new ManualResetEvent (false)) {
|
||||
var thread = new Thread (() => {
|
||||
ready.Set ();
|
||||
mre.WaitOne (1000);
|
||||
});
|
||||
|
||||
thread.Start ();
|
||||
ready.WaitOne ();
|
||||
|
||||
Thread.Sleep (10); // wait a bit so we enter mre.WaitOne
|
||||
|
||||
DateTime end = DateTime.Now.AddMilliseconds (500);
|
||||
while (DateTime.Now < end) {
|
||||
thread.Suspend ();
|
||||
thread.Resume ();
|
||||
}
|
||||
|
||||
Assert.IsTrue (thread.Join (1000), "#1");
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WaitAnyWithTimeoutAndSpuriousWake ()
|
||||
{
|
||||
/* This is to test that WaitEvent.WaitAny is not going to wait largely
|
||||
* more than its timeout. In this test, it shouldn't wait more than
|
||||
* 1500 milliseconds, with its timeout being 1000ms */
|
||||
|
||||
using (ManualResetEvent mre1 = new ManualResetEvent (false))
|
||||
using (ManualResetEvent mre2 = new ManualResetEvent (false))
|
||||
using (ManualResetEvent ready = new ManualResetEvent (false)) {
|
||||
var thread = new Thread (() => {
|
||||
ready.Set ();
|
||||
WaitHandle.WaitAny (new [] { mre1, mre2 }, 1000);
|
||||
});
|
||||
|
||||
thread.Start ();
|
||||
ready.WaitOne ();
|
||||
|
||||
Thread.Sleep (10); // wait a bit so we enter WaitHandle.WaitAny ({mre1, mre2})
|
||||
|
||||
DateTime end = DateTime.Now.AddMilliseconds (500);
|
||||
while (DateTime.Now < end) {
|
||||
thread.Suspend ();
|
||||
thread.Resume ();
|
||||
}
|
||||
|
||||
Assert.IsTrue (thread.Join (1000), "#1");
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WaitAllWithTimeoutAndSpuriousWake ()
|
||||
{
|
||||
/* This is to test that WaitEvent.WaitAll is not going to wait largely
|
||||
* more than its timeout. In this test, it shouldn't wait more than
|
||||
* 1500 milliseconds, with its timeout being 1000ms */
|
||||
|
||||
using (ManualResetEvent mre1 = new ManualResetEvent (false))
|
||||
using (ManualResetEvent mre2 = new ManualResetEvent (false))
|
||||
using (ManualResetEvent ready = new ManualResetEvent (false)) {
|
||||
var thread = new Thread (() => {
|
||||
ready.Set ();
|
||||
WaitHandle.WaitAll (new [] { mre1, mre2 }, 1000);
|
||||
});
|
||||
|
||||
thread.Start ();
|
||||
ready.WaitOne ();
|
||||
|
||||
Thread.Sleep (10); // wait a bit so we enter WaitHandle.WaitAll ({mre1, mre2})
|
||||
|
||||
DateTime end = DateTime.Now.AddMilliseconds (500);
|
||||
while (DateTime.Now < end) {
|
||||
thread.Suspend ();
|
||||
thread.Resume ();
|
||||
}
|
||||
|
||||
Assert.IsTrue (thread.Join (1000), "#1");
|
||||
}
|
||||
}
|
||||
#endif // MONO_FEATURE_THREAD_SUSPEND_RESUME
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1 +1 @@
|
||||
8f5979d27ed2a52fccb1bc587845fb652a05412c
|
||||
362e108c1374bb987f401f2b4d420b050a031231
|
@ -1 +1 @@
|
||||
842cbee0abeca01699b2af178bde507d4d52b277
|
||||
c64b6fef099910e33f49c5132d6568abfbdf62b3
|
@ -1 +1 @@
|
||||
0a1c99b3277a99080d40a64a7da507e2d61460f0
|
||||
24979c09819a656e19fc58fcf19e9b5a16584075
|
@ -1 +1 @@
|
||||
bd0d7c1a8100803b2ef6da3853c7045cc83c4824
|
||||
bd4b36083e46dd607da7e0ec9922f22c312cf270
|
@ -1 +1 @@
|
||||
107c45faacbffc3876e310e13f5528c765944ba4
|
||||
2caa7c6153cffdaf2f9392820e8c2468e5b287af
|
@ -64,7 +64,7 @@ namespace MonoTests.Helpers
|
||||
tcpListener = new TcpListener (ep);
|
||||
tcpListener.Start ();
|
||||
|
||||
listenTask = Task.Run (Listen);
|
||||
listenTask = Task.Run ((Action) Listen);
|
||||
}
|
||||
|
||||
public void Dispose ()
|
||||
|
11
mcs/errors/cs8082-2.cs
Normal file
11
mcs/errors/cs8082-2.cs
Normal file
@ -0,0 +1,11 @@
|
||||
// CS8082: An argument to nameof operator cannot include sub-expression
|
||||
// Line: 9
|
||||
|
||||
class C
|
||||
{
|
||||
void Foo ()
|
||||
{
|
||||
dynamic o = null;
|
||||
var s = nameof (o.ToString ().Equals);
|
||||
}
|
||||
}
|
10
mcs/errors/cs8082-3.cs
Normal file
10
mcs/errors/cs8082-3.cs
Normal file
@ -0,0 +1,10 @@
|
||||
// CS8082: An argument to nameof operator cannot include sub-expression
|
||||
// Line: 8
|
||||
|
||||
class C
|
||||
{
|
||||
void Foo ()
|
||||
{
|
||||
var v = nameof (this?.Equals);
|
||||
}
|
||||
}
|
10
mcs/errors/cs8082-4.cs
Normal file
10
mcs/errors/cs8082-4.cs
Normal file
@ -0,0 +1,10 @@
|
||||
// CS8082: An argument to nameof operator cannot include sub-expression
|
||||
// Line: 8
|
||||
|
||||
class C
|
||||
{
|
||||
void Foo ()
|
||||
{
|
||||
var s = nameof (1.ToString);
|
||||
}
|
||||
}
|
@ -90,6 +90,11 @@ namespace Mono.CSharp
|
||||
if (!stmt.Resolve (bc))
|
||||
return null;
|
||||
|
||||
if (rc.HasSet (ResolveContext.Options.FinallyScope) && rc.CurrentAnonymousMethod != null) {
|
||||
var ats = (AsyncTaskStorey)rc.CurrentAnonymousMethod.Storey;
|
||||
ats.HasAwaitInsideFinally = true;
|
||||
}
|
||||
|
||||
type = stmt.ResultType;
|
||||
eclass = ExprClass.Variable;
|
||||
return this;
|
||||
@ -344,7 +349,11 @@ namespace Mono.CSharp
|
||||
|
||||
var errors_printer = new SessionReportPrinter ();
|
||||
var old = bc.Report.SetPrinter (errors_printer);
|
||||
ama = new Invocation (ama, args).Resolve (bc);
|
||||
|
||||
//
|
||||
// The expression await t is classified the same way as the expression (t).GetAwaiter().GetResult().
|
||||
//
|
||||
ama = new Invocation (new ParenthesizedExpression (ama, Location.Null), args).Resolve (bc);
|
||||
bc.Report.SetPrinter (old);
|
||||
|
||||
if (errors_printer.ErrorsCount > 0 || !MemberAccess.IsValidDotExpression (ama.Type)) {
|
||||
@ -536,6 +545,8 @@ namespace Mono.CSharp
|
||||
|
||||
#region Properties
|
||||
|
||||
public bool HasAwaitInsideFinally { get; set; }
|
||||
|
||||
public Expression HoistedReturnValue { get; set; }
|
||||
|
||||
public TypeSpec ReturnType {
|
||||
@ -689,6 +700,18 @@ namespace Mono.CSharp
|
||||
|
||||
builder = AddCompilerGeneratedField ("$builder", new TypeExpression (bt, Location));
|
||||
|
||||
Field rfield;
|
||||
if (has_task_return_type && HasAwaitInsideFinally) {
|
||||
//
|
||||
// Special case async block with return value from finally clause. In such case
|
||||
// we rewrite all return expresison stores to stfld to $return. Instead of treating
|
||||
// returns outside of finally and inside of finally differently.
|
||||
//
|
||||
rfield = AddCompilerGeneratedField ("$return", new TypeExpression (bt.TypeArguments [0], Location));
|
||||
} else {
|
||||
rfield = null;
|
||||
}
|
||||
|
||||
var set_state_machine = new Method (this, new TypeExpression (Compiler.BuiltinTypes.Void, Location),
|
||||
Modifiers.COMPILER_GENERATED | Modifiers.DEBUGGER_HIDDEN | Modifiers.PUBLIC,
|
||||
new MemberName ("SetStateMachine"),
|
||||
@ -726,7 +749,13 @@ namespace Mono.CSharp
|
||||
set_state_machine.Block.AddStatement (new StatementExpression (new Invocation (mg, args)));
|
||||
|
||||
if (has_task_return_type) {
|
||||
HoistedReturnValue = TemporaryVariableReference.Create (bt.TypeArguments [0], StateMachineMethod.Block, Location);
|
||||
if (rfield != null) {
|
||||
HoistedReturnValue = new FieldExpr (rfield, Location) {
|
||||
InstanceExpression = new CompilerGeneratedThis (CurrentType, Location.Null)
|
||||
};
|
||||
} else {
|
||||
HoistedReturnValue = TemporaryVariableReference.Create (bt.TypeArguments [0], StateMachineMethod.Block, Location);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -2179,8 +2179,11 @@ namespace Mono.CSharp {
|
||||
var ma = expr as MemberAccess;
|
||||
if (ma != null) {
|
||||
var lexpr = ma.LeftExpression;
|
||||
Expression res;
|
||||
|
||||
var res = ma.LookupNameExpression (rc, MemberLookupRestrictions.IgnoreAmbiguity);
|
||||
using (rc.Set (ResolveContext.Options.NameOfScope)) {
|
||||
res = ma.LookupNameExpression (rc, MemberLookupRestrictions.IgnoreAmbiguity);
|
||||
}
|
||||
|
||||
if (res == null) {
|
||||
return false;
|
||||
@ -2194,11 +2197,6 @@ namespace Mono.CSharp {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!IsLeftExpressionValid (lexpr)) {
|
||||
rc.Report.Error (8082, lexpr.Location, "An argument to nameof operator cannot include sub-expression");
|
||||
return false;
|
||||
}
|
||||
|
||||
var mg = res as MethodGroupExpr;
|
||||
if (mg != null) {
|
||||
var emg = res as ExtensionMethodGroupExpr;
|
||||
@ -2215,6 +2213,14 @@ namespace Mono.CSharp {
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// LAMESPEC: Why is conditional access not allowed?
|
||||
//
|
||||
if (!IsLeftResolvedExpressionValid (ma.LeftExpression) || ma.HasConditionalAccess ()) {
|
||||
rc.Report.Error (8082, lexpr.Location, "An argument to nameof operator cannot include sub-expression");
|
||||
return false;
|
||||
}
|
||||
|
||||
Value = ma.Name;
|
||||
return true;
|
||||
}
|
||||
@ -2223,26 +2229,25 @@ namespace Mono.CSharp {
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool IsLeftExpressionValid (Expression expr)
|
||||
static bool IsLeftResolvedExpressionValid (Expression expr)
|
||||
{
|
||||
if (expr is SimpleName)
|
||||
return true;
|
||||
|
||||
if (expr is This)
|
||||
return true;
|
||||
|
||||
if (expr is NamespaceExpression)
|
||||
return true;
|
||||
|
||||
if (expr is TypeExpr)
|
||||
return true;
|
||||
|
||||
var ma = expr as MemberAccess;
|
||||
if (ma != null) {
|
||||
// TODO: Will conditional access be allowed?
|
||||
return IsLeftExpressionValid (ma.LeftExpression);
|
||||
var fe = expr as FieldExpr;
|
||||
if (fe != null) {
|
||||
return fe.InstanceExpression == null || IsLeftResolvedExpressionValid (fe.InstanceExpression);
|
||||
}
|
||||
|
||||
var pe = expr as PropertyExpr;
|
||||
if (pe != null)
|
||||
return pe.InstanceExpression == null || IsLeftResolvedExpressionValid (pe.InstanceExpression);
|
||||
|
||||
var dmb = expr as DynamicMemberBinder;
|
||||
if (dmb != null) {
|
||||
return IsLeftResolvedExpressionValid (dmb.Arguments [0].Expr);
|
||||
}
|
||||
|
||||
if (expr is ConstantExpr || expr is TypeExpr || expr is NamespaceExpression || expr is This)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -191,6 +191,8 @@ namespace Mono.CSharp
|
||||
|
||||
DontSetConditionalAccessReceiver = 1 << 16,
|
||||
|
||||
NameOfScope = 1 << 17,
|
||||
|
||||
///
|
||||
/// Indicates the current context is in probing mode, no errors are reported.
|
||||
///
|
||||
|
@ -4058,6 +4058,9 @@ namespace Mono.CSharp
|
||||
--braces;
|
||||
break;
|
||||
case '\\':
|
||||
if (parsing_string_interpolation_quoted != null && parsing_string_interpolation_quoted.Peek ())
|
||||
break;
|
||||
|
||||
++col;
|
||||
int surrogate;
|
||||
ch = escape (ch, out surrogate);
|
||||
|
@ -1 +1 @@
|
||||
52da19a1b970748d49991d1a2b47a7bbef11a061
|
||||
a581906d3e9b82d7ffd04ab74c4c1f8275e7efa5
|
@ -1 +1 @@
|
||||
c5139d57f673c5d02f003618a9d64ccc09dcc2a1
|
||||
bfba44fbb8c656079254fc346737ea8a4af5fd3e
|
@ -897,6 +897,18 @@ namespace Mono.CSharp.Nullable
|
||||
|
||||
ec.MarkLabel (is_null_label);
|
||||
LiftedNull.Create (type, loc).Emit (ec);
|
||||
} else if (Left.IsNull && UnwrapRight != null) {
|
||||
UnwrapRight.Emit (ec);
|
||||
|
||||
ec.Emit (or ? OpCodes.Brtrue_S : OpCodes.Brfalse_S, load_right);
|
||||
|
||||
LiftedNull.Create (type, loc).Emit (ec);
|
||||
|
||||
ec.Emit (OpCodes.Br_S, end_label);
|
||||
|
||||
ec.MarkLabel (load_right);
|
||||
|
||||
UnwrapRight.Load (ec);
|
||||
} else {
|
||||
Right.Emit (ec);
|
||||
ec.Emit (or ? OpCodes.Brfalse_S : OpCodes.Brtrue_S, load_left);
|
||||
|
@ -1210,6 +1210,16 @@ namespace Mono.CSharp {
|
||||
settings.RuntimeMetadataVersion = value;
|
||||
return ParseResult.Success;
|
||||
|
||||
// csc options that we don't support
|
||||
case "/utf8output":
|
||||
case "/subsystemversion":
|
||||
case "/highentropyva":
|
||||
case "/highentropyva+":
|
||||
case "/highentropyva-":
|
||||
case "/win32manifest":
|
||||
case "/nowin32manifest":
|
||||
return ParseResult.Success;
|
||||
|
||||
default:
|
||||
return ParseResult.UnknownOption;
|
||||
}
|
||||
|
@ -1 +1 @@
|
||||
e5c8bb4316c6b5af4ce075f1b939559bf7efd40f
|
||||
3fbb360debcdacf3146092c1a7adddf7f20f3fde
|
@ -99,6 +99,35 @@ class C
|
||||
if ((null | b4) != true)
|
||||
return 103;
|
||||
|
||||
bool? x_n = null;
|
||||
bool? x_f = false;
|
||||
bool? x_t = true;
|
||||
|
||||
bool? res;
|
||||
res = null & x_n;
|
||||
if (res.HasValue)
|
||||
return 201;
|
||||
|
||||
res = null & x_t;
|
||||
if (res.HasValue)
|
||||
return 202;
|
||||
|
||||
res = null & x_f;
|
||||
if (res.Value != false)
|
||||
return 203;
|
||||
|
||||
res = null | x_n;
|
||||
if (res.HasValue)
|
||||
return 204;
|
||||
|
||||
res = null | x_t;
|
||||
if (res.Value != true)
|
||||
return 205;
|
||||
|
||||
res = null | x_f;
|
||||
if (res.HasValue)
|
||||
return 206;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
30
mcs/tests/test-async-82.cs
Normal file
30
mcs/tests/test-async-82.cs
Normal file
@ -0,0 +1,30 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
class X
|
||||
{
|
||||
public static int Main ()
|
||||
{
|
||||
if (new X ().Test (false).Result != true)
|
||||
return 1;
|
||||
|
||||
if (new X ().Test (true).Result != true)
|
||||
return 2;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public async Task<bool> Test(bool TrueOrFalse)
|
||||
{
|
||||
if (TrueOrFalse)
|
||||
return true;
|
||||
|
||||
try {
|
||||
return true;
|
||||
}
|
||||
finally
|
||||
{
|
||||
await Task.Yield ();
|
||||
}
|
||||
}
|
||||
}
|
34
mcs/tests/test-async-83.cs
Normal file
34
mcs/tests/test-async-83.cs
Normal file
@ -0,0 +1,34 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
class MainClass
|
||||
{
|
||||
public static int Main ()
|
||||
{
|
||||
var t = GetSomeStrings (null);
|
||||
try {
|
||||
var s = t.Result;
|
||||
return 1;
|
||||
} catch (AggregateException e) {
|
||||
if (e.InnerException is NullReferenceException)
|
||||
return 0;
|
||||
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
public static async Task<string> GetSomeStrings (AsyncStringFactory myFactory)
|
||||
{
|
||||
var res = await myFactory?.GetSomeStringAsync ();
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
public class AsyncStringFactory
|
||||
{
|
||||
public async Task<string> GetSomeStringAsync ()
|
||||
{
|
||||
await Task.Yield();
|
||||
return "foo";
|
||||
}
|
||||
}
|
35
mcs/tests/test-async-84.cs
Normal file
35
mcs/tests/test-async-84.cs
Normal file
@ -0,0 +1,35 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
struct S
|
||||
{
|
||||
public int value;
|
||||
public string str;
|
||||
}
|
||||
|
||||
public class Program
|
||||
{
|
||||
async Task<S> Foo ()
|
||||
{
|
||||
return new S {
|
||||
value = 1,
|
||||
str = await DoAsync ()
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
static async Task<string> DoAsync ()
|
||||
{
|
||||
await Task.Yield ();
|
||||
return "asdafs";
|
||||
}
|
||||
|
||||
static int Main ()
|
||||
{
|
||||
var res = new Program ().Foo ().Result;
|
||||
if (res.value != 1)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
16
mcs/tests/test-interpolation-09.cs
Normal file
16
mcs/tests/test-interpolation-09.cs
Normal file
@ -0,0 +1,16 @@
|
||||
using System;
|
||||
|
||||
class EscapedQuotedInterpolatedFormatSpecifier
|
||||
{
|
||||
public static int Main ()
|
||||
{
|
||||
string ss = "ss";
|
||||
var t = $@"\4{ss:\u007B}\5";
|
||||
|
||||
Console.WriteLine (t);
|
||||
if (t != @"\4ss\5")
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
66
mcs/tests/test-nameof-05.cs
Normal file
66
mcs/tests/test-nameof-05.cs
Normal file
@ -0,0 +1,66 @@
|
||||
// Compiler options: -warnaserror
|
||||
|
||||
using System;
|
||||
|
||||
public class Person
|
||||
{
|
||||
public Car MyCar { get; set; }
|
||||
}
|
||||
|
||||
public class Car
|
||||
{
|
||||
public int Year { get; set; }
|
||||
}
|
||||
|
||||
enum EE
|
||||
{
|
||||
K
|
||||
}
|
||||
|
||||
public class MainClass
|
||||
{
|
||||
class Nested
|
||||
{
|
||||
}
|
||||
|
||||
public static Person MyPerson1 { get; } = new Person();
|
||||
public static Person MyPerson2 = new Person();
|
||||
public const Person MyPerson3 = null;
|
||||
public static event Action Act = null;
|
||||
public static dynamic BBB = null;
|
||||
|
||||
public static int Main ()
|
||||
{
|
||||
string name;
|
||||
|
||||
name = nameof (MyPerson1.MyCar.Year);
|
||||
if (name != "Year")
|
||||
return 1;
|
||||
|
||||
name = nameof (MyPerson2.MyCar.Year);
|
||||
if (name != "Year")
|
||||
return 2;
|
||||
|
||||
name = nameof (MyPerson3.MyCar.Year);
|
||||
if (name != "Year")
|
||||
return 3;
|
||||
|
||||
name = nameof (Act.Method.MemberType);
|
||||
if (name != "MemberType")
|
||||
return 4;
|
||||
|
||||
name = nameof (BBB.A.B.C);
|
||||
if (name != "C")
|
||||
return 5;
|
||||
|
||||
name = nameof (EE.K.ToString);
|
||||
if (name != "ToString")
|
||||
return 6;
|
||||
|
||||
name = nameof (int.ToString);
|
||||
if (name != "ToString")
|
||||
return 7;
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
@ -1 +1 @@
|
||||
dcd5f610003bf7b72bb83316c5aeefb95f9e64ce
|
||||
55a55a8ce00b5f19846f2a4e0df099c17d0799cd
|
@ -345,10 +345,12 @@ void mono_register_config_for_assembly (const char* assembly_name, cons
|
||||
|
||||
// The non-parallel part
|
||||
byte [] buffer = new byte [8192];
|
||||
// everything other than a-zA-Z0-9_ needs to be escaped in asm symbols.
|
||||
var symbolEscapeRE = new System.Text.RegularExpressions.Regex ("[^\\w_]");
|
||||
foreach (var url in files) {
|
||||
string fname = LocateFile (new Uri (url).LocalPath);
|
||||
string aname = Path.GetFileName (fname);
|
||||
string encoded = aname.Replace ("-", "_").Replace (".", "_");
|
||||
string encoded = symbolEscapeRE.Replace (aname, "_");
|
||||
|
||||
if (prog == null)
|
||||
prog = aname;
|
||||
@ -550,7 +552,7 @@ void mono_register_config_for_assembly (const char* assembly_name, cons
|
||||
smonolib = "`pkg-config --variable=libdir mono-2`/libmono-2.0.a ";
|
||||
else
|
||||
smonolib = "-Wl,-Bstatic -lmono-2.0 -Wl,-Bdynamic ";
|
||||
cmd = String.Format("{4} -o {2} -Wall `pkg-config --cflags mono-2` {0} {3} " +
|
||||
cmd = String.Format("{4} -o '{2}' -Wall `pkg-config --cflags mono-2` {0} {3} " +
|
||||
"`pkg-config --libs-only-L mono-2` " + smonolib +
|
||||
"`pkg-config --libs-only-l mono-2 | sed -e \"s/\\-lmono-2.0 //\"` {1}",
|
||||
temp_c, temp_o, output, zlib, cc);
|
||||
@ -558,7 +560,7 @@ void mono_register_config_for_assembly (const char* assembly_name, cons
|
||||
else
|
||||
{
|
||||
|
||||
cmd = String.Format("{4} " + debugging + " -o {2} -Wall {0} `pkg-config --cflags --libs mono-2` {3} {1}",
|
||||
cmd = String.Format("{4} " + debugging + " -o '{2}' -Wall {0} `pkg-config --cflags --libs mono-2` {3} {1}",
|
||||
temp_c, temp_o, output, zlib, cc);
|
||||
}
|
||||
Execute (cmd);
|
||||
|
@ -83,6 +83,11 @@ install-web-targets:
|
||||
$(INSTALL_DATA) targets/Microsoft.WebApplication.targets $(DESTDIR)$(VS_TARGETS_DIR)/v10.0/WebApplications
|
||||
$(MKINSTALLDIRS) $(DESTDIR)$(VS_TARGETS_DIR)/v11.0/WebApplications
|
||||
$(INSTALL_DATA) targets/Microsoft.WebApplication.targets $(DESTDIR)$(VS_TARGETS_DIR)/v11.0/WebApplications
|
||||
$(MKINSTALLDIRS) $(DESTDIR)$(VS_TARGETS_DIR)/v12.0/WebApplications
|
||||
$(INSTALL_DATA) targets/Microsoft.WebApplication.targets $(DESTDIR)$(VS_TARGETS_DIR)/v12.0/WebApplications
|
||||
$(MKINSTALLDIRS) $(DESTDIR)$(VS_TARGETS_DIR)/v14.0/WebApplications
|
||||
$(INSTALL_DATA) targets/Microsoft.WebApplication.targets $(DESTDIR)$(VS_TARGETS_DIR)/v14.0/WebApplications
|
||||
|
||||
|
||||
EXTRA_DISTFILES = \
|
||||
data/xbuild.rsp \
|
||||
|
@ -30,7 +30,6 @@
|
||||
<AssemblyName Condition="'$(AssemblyName)' == ''">$(MSBuildProjectName)</AssemblyName>
|
||||
<OutputPath Condition="'$(OutputPath)' != '' and !HasTrailingSlash('$(OutputPath)')">$(OutputPath)\</OutputPath>
|
||||
<OutputPath Condition=" '$(Platform)'=='' and '$(Configuration)'=='' and '$(OutputPath)'=='' ">bin\Debug\</OutputPath>
|
||||
<WarningLevel Condition="'$(WarningLevel)' == ''" >2</WarningLevel>
|
||||
|
||||
<TargetFrameworkIdentifier Condition="'$(TargetFrameworkIdentifier)' == ''">.NETFramework</TargetFrameworkIdentifier>
|
||||
<TargetFrameworkVersion Condition="'$(TargetFrameworkVersion)' == ''">v4.0</TargetFrameworkVersion>
|
||||
|
@ -30,7 +30,6 @@
|
||||
<AssemblyName Condition="'$(AssemblyName)' == ''">$(MSBuildProjectName)</AssemblyName>
|
||||
<OutputPath Condition="'$(OutputPath)' != '' and !HasTrailingSlash('$(OutputPath)')">$(OutputPath)\</OutputPath>
|
||||
<OutputPath Condition=" '$(Platform)'=='' and '$(Configuration)'=='' and '$(OutputPath)'=='' ">bin\Debug\</OutputPath>
|
||||
<WarningLevel Condition="'$(WarningLevel)' == ''" >2</WarningLevel>
|
||||
|
||||
<TargetFrameworkIdentifier Condition="'$(TargetFrameworkIdentifier)' == ''">.NETFramework</TargetFrameworkIdentifier>
|
||||
<TargetFrameworkVersion Condition="'$(TargetFrameworkVersion)' == ''">v4.0</TargetFrameworkVersion>
|
||||
|
@ -18,7 +18,6 @@
|
||||
<AssemblyName Condition="'$(AssemblyName)' == ''">$(MSBuildProjectName)</AssemblyName>
|
||||
<OutputPath Condition="'$(OutputPath)' != '' and !HasTrailingSlash('$(OutputPath)')">$(OutputPath)\</OutputPath>
|
||||
<OutputPath Condition=" '$(Platform)'=='' and '$(Configuration)'=='' and '$(OutputPath)'=='' ">bin\Debug\</OutputPath>
|
||||
<WarningLevel Condition="'$(WarningLevel)' == ''" >2</WarningLevel>
|
||||
<TargetFrameworkVersion Condition="'$(TargetFrameworkVersion)' == ''">v2.0</TargetFrameworkVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
|
@ -18,7 +18,6 @@
|
||||
<AssemblyName Condition="'$(AssemblyName)' == ''">$(MSBuildProjectName)</AssemblyName>
|
||||
<OutputPath Condition="'$(OutputPath)' != '' and !HasTrailingSlash('$(OutputPath)')">$(OutputPath)\</OutputPath>
|
||||
<OutputPath Condition=" '$(Platform)'=='' and '$(Configuration)'=='' and '$(OutputPath)'=='' ">bin\Debug\</OutputPath>
|
||||
<WarningLevel Condition="'$(WarningLevel)' == ''" >2</WarningLevel>
|
||||
<TargetFrameworkVersion Condition="'$(TargetFrameworkVersion)' == ''">v2.0</TargetFrameworkVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
|
@ -30,7 +30,6 @@
|
||||
<AssemblyName Condition="'$(AssemblyName)' == ''">$(MSBuildProjectName)</AssemblyName>
|
||||
<OutputPath Condition="'$(OutputPath)' != '' and !HasTrailingSlash('$(OutputPath)')">$(OutputPath)\</OutputPath>
|
||||
<OutputPath Condition=" '$(Platform)'=='' and '$(Configuration)'=='' and '$(OutputPath)'=='' ">bin\Debug\</OutputPath>
|
||||
<WarningLevel Condition="'$(WarningLevel)' == ''" >2</WarningLevel>
|
||||
|
||||
<TargetFrameworkIdentifier Condition="'$(TargetFrameworkIdentifier)' == ''">.NETFramework</TargetFrameworkIdentifier>
|
||||
<TargetFrameworkVersion Condition="'$(TargetFrameworkVersion)' == ''">v4.0</TargetFrameworkVersion>
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include <mono/io-layer/wapi-private.h>
|
||||
#include <mono/io-layer/io-trace.h>
|
||||
#include <mono/utils/mono-logger-internals.h>
|
||||
#include <mono/utils/mono-time.h>
|
||||
|
||||
static gboolean own_if_signalled(gpointer handle)
|
||||
{
|
||||
@ -88,6 +89,7 @@ guint32 WaitForSingleObjectEx(gpointer handle, guint32 timeout,
|
||||
int thr_ret;
|
||||
gboolean apc_pending = FALSE;
|
||||
gpointer current_thread = wapi_get_current_thread_handle ();
|
||||
gint64 now, end;
|
||||
|
||||
if (current_thread == NULL) {
|
||||
SetLastError (ERROR_INVALID_HANDLE);
|
||||
@ -157,6 +159,9 @@ guint32 WaitForSingleObjectEx(gpointer handle, guint32 timeout,
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (timeout != INFINITE)
|
||||
end = mono_100ns_ticks () + timeout * 1000 * 10;
|
||||
|
||||
do {
|
||||
/* Check before waiting on the condition, just in case
|
||||
*/
|
||||
@ -170,7 +175,17 @@ guint32 WaitForSingleObjectEx(gpointer handle, guint32 timeout,
|
||||
goto done;
|
||||
}
|
||||
|
||||
waited = _wapi_handle_timedwait_signal_handle (handle, timeout, alertable, FALSE, &apc_pending);
|
||||
if (timeout == INFINITE) {
|
||||
waited = _wapi_handle_timedwait_signal_handle (handle, INFINITE, alertable, FALSE, &apc_pending);
|
||||
} else {
|
||||
now = mono_100ns_ticks ();
|
||||
if (end < now) {
|
||||
ret = WAIT_TIMEOUT;
|
||||
goto done;
|
||||
}
|
||||
|
||||
waited = _wapi_handle_timedwait_signal_handle (handle, (end - now) / 10 / 1000, alertable, FALSE, &apc_pending);
|
||||
}
|
||||
|
||||
if(waited==0 && !apc_pending) {
|
||||
/* Condition was signalled, so hopefully
|
||||
@ -253,6 +268,7 @@ guint32 SignalObjectAndWait(gpointer signal_handle, gpointer wait,
|
||||
int thr_ret;
|
||||
gboolean apc_pending = FALSE;
|
||||
gpointer current_thread = wapi_get_current_thread_handle ();
|
||||
gint64 now, end;
|
||||
|
||||
if (current_thread == NULL) {
|
||||
SetLastError (ERROR_INVALID_HANDLE);
|
||||
@ -327,6 +343,9 @@ guint32 SignalObjectAndWait(gpointer signal_handle, gpointer wait,
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (timeout != INFINITE)
|
||||
end = mono_100ns_ticks () + timeout * 1000 * 10;
|
||||
|
||||
do {
|
||||
/* Check before waiting on the condition, just in case
|
||||
*/
|
||||
@ -339,7 +358,17 @@ guint32 SignalObjectAndWait(gpointer signal_handle, gpointer wait,
|
||||
goto done;
|
||||
}
|
||||
|
||||
waited = _wapi_handle_timedwait_signal_handle (wait, timeout, alertable, FALSE, &apc_pending);
|
||||
if (timeout == INFINITE) {
|
||||
waited = _wapi_handle_timedwait_signal_handle (wait, INFINITE, alertable, FALSE, &apc_pending);
|
||||
} else {
|
||||
now = mono_100ns_ticks ();
|
||||
if (end < now) {
|
||||
ret = WAIT_TIMEOUT;
|
||||
goto done;
|
||||
}
|
||||
|
||||
waited = _wapi_handle_timedwait_signal_handle (wait, (end - now) / 10 / 1000, alertable, FALSE, &apc_pending);
|
||||
}
|
||||
|
||||
if (waited==0 && !apc_pending) {
|
||||
/* Condition was signalled, so hopefully
|
||||
@ -445,6 +474,7 @@ guint32 WaitForMultipleObjectsEx(guint32 numobjects, gpointer *handles,
|
||||
gboolean poll;
|
||||
gpointer sorted_handles [MAXIMUM_WAIT_OBJECTS];
|
||||
gboolean apc_pending = FALSE;
|
||||
gint64 now, end;
|
||||
|
||||
if (current_thread == NULL) {
|
||||
SetLastError (ERROR_INVALID_HANDLE);
|
||||
@ -528,6 +558,10 @@ guint32 WaitForMultipleObjectsEx(guint32 numobjects, gpointer *handles,
|
||||
if (timeout == 0) {
|
||||
return WAIT_TIMEOUT;
|
||||
}
|
||||
|
||||
if (timeout != INFINITE)
|
||||
end = mono_100ns_ticks () + timeout * 1000 * 10;
|
||||
|
||||
/* Have to wait for some or all handles to become signalled
|
||||
*/
|
||||
|
||||
@ -571,7 +605,16 @@ guint32 WaitForMultipleObjectsEx(guint32 numobjects, gpointer *handles,
|
||||
|
||||
if (!done) {
|
||||
/* Enter the wait */
|
||||
ret = _wapi_handle_timedwait_signal (timeout, poll, &apc_pending);
|
||||
if (timeout == INFINITE) {
|
||||
ret = _wapi_handle_timedwait_signal (INFINITE, poll, &apc_pending);
|
||||
} else {
|
||||
now = mono_100ns_ticks ();
|
||||
if (end < now) {
|
||||
ret = WAIT_TIMEOUT;
|
||||
} else {
|
||||
ret = _wapi_handle_timedwait_signal ((end - now) / 10 / 1000, poll, &apc_pending);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* No need to wait */
|
||||
ret = 0;
|
||||
|
@ -1046,7 +1046,8 @@ do_mono_image_load (MonoImage *image, MonoImageOpenStatus *status,
|
||||
}
|
||||
}
|
||||
if (!image->loader) {
|
||||
*status = MONO_IMAGE_IMAGE_INVALID;
|
||||
if (status)
|
||||
*status = MONO_IMAGE_IMAGE_INVALID;
|
||||
goto invalid_image;
|
||||
}
|
||||
|
||||
|
@ -601,7 +601,7 @@ jit_info_table_add (MonoDomain *domain, MonoJitInfoTable *volatile *table_ptr, M
|
||||
*table_ptr = new_table;
|
||||
mono_memory_barrier ();
|
||||
domain->num_jit_info_tables++;
|
||||
mono_thread_hazardous_free_or_queue (table, (MonoHazardousFreeFunc)mono_jit_info_table_free, TRUE, FALSE);
|
||||
mono_thread_hazardous_free_or_queue (table, (MonoHazardousFreeFunc)mono_jit_info_table_free, HAZARD_FREE_MAY_LOCK, HAZARD_FREE_SAFE_CTX);
|
||||
table = new_table;
|
||||
|
||||
goto restart;
|
||||
@ -677,7 +677,7 @@ mono_jit_info_free_or_queue (MonoDomain *domain, MonoJitInfo *ji)
|
||||
if (domain->num_jit_info_tables <= 1) {
|
||||
/* Can it actually happen that we only have one table
|
||||
but ji is still hazardous? */
|
||||
mono_thread_hazardous_free_or_queue (ji, g_free, TRUE, FALSE);
|
||||
mono_thread_hazardous_free_or_queue (ji, g_free, HAZARD_FREE_MAY_LOCK, HAZARD_FREE_SAFE_CTX);
|
||||
} else {
|
||||
domain->jit_info_free_queue = g_slist_prepend (domain->jit_info_free_queue, ji);
|
||||
}
|
||||
|
@ -57,11 +57,10 @@ ves_icall_System_Diagnostics_Process_GetPid_internal (void)
|
||||
return mono_process_current_pid ();
|
||||
}
|
||||
|
||||
void ves_icall_System_Diagnostics_Process_Process_free_internal (MonoObject *this_obj,
|
||||
HANDLE process)
|
||||
void ves_icall_System_Diagnostics_Process_Process_free_internal (HANDLE process)
|
||||
{
|
||||
#ifdef THREAD_DEBUG
|
||||
g_message ("%s: Closing process %p, handle %p", __func__, this_obj, process);
|
||||
g_message ("%s: Closing process handle %p", __func__, process);
|
||||
#endif
|
||||
|
||||
#if defined(TARGET_WIN32) || defined(HOST_WIN32)
|
||||
|
@ -60,7 +60,7 @@ G_BEGIN_DECLS
|
||||
HANDLE ves_icall_System_Diagnostics_Process_GetProcess_internal (guint32 pid);
|
||||
MonoArray *ves_icall_System_Diagnostics_Process_GetProcesses_internal (void);
|
||||
guint32 ves_icall_System_Diagnostics_Process_GetPid_internal (void);
|
||||
void ves_icall_System_Diagnostics_Process_Process_free_internal (MonoObject *this_obj, HANDLE process);
|
||||
void ves_icall_System_Diagnostics_Process_Process_free_internal (HANDLE process);
|
||||
MonoArray *ves_icall_System_Diagnostics_Process_GetModules_internal (MonoObject *this_obj, HANDLE process);
|
||||
void ves_icall_System_Diagnostics_FileVersionInfo_GetVersionInfo_internal (MonoObject *this_obj, MonoString *filename);
|
||||
MonoBoolean ves_icall_System_Diagnostics_Process_ShellExecuteEx_internal (MonoProcessStartInfo *proc_start_info, MonoProcInfo *process_handle);
|
||||
|
@ -2338,8 +2338,6 @@ mono_gc_scan_object (void *obj, void *gc_data)
|
||||
void
|
||||
sgen_client_scan_thread_data (void *start_nursery, void *end_nursery, gboolean precise, ScanCopyContext ctx)
|
||||
{
|
||||
SgenThreadInfo *info;
|
||||
|
||||
scan_area_arg_start = start_nursery;
|
||||
scan_area_arg_end = end_nursery;
|
||||
|
||||
@ -2393,7 +2391,7 @@ sgen_client_scan_thread_data (void *start_nursery, void *end_nursery, gboolean p
|
||||
}
|
||||
}
|
||||
}
|
||||
} END_FOREACH_THREAD
|
||||
} FOREACH_THREAD_END
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -112,12 +112,11 @@ sgen_thread_handshake (BOOL suspend)
|
||||
{
|
||||
SgenThreadInfo *cur_thread = mono_thread_info_current ();
|
||||
kern_return_t ret;
|
||||
SgenThreadInfo *info;
|
||||
|
||||
int count = 0;
|
||||
|
||||
cur_thread->client_info.suspend_done = TRUE;
|
||||
FOREACH_THREAD_SAFE (info) {
|
||||
FOREACH_THREAD (info) {
|
||||
if (info == cur_thread || sgen_thread_pool_is_thread_pool_thread (mono_thread_info_get_tid (info)))
|
||||
continue;
|
||||
|
||||
@ -134,7 +133,7 @@ sgen_thread_handshake (BOOL suspend)
|
||||
continue;
|
||||
}
|
||||
count ++;
|
||||
} END_FOREACH_THREAD_SAFE
|
||||
} FOREACH_THREAD_END
|
||||
return count;
|
||||
}
|
||||
|
||||
|
@ -197,14 +197,13 @@ int
|
||||
sgen_thread_handshake (BOOL suspend)
|
||||
{
|
||||
int count, result;
|
||||
SgenThreadInfo *info;
|
||||
int signum = suspend ? suspend_signal_num : restart_signal_num;
|
||||
|
||||
MonoNativeThreadId me = mono_native_thread_id_get ();
|
||||
|
||||
count = 0;
|
||||
mono_thread_info_current ()->client_info.suspend_done = TRUE;
|
||||
FOREACH_THREAD_SAFE (info) {
|
||||
FOREACH_THREAD (info) {
|
||||
if (mono_native_thread_id_equals (mono_thread_info_get_tid (info), me)) {
|
||||
continue;
|
||||
}
|
||||
@ -219,7 +218,7 @@ sgen_thread_handshake (BOOL suspend)
|
||||
} else {
|
||||
info->client_info.skip = 1;
|
||||
}
|
||||
} END_FOREACH_THREAD_SAFE
|
||||
} FOREACH_THREAD_END
|
||||
|
||||
sgen_wait_for_suspend_ack (count);
|
||||
|
||||
|
@ -123,12 +123,11 @@ sgen_wait_for_suspend_ack (int count)
|
||||
int
|
||||
sgen_thread_handshake (BOOL suspend)
|
||||
{
|
||||
SgenThreadInfo *info;
|
||||
SgenThreadInfo *current = mono_thread_info_current ();
|
||||
int count = 0;
|
||||
|
||||
current->client_info.suspend_done = TRUE;
|
||||
FOREACH_THREAD_SAFE (info) {
|
||||
FOREACH_THREAD (info) {
|
||||
if (info == current)
|
||||
continue;
|
||||
info->client_info.suspend_done = FALSE;
|
||||
@ -142,7 +141,7 @@ sgen_thread_handshake (BOOL suspend)
|
||||
continue;
|
||||
}
|
||||
++count;
|
||||
} END_FOREACH_THREAD_SAFE
|
||||
} FOREACH_THREAD_END
|
||||
return count;
|
||||
}
|
||||
|
||||
|
@ -113,7 +113,6 @@ is_ip_in_managed_allocator (MonoDomain *domain, gpointer ip)
|
||||
static int
|
||||
restart_threads_until_none_in_managed_allocator (void)
|
||||
{
|
||||
SgenThreadInfo *info;
|
||||
int num_threads_died = 0;
|
||||
int sleep_duration = -1;
|
||||
|
||||
@ -121,7 +120,7 @@ restart_threads_until_none_in_managed_allocator (void)
|
||||
int restart_count = 0, restarted_count = 0;
|
||||
/* restart all threads that stopped in the
|
||||
allocator */
|
||||
FOREACH_THREAD_SAFE (info) {
|
||||
FOREACH_THREAD (info) {
|
||||
gboolean result;
|
||||
if (info->client_info.skip || info->client_info.gc_disabled || info->client_info.suspend_done)
|
||||
continue;
|
||||
@ -146,7 +145,7 @@ restart_threads_until_none_in_managed_allocator (void)
|
||||
info->client_info.stopped_domain = NULL;
|
||||
info->client_info.suspend_done = TRUE;
|
||||
}
|
||||
} END_FOREACH_THREAD_SAFE
|
||||
} FOREACH_THREAD_END
|
||||
/* if no threads were restarted, we're done */
|
||||
if (restart_count == 0)
|
||||
break;
|
||||
@ -174,7 +173,7 @@ restart_threads_until_none_in_managed_allocator (void)
|
||||
} else {
|
||||
info->client_info.skip = 1;
|
||||
}
|
||||
} END_FOREACH_THREAD
|
||||
} FOREACH_THREAD_END
|
||||
/* some threads might have died */
|
||||
num_threads_died += restart_count - restarted_count;
|
||||
/* wait for the threads to signal their suspension
|
||||
@ -251,7 +250,6 @@ sgen_client_stop_world (int generation)
|
||||
void
|
||||
sgen_client_restart_world (int generation, GGTimingInfo *timing)
|
||||
{
|
||||
SgenThreadInfo *info;
|
||||
TV_DECLARE (end_sw);
|
||||
TV_DECLARE (start_handshake);
|
||||
TV_DECLARE (end_bridge);
|
||||
@ -269,7 +267,7 @@ sgen_client_restart_world (int generation, GGTimingInfo *timing)
|
||||
#else
|
||||
memset (&info->client_info.regs, 0, sizeof (info->client_info.regs));
|
||||
#endif
|
||||
} END_FOREACH_THREAD
|
||||
} FOREACH_THREAD_END
|
||||
|
||||
TV_GETTIME (start_handshake);
|
||||
|
||||
@ -387,13 +385,12 @@ static void
|
||||
sgen_unified_suspend_stop_world (void)
|
||||
{
|
||||
int restart_counter;
|
||||
SgenThreadInfo *info;
|
||||
int sleep_duration = -1;
|
||||
|
||||
mono_threads_begin_global_suspend ();
|
||||
THREADS_STW_DEBUG ("[GC-STW-BEGIN] *** BEGIN SUSPEND *** \n");
|
||||
|
||||
FOREACH_THREAD_SAFE (info) {
|
||||
FOREACH_THREAD (info) {
|
||||
info->client_info.skip = FALSE;
|
||||
info->client_info.suspend_done = FALSE;
|
||||
if (sgen_is_thread_in_current_stw (info)) {
|
||||
@ -402,14 +399,14 @@ sgen_unified_suspend_stop_world (void)
|
||||
} else {
|
||||
THREADS_STW_DEBUG ("[GC-STW-BEGIN-SUSPEND] IGNORE thread %p skip %d\n", mono_thread_info_get_tid (info), info->client_info.skip);
|
||||
}
|
||||
} END_FOREACH_THREAD_SAFE
|
||||
} FOREACH_THREAD_END
|
||||
|
||||
mono_thread_info_current ()->client_info.suspend_done = TRUE;
|
||||
mono_threads_wait_pending_operations ();
|
||||
|
||||
for (;;) {
|
||||
restart_counter = 0;
|
||||
FOREACH_THREAD_SAFE (info) {
|
||||
FOREACH_THREAD (info) {
|
||||
if (info->client_info.suspend_done || !sgen_is_thread_in_current_stw (info)) {
|
||||
THREADS_STW_DEBUG ("[GC-STW-RESTART] IGNORE thread %p not been processed done %d current %d\n", mono_thread_info_get_tid (info), info->client_info.suspend_done, !sgen_is_thread_in_current_stw (info));
|
||||
continue;
|
||||
@ -438,7 +435,7 @@ sgen_unified_suspend_stop_world (void)
|
||||
g_assert (!info->client_info.in_critical_region);
|
||||
info->client_info.suspend_done = TRUE;
|
||||
}
|
||||
} END_FOREACH_THREAD_SAFE
|
||||
} FOREACH_THREAD_END
|
||||
|
||||
if (restart_counter == 0)
|
||||
break;
|
||||
@ -456,19 +453,19 @@ sgen_unified_suspend_stop_world (void)
|
||||
sleep_duration += 10;
|
||||
}
|
||||
|
||||
FOREACH_THREAD_SAFE (info) {
|
||||
FOREACH_THREAD (info) {
|
||||
if (sgen_is_thread_in_current_stw (info) && mono_thread_info_is_running (info)) {
|
||||
gboolean res = mono_thread_info_begin_suspend (info, FALSE);
|
||||
THREADS_STW_DEBUG ("[GC-STW-RESTART] SUSPEND thread %p skip %d\n", mono_thread_info_get_tid (info), res);
|
||||
if (!res)
|
||||
info->client_info.skip = TRUE;
|
||||
}
|
||||
} END_FOREACH_THREAD_SAFE
|
||||
} FOREACH_THREAD_END
|
||||
|
||||
mono_threads_wait_pending_operations ();
|
||||
}
|
||||
|
||||
FOREACH_THREAD_SAFE (info) {
|
||||
FOREACH_THREAD (info) {
|
||||
if (sgen_is_thread_in_current_stw (info)) {
|
||||
THREADS_STW_DEBUG ("[GC-STW-SUSPEND-END] thread %p is suspended\n", mono_thread_info_get_tid (info));
|
||||
g_assert (info->client_info.suspend_done);
|
||||
@ -476,23 +473,21 @@ sgen_unified_suspend_stop_world (void)
|
||||
} else {
|
||||
g_assert (!info->client_info.suspend_done || info == mono_thread_info_current ());
|
||||
}
|
||||
} END_FOREACH_THREAD_SAFE
|
||||
} FOREACH_THREAD_END
|
||||
}
|
||||
|
||||
static void
|
||||
sgen_unified_suspend_restart_world (void)
|
||||
{
|
||||
SgenThreadInfo *info;
|
||||
|
||||
THREADS_STW_DEBUG ("[GC-STW-END] *** BEGIN RESUME ***\n");
|
||||
FOREACH_THREAD_SAFE (info) {
|
||||
FOREACH_THREAD (info) {
|
||||
if (sgen_is_thread_in_current_stw (info)) {
|
||||
g_assert (mono_thread_info_begin_resume (info));
|
||||
THREADS_STW_DEBUG ("[GC-STW-RESUME-WORLD] RESUME thread %p\n", mono_thread_info_get_tid (info));
|
||||
} else {
|
||||
THREADS_STW_DEBUG ("[GC-STW-RESUME-WORLD] IGNORE thread %p\n", mono_thread_info_get_tid (info));
|
||||
}
|
||||
} END_FOREACH_THREAD_SAFE
|
||||
} FOREACH_THREAD_END
|
||||
|
||||
mono_threads_wait_pending_operations ();
|
||||
mono_threads_end_global_suspend ();
|
||||
|
@ -801,7 +801,7 @@ EXTRA_DIST = TestDriver.cs \
|
||||
Makefile.am.in
|
||||
|
||||
version.h: Makefile
|
||||
echo "#define FULL_VERSION \"Stable 4.3.2.467/ba2e5e4\"" > version.h
|
||||
echo "#define FULL_VERSION \"Stable 4.4.0.40/f8474c4\"" > version.h
|
||||
|
||||
# Utility target for patching libtool to speed up linking
|
||||
patch-libtool:
|
||||
|
@ -801,7 +801,7 @@ EXTRA_DIST = TestDriver.cs \
|
||||
Makefile.am.in
|
||||
|
||||
version.h: Makefile
|
||||
echo "#define FULL_VERSION \"Stable 4.3.2.467/ba2e5e4\"" > version.h
|
||||
echo "#define FULL_VERSION \"Stable 4.4.0.40/f8474c4\"" > version.h
|
||||
|
||||
# Utility target for patching libtool to speed up linking
|
||||
patch-libtool:
|
||||
|
@ -1 +1 @@
|
||||
26c259ab73e00ef686162f329e573254e8a1a8be
|
||||
feaddf3ea0bb6cd34b061a30d89031f0d11d66ec
|
@ -1 +1 @@
|
||||
91cb5ce5004d809c09f9c0d8a526f78070c03c8d
|
||||
26979427a0ebbb4e979939dad6a0e766cc2b6917
|
@ -1 +1 @@
|
||||
13f9263e7cb11b6262697f85d44bc8d01a9ccd07
|
||||
26d4d91456e706536c43cb083afe6adde5d651e0
|
@ -262,7 +262,7 @@ mono_arch_get_call_filter (MonoTrampInfo **info, gboolean aot)
|
||||
continue;
|
||||
#endif
|
||||
if (AMD64_IS_CALLEE_SAVED_REG (i) && i != AMD64_RBP)
|
||||
amd64_mov_reg_membase (code, AMD64_RBX, AMD64_ARG_REG1, gregs_offset + (i * 8), 8);
|
||||
amd64_mov_reg_membase (code, i, AMD64_ARG_REG1, gregs_offset + (i * 8), 8);
|
||||
}
|
||||
/* load exc register */
|
||||
amd64_mov_reg_membase (code, AMD64_RAX, AMD64_ARG_REG1, gregs_offset + (AMD64_RAX * 8), 8);
|
||||
|
@ -12,6 +12,13 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <llvm-c/Core.h>
|
||||
#include <llvm-c/ExecutionEngine.h>
|
||||
|
||||
#include "mini-llvm-cpp.h"
|
||||
|
||||
#if !defined(MONO_CROSS_COMPILE) && LLVM_API_VERSION < 100
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <llvm/Support/raw_ostream.h>
|
||||
@ -36,13 +43,6 @@
|
||||
#include <llvm/IR/IRBuilder.h>
|
||||
#include <llvm/IR/Module.h>
|
||||
|
||||
#include <llvm-c/Core.h>
|
||||
#include <llvm-c/ExecutionEngine.h>
|
||||
|
||||
#include "mini-llvm-cpp.h"
|
||||
|
||||
#ifndef MONO_CROSS_COMPILE
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
static void (*unhandled_exception)() = default_mono_llvm_unhandled_exception;
|
||||
|
@ -1 +1 @@
|
||||
915dc58fe04dbc4ab7dd14806c61b46212a195f9
|
||||
c4647d8650c5892dc0c3989cb5d74e993161ffcc
|
@ -326,7 +326,6 @@ per_thread_profiler_hit (void *ctx)
|
||||
|
||||
MONO_SIG_HANDLER_FUNC (static, sigprof_signal_handler)
|
||||
{
|
||||
MonoThreadInfo *info;
|
||||
int old_errno = errno;
|
||||
int hp_save_index;
|
||||
MONO_SIG_HANDLER_GET_CONTEXT;
|
||||
@ -348,7 +347,7 @@ MONO_SIG_HANDLER_FUNC (static, sigprof_signal_handler)
|
||||
|
||||
mono_threads_add_async_job (info, MONO_SERVICE_REQUEST_SAMPLE);
|
||||
mono_threads_pthread_kill (info, profiling_signal_in_use);
|
||||
} END_FOREACH_THREAD_SAFE;
|
||||
} FOREACH_THREAD_SAFE_END
|
||||
}
|
||||
|
||||
mono_thread_info_set_is_async_context (TRUE);
|
||||
|
@ -1 +1 @@
|
||||
#define FULL_VERSION "Stable 4.3.2.467/ba2e5e4"
|
||||
#define FULL_VERSION "Stable 4.4.0.40/f8474c4"
|
||||
|
@ -530,15 +530,13 @@ sgen_init_tlab_info (SgenThreadInfo* info)
|
||||
void
|
||||
sgen_clear_tlabs (void)
|
||||
{
|
||||
SgenThreadInfo *info;
|
||||
|
||||
FOREACH_THREAD (info) {
|
||||
/* A new TLAB will be allocated when the thread does its first allocation */
|
||||
*info->tlab_start_addr = NULL;
|
||||
*info->tlab_next_addr = NULL;
|
||||
*info->tlab_temp_end_addr = NULL;
|
||||
*info->tlab_real_end_addr = NULL;
|
||||
} END_FOREACH_THREAD
|
||||
} FOREACH_THREAD_END
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -505,7 +505,6 @@ find_pinning_ref_from_thread (char *obj, size_t size)
|
||||
{
|
||||
#ifndef SGEN_WITHOUT_MONO
|
||||
int j;
|
||||
SgenThreadInfo *info;
|
||||
char *endobj = obj + size;
|
||||
|
||||
FOREACH_THREAD (info) {
|
||||
@ -527,8 +526,8 @@ find_pinning_ref_from_thread (char *obj, size_t size)
|
||||
|
||||
if (w >= (mword)obj && w < (mword)obj + size)
|
||||
SGEN_LOG (0, "Object %p referenced in saved reg %d of thread %p (id %p)", obj, j, info, (gpointer)mono_thread_info_get_tid (info));
|
||||
} END_FOREACH_THREAD
|
||||
}
|
||||
}
|
||||
} FOREACH_THREAD_END
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -74,11 +74,11 @@ worker (void *arg)
|
||||
break;
|
||||
case STATE_OUT:
|
||||
if (InterlockedCompareExchange (&nodes [i].state, STATE_BUSY, STATE_OUT) == STATE_OUT) {
|
||||
result = mono_lls_find (&lls, hp, i);
|
||||
result = mono_lls_find (&lls, hp, i, HAZARD_FREE_SAFE_CTX);
|
||||
assert (!result);
|
||||
mono_hazard_pointer_clear_all (hp, -1);
|
||||
|
||||
result = mono_lls_insert (&lls, hp, &nodes [i].node);
|
||||
result = mono_lls_insert (&lls, hp, &nodes [i].node, HAZARD_FREE_SAFE_CTX);
|
||||
mono_hazard_pointer_clear_all (hp, -1);
|
||||
|
||||
assert (nodes [i].state == STATE_BUSY);
|
||||
@ -89,12 +89,12 @@ worker (void *arg)
|
||||
break;
|
||||
case STATE_IN:
|
||||
if (InterlockedCompareExchange (&nodes [i].state, STATE_BUSY, STATE_IN) == STATE_IN) {
|
||||
result = mono_lls_find (&lls, hp, i);
|
||||
result = mono_lls_find (&lls, hp, i, HAZARD_FREE_SAFE_CTX);
|
||||
assert (result);
|
||||
assert (mono_hazard_pointer_get_val (hp, 1) == &nodes [i].node);
|
||||
mono_hazard_pointer_clear_all (hp, -1);
|
||||
|
||||
result = mono_lls_remove (&lls, hp, &nodes [i].node);
|
||||
result = mono_lls_remove (&lls, hp, &nodes [i].node, HAZARD_FREE_SAFE_CTX);
|
||||
mono_hazard_pointer_clear_all (hp, -1);
|
||||
|
||||
++thread_data->num_removes;
|
||||
@ -126,7 +126,7 @@ main (int argc, char *argv [])
|
||||
|
||||
mono_threads_init (&thread_callbacks, 0);
|
||||
|
||||
mono_lls_init (&lls, free_node);
|
||||
mono_lls_init (&lls, free_node, HAZARD_FREE_NO_LOCK);
|
||||
|
||||
for (i = 0; i < N; ++i) {
|
||||
nodes [i].node.key = i;
|
||||
|
@ -28,7 +28,7 @@
|
||||
typedef struct {
|
||||
gpointer p;
|
||||
MonoHazardousFreeFunc free_func;
|
||||
gboolean might_lock;
|
||||
HazardFreeLocking locking;
|
||||
} DelayedFreeItem;
|
||||
|
||||
/* The hazard table */
|
||||
@ -286,7 +286,7 @@ mono_hazard_pointer_restore_for_signal_handler (int small_id)
|
||||
}
|
||||
|
||||
static gboolean
|
||||
try_free_delayed_free_item (gboolean lock_free_context)
|
||||
try_free_delayed_free_item (HazardFreeContext context)
|
||||
{
|
||||
DelayedFreeItem item;
|
||||
gboolean popped = mono_lock_free_array_queue_pop (&delayed_free_queue, &item);
|
||||
@ -294,7 +294,8 @@ try_free_delayed_free_item (gboolean lock_free_context)
|
||||
if (!popped)
|
||||
return FALSE;
|
||||
|
||||
if ((lock_free_context && item.might_lock) || (is_pointer_hazardous (item.p))) {
|
||||
if ((context == HAZARD_FREE_ASYNC_CTX && item.locking == HAZARD_FREE_MAY_LOCK) ||
|
||||
(is_pointer_hazardous (item.p))) {
|
||||
mono_lock_free_array_queue_push (&delayed_free_queue, &item);
|
||||
return FALSE;
|
||||
}
|
||||
@ -306,24 +307,20 @@ try_free_delayed_free_item (gboolean lock_free_context)
|
||||
|
||||
void
|
||||
mono_thread_hazardous_free_or_queue (gpointer p, MonoHazardousFreeFunc free_func,
|
||||
gboolean free_func_might_lock, gboolean lock_free_context)
|
||||
HazardFreeLocking locking, HazardFreeContext context)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (lock_free_context)
|
||||
g_assert (!free_func_might_lock);
|
||||
if (free_func_might_lock)
|
||||
g_assert (!lock_free_context);
|
||||
|
||||
/* First try to free a few entries in the delayed free
|
||||
table. */
|
||||
for (i = 0; i < 3; ++i)
|
||||
try_free_delayed_free_item (lock_free_context);
|
||||
try_free_delayed_free_item (context);
|
||||
|
||||
/* Now see if the pointer we're freeing is hazardous. If it
|
||||
isn't, free it. Otherwise put it in the delay list. */
|
||||
if (is_pointer_hazardous (p)) {
|
||||
DelayedFreeItem item = { p, free_func, free_func_might_lock };
|
||||
if ((context == HAZARD_FREE_ASYNC_CTX && locking == HAZARD_FREE_MAY_LOCK) ||
|
||||
is_pointer_hazardous (p)) {
|
||||
DelayedFreeItem item = { p, free_func, locking };
|
||||
|
||||
++hazardous_pointer_count;
|
||||
|
||||
@ -336,7 +333,7 @@ mono_thread_hazardous_free_or_queue (gpointer p, MonoHazardousFreeFunc free_func
|
||||
void
|
||||
mono_thread_hazardous_try_free_all (void)
|
||||
{
|
||||
while (try_free_delayed_free_item (FALSE))
|
||||
while (try_free_delayed_free_item (HAZARD_FREE_SAFE_CTX))
|
||||
;
|
||||
}
|
||||
|
||||
@ -345,7 +342,7 @@ mono_thread_hazardous_try_free_some (void)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < 10; ++i)
|
||||
try_free_delayed_free_item (FALSE);
|
||||
try_free_delayed_free_item (HAZARD_FREE_SAFE_CTX);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -18,8 +18,18 @@ typedef struct {
|
||||
|
||||
typedef void (*MonoHazardousFreeFunc) (gpointer p);
|
||||
|
||||
typedef enum {
|
||||
HAZARD_FREE_MAY_LOCK,
|
||||
HAZARD_FREE_NO_LOCK,
|
||||
} HazardFreeLocking;
|
||||
|
||||
typedef enum {
|
||||
HAZARD_FREE_SAFE_CTX,
|
||||
HAZARD_FREE_ASYNC_CTX,
|
||||
} HazardFreeContext;
|
||||
|
||||
void mono_thread_hazardous_free_or_queue (gpointer p, MonoHazardousFreeFunc free_func,
|
||||
gboolean free_func_might_lock, gboolean lock_free_context);
|
||||
HazardFreeLocking locking, HazardFreeContext context);
|
||||
void mono_thread_hazardous_try_free_all (void);
|
||||
void mono_thread_hazardous_try_free_some (void);
|
||||
MonoThreadHazardPointers* mono_hazard_pointer_get (void);
|
||||
|
@ -250,7 +250,7 @@ desc_retire (Descriptor *desc)
|
||||
g_assert (desc->in_use);
|
||||
desc->in_use = FALSE;
|
||||
free_sb (desc->sb, desc->block_size);
|
||||
mono_thread_hazardous_free_or_queue (desc, desc_enqueue_avail, FALSE, TRUE);
|
||||
mono_thread_hazardous_free_or_queue (desc, desc_enqueue_avail, HAZARD_FREE_NO_LOCK, HAZARD_FREE_ASYNC_CTX);
|
||||
}
|
||||
#else
|
||||
MonoLockFreeQueue available_descs;
|
||||
@ -302,7 +302,7 @@ static void
|
||||
list_put_partial (Descriptor *desc)
|
||||
{
|
||||
g_assert (desc->anchor.data.state != STATE_FULL);
|
||||
mono_thread_hazardous_free_or_queue (desc, desc_put_partial, FALSE, TRUE);
|
||||
mono_thread_hazardous_free_or_queue (desc, desc_put_partial, HAZARD_FREE_NO_LOCK, HAZARD_FREE_ASYNC_CTX);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -321,7 +321,7 @@ list_remove_empty_desc (MonoLockFreeAllocSizeClass *sc)
|
||||
desc_retire (desc);
|
||||
} else {
|
||||
g_assert (desc->heap->sc == sc);
|
||||
mono_thread_hazardous_free_or_queue (desc, desc_put_partial, FALSE, TRUE);
|
||||
mono_thread_hazardous_free_or_queue (desc, desc_put_partial, HAZARD_FREE_NO_LOCK, HAZARD_FREE_ASYNC_CTX);
|
||||
if (++num_non_empty >= 2)
|
||||
return;
|
||||
}
|
||||
|
@ -286,7 +286,7 @@ mono_lock_free_queue_dequeue (MonoLockFreeQueue *q)
|
||||
g_assert (q->has_dummy);
|
||||
q->has_dummy = 0;
|
||||
mono_memory_write_barrier ();
|
||||
mono_thread_hazardous_free_or_queue (head, free_dummy, FALSE, TRUE);
|
||||
mono_thread_hazardous_free_or_queue (head, free_dummy, HAZARD_FREE_NO_LOCK, HAZARD_FREE_ASYNC_CTX);
|
||||
if (try_reenqueue_dummy (q))
|
||||
goto retry;
|
||||
return NULL;
|
||||
|
@ -56,7 +56,7 @@ conc_table_free (gpointer ptr)
|
||||
static void
|
||||
conc_table_lf_free (conc_table *table)
|
||||
{
|
||||
mono_thread_hazardous_free_or_queue (table, conc_table_free, TRUE, FALSE);
|
||||
mono_thread_hazardous_free_or_queue (table, conc_table_free, HAZARD_FREE_MAY_LOCK, HAZARD_FREE_SAFE_CTX);
|
||||
}
|
||||
|
||||
|
||||
|
@ -56,27 +56,28 @@ get_hazardous_pointer_with_mask (gpointer volatile *pp, MonoThreadHazardPointers
|
||||
/*
|
||||
Initialize @list and will use @free_node_func to release memory.
|
||||
If @free_node_func is null the caller is responsible for releasing node memory.
|
||||
@free_node_func must be lock-free. That implies that it cannot use malloc/free.
|
||||
If @free_node_func may lock, @free_node_func_locking must be
|
||||
HAZARD_FREE_MAY_LOCK; otherwise, HAZARD_FREE_NO_LOCK. It is ignored if
|
||||
@free_node_func is null.
|
||||
*/
|
||||
void
|
||||
mono_lls_init (MonoLinkedListSet *list, void (*free_node_func)(void *))
|
||||
mono_lls_init (MonoLinkedListSet *list, void (*free_node_func)(void *), HazardFreeLocking free_node_func_locking)
|
||||
{
|
||||
list->head = NULL;
|
||||
list->free_node_func = free_node_func;
|
||||
list->locking = free_node_func_locking;
|
||||
}
|
||||
|
||||
/*
|
||||
Search @list for element with key @key.
|
||||
@context specifies whether the function is being called from a lock-free (i.e.
|
||||
signal handler or world stopped) context. It is only relevant if a node free
|
||||
function was given.
|
||||
The nodes next, cur and prev are returned in @hp.
|
||||
Returns true if a node with key @key was found.
|
||||
This function cannot be called from a signal nor within interrupt context*.
|
||||
XXX A variant that works within interrupted is possible if needed.
|
||||
|
||||
* interrupt context is when the current thread is reposible for another thread
|
||||
been suspended at an arbritary point. This is a limitation of our SMR implementation.
|
||||
*/
|
||||
gboolean
|
||||
mono_lls_find (MonoLinkedListSet *list, MonoThreadHazardPointers *hp, uintptr_t key)
|
||||
mono_lls_find (MonoLinkedListSet *list, MonoThreadHazardPointers *hp, uintptr_t key, HazardFreeContext context)
|
||||
{
|
||||
MonoLinkedListSetNode *cur, *next;
|
||||
MonoLinkedListSetNode **prev;
|
||||
@ -125,7 +126,7 @@ try_again:
|
||||
mono_memory_write_barrier ();
|
||||
mono_hazard_pointer_clear (hp, 1);
|
||||
if (list->free_node_func)
|
||||
mono_thread_hazardous_free_or_queue (cur, list->free_node_func, FALSE, TRUE);
|
||||
mono_thread_hazardous_free_or_queue (cur, list->free_node_func, list->locking, context);
|
||||
} else
|
||||
goto try_again;
|
||||
}
|
||||
@ -136,13 +137,15 @@ try_again:
|
||||
|
||||
/*
|
||||
Insert @value into @list.
|
||||
@context specifies whether the function is being called from a lock-free (i.e.
|
||||
signal handler or world stopped) context. It is only relevant if a node free
|
||||
function was given.
|
||||
The nodes value, cur and prev are returned in @hp.
|
||||
Return true if @value was inserted by this call. If it returns FALSE, it's the caller
|
||||
resposibility to release memory.
|
||||
This function cannot be called from a signal nor with the world stopped.
|
||||
*/
|
||||
gboolean
|
||||
mono_lls_insert (MonoLinkedListSet *list, MonoThreadHazardPointers *hp, MonoLinkedListSetNode *value)
|
||||
mono_lls_insert (MonoLinkedListSet *list, MonoThreadHazardPointers *hp, MonoLinkedListSetNode *value, HazardFreeContext context)
|
||||
{
|
||||
MonoLinkedListSetNode *cur, **prev;
|
||||
/*We must do a store barrier before inserting
|
||||
@ -150,7 +153,7 @@ mono_lls_insert (MonoLinkedListSet *list, MonoThreadHazardPointers *hp, MonoLink
|
||||
mono_memory_barrier ();
|
||||
|
||||
while (1) {
|
||||
if (mono_lls_find (list, hp, value->key))
|
||||
if (mono_lls_find (list, hp, value->key, context))
|
||||
return FALSE;
|
||||
cur = (MonoLinkedListSetNode *) mono_hazard_pointer_get_val (hp, 1);
|
||||
prev = (MonoLinkedListSetNode **) mono_hazard_pointer_get_val (hp, 2);
|
||||
@ -165,17 +168,19 @@ mono_lls_insert (MonoLinkedListSet *list, MonoThreadHazardPointers *hp, MonoLink
|
||||
}
|
||||
|
||||
/*
|
||||
Search @list for element with key @key.
|
||||
Search @list for element with key @key and remove it.
|
||||
@context specifies whether the function is being called from a lock-free (i.e.
|
||||
signal handler or world stopped) context. It is only relevant if a node free
|
||||
function was given.
|
||||
The nodes next, cur and prev are returned in @hp
|
||||
Returns true if @value was removed by this call.
|
||||
This function cannot be called from a signal nor with the world stopped.
|
||||
*/
|
||||
gboolean
|
||||
mono_lls_remove (MonoLinkedListSet *list, MonoThreadHazardPointers *hp, MonoLinkedListSetNode *value)
|
||||
mono_lls_remove (MonoLinkedListSet *list, MonoThreadHazardPointers *hp, MonoLinkedListSetNode *value, HazardFreeContext context)
|
||||
{
|
||||
MonoLinkedListSetNode *cur, **prev, *next;
|
||||
while (1) {
|
||||
if (!mono_lls_find (list, hp, value->key))
|
||||
if (!mono_lls_find (list, hp, value->key, context))
|
||||
return FALSE;
|
||||
|
||||
next = (MonoLinkedListSetNode *) mono_hazard_pointer_get_val (hp, 0);
|
||||
@ -193,9 +198,9 @@ mono_lls_remove (MonoLinkedListSet *list, MonoThreadHazardPointers *hp, MonoLink
|
||||
mono_memory_write_barrier ();
|
||||
mono_hazard_pointer_clear (hp, 1);
|
||||
if (list->free_node_func)
|
||||
mono_thread_hazardous_free_or_queue (value, list->free_node_func, FALSE, TRUE);
|
||||
mono_thread_hazardous_free_or_queue (value, list->free_node_func, list->locking, context);
|
||||
} else
|
||||
mono_lls_find (list, hp, value->key);
|
||||
mono_lls_find (list, hp, value->key, context);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
@ -24,6 +24,7 @@ struct _MonoLinkedListSetNode {
|
||||
typedef struct {
|
||||
MonoLinkedListSetNode *head;
|
||||
void (*free_node_func)(void *);
|
||||
HazardFreeLocking locking;
|
||||
} MonoLinkedListSet;
|
||||
|
||||
|
||||
@ -45,77 +46,129 @@ You must manually clean the hazard pointer table after using them.
|
||||
*/
|
||||
|
||||
void
|
||||
mono_lls_init (MonoLinkedListSet *list, void (*free_node_func)(void *));
|
||||
mono_lls_init (MonoLinkedListSet *list, void (*free_node_func)(void *), HazardFreeLocking free_node_func_locking);
|
||||
|
||||
gboolean
|
||||
mono_lls_find (MonoLinkedListSet *list, MonoThreadHazardPointers *hp, uintptr_t key);
|
||||
mono_lls_find (MonoLinkedListSet *list, MonoThreadHazardPointers *hp, uintptr_t key, HazardFreeContext context);
|
||||
|
||||
gboolean
|
||||
mono_lls_insert (MonoLinkedListSet *list, MonoThreadHazardPointers *hp, MonoLinkedListSetNode *value);
|
||||
mono_lls_insert (MonoLinkedListSet *list, MonoThreadHazardPointers *hp, MonoLinkedListSetNode *value, HazardFreeContext context);
|
||||
|
||||
gboolean
|
||||
mono_lls_remove (MonoLinkedListSet *list, MonoThreadHazardPointers *hp, MonoLinkedListSetNode *value);
|
||||
mono_lls_remove (MonoLinkedListSet *list, MonoThreadHazardPointers *hp, MonoLinkedListSetNode *value, HazardFreeContext context);
|
||||
|
||||
gpointer
|
||||
get_hazardous_pointer_with_mask (gpointer volatile *pp, MonoThreadHazardPointers *hp, int hazard_index);
|
||||
|
||||
/*
|
||||
Requires the world to be stoped
|
||||
*/
|
||||
#define MONO_LLS_FOREACH(list, element, type) {\
|
||||
MonoLinkedListSetNode *__cur; \
|
||||
for (__cur = (list)->head; __cur; __cur = mono_lls_pointer_unmask (__cur->next)) \
|
||||
if (!mono_lls_pointer_get_mark (__cur->next)) { \
|
||||
(element) = (type)__cur;
|
||||
|
||||
|
||||
#define MONO_LLS_FOREACH_FILTERED(list, element, filter_func, type) {\
|
||||
MonoLinkedListSetNode *__cur; \
|
||||
for (__cur = (list)->head; __cur; __cur = (MonoLinkedListSetNode *)mono_lls_pointer_unmask (__cur->next)) \
|
||||
if (!mono_lls_pointer_get_mark (__cur->next)) { \
|
||||
(element) = (type)__cur; \
|
||||
if (!filter_func (element)) continue;
|
||||
|
||||
#define MONO_LLS_END_FOREACH }}
|
||||
|
||||
static inline MonoLinkedListSetNode*
|
||||
mono_lls_info_step (MonoLinkedListSetNode *val, MonoThreadHazardPointers *hp)
|
||||
static inline gboolean
|
||||
mono_lls_filter_accept_all (gpointer elem)
|
||||
{
|
||||
val = (MonoLinkedListSetNode *) mono_lls_pointer_unmask (val);
|
||||
mono_hazard_pointer_set (hp, 1, val);
|
||||
return val;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
Provides snapshot iteration
|
||||
*/
|
||||
#define MONO_LLS_FOREACH_SAFE(list, element, type) {\
|
||||
MonoThreadHazardPointers *__hp = mono_hazard_pointer_get (); \
|
||||
MonoLinkedListSetNode *__cur, *__next; \
|
||||
for (__cur = (MonoLinkedListSetNode *) mono_lls_pointer_unmask (get_hazardous_pointer ((gpointer volatile*)&(list)->head, __hp, 1)); \
|
||||
__cur; \
|
||||
__cur = (MonoLinkedListSetNode *) mono_lls_info_step (__next, __hp)) { \
|
||||
__next = (MonoLinkedListSetNode *) get_hazardous_pointer_with_mask ((gpointer volatile*)&__cur->next, __hp, 0); \
|
||||
if (!mono_lls_pointer_get_mark (__next)) { \
|
||||
(element) = (type)__cur;
|
||||
* These macros assume that no other threads are actively modifying the list.
|
||||
*/
|
||||
|
||||
#define MONO_LLS_FOREACH_FILTERED_SAFE(list, element, filter_func, type) {\
|
||||
MonoThreadHazardPointers *__hp = mono_hazard_pointer_get (); \
|
||||
MonoLinkedListSetNode *__cur, *__next; \
|
||||
for (__cur = (MonoLinkedListSetNode *) mono_lls_pointer_unmask (get_hazardous_pointer ((gpointer volatile*)&(list)->head, __hp, 1)); \
|
||||
__cur; \
|
||||
__cur = (MonoLinkedListSetNode *) mono_lls_info_step (__next, __hp)) { \
|
||||
__next = (MonoLinkedListSetNode *) get_hazardous_pointer_with_mask ((gpointer volatile*)&__cur->next, __hp, 0); \
|
||||
if (!mono_lls_pointer_get_mark (__next)) { \
|
||||
(element) = (type)__cur; \
|
||||
if (!filter_func (element)) continue;
|
||||
#define MONO_LLS_FOREACH_FILTERED(list, type, elem, filter) \
|
||||
do { \
|
||||
MonoLinkedListSet *list__ = (list); \
|
||||
for (MonoLinkedListSetNode *cur__ = list__->head; cur__; cur__ = (MonoLinkedListSetNode *) mono_lls_pointer_unmask (cur__->next)) { \
|
||||
if (!mono_lls_pointer_get_mark (cur__->next)) { \
|
||||
type *elem = (type *) cur__; \
|
||||
if (filter (elem)) {
|
||||
|
||||
|
||||
#define MONO_LLS_END_FOREACH_SAFE \
|
||||
#define MONO_LLS_FOREACH_END \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
mono_hazard_pointer_clear (__hp, 0); \
|
||||
mono_hazard_pointer_clear (__hp, 1); \
|
||||
}
|
||||
} while (0);
|
||||
|
||||
#define MONO_LLS_FOREACH(list, type, elem) \
|
||||
MONO_LLS_FOREACH_FILTERED ((list), type, elem, mono_lls_filter_accept_all)
|
||||
|
||||
/*
|
||||
* These macros can be used while other threads are potentially modifying the
|
||||
* list, but they only provide a snapshot of the list as a result.
|
||||
*
|
||||
* NOTE: Do NOT break out of the loop through any other means than a break
|
||||
* statement, as other ways of breaking the loop will skip past important
|
||||
* cleanup work.
|
||||
*/
|
||||
|
||||
#define MONO_LLS_FOREACH_FILTERED_SAFE(list, type, elem, filter) \
|
||||
do { \
|
||||
/* NOTE: Keep this macro's code in sync with the mono_lls_find () logic. */ \
|
||||
MonoLinkedListSet *list__ = (list); \
|
||||
MonoThreadHazardPointers *hp__ = mono_hazard_pointer_get (); \
|
||||
gboolean progress__ = FALSE; \
|
||||
uintptr_t hkey__; \
|
||||
gboolean restart__; \
|
||||
do { \
|
||||
restart__ = FALSE; \
|
||||
MonoLinkedListSetNode **prev__ = &list__->head; \
|
||||
mono_hazard_pointer_set (hp__, 2, prev__); \
|
||||
MonoLinkedListSetNode *cur__ = (MonoLinkedListSetNode *) get_hazardous_pointer_with_mask ((gpointer *) prev__, hp__, 1); \
|
||||
while (1) { \
|
||||
if (!cur__) { \
|
||||
break; \
|
||||
} \
|
||||
MonoLinkedListSetNode *next__ = (MonoLinkedListSetNode *) get_hazardous_pointer_with_mask ((gpointer *) &cur__->next, hp__, 0); \
|
||||
uintptr_t ckey__ = cur__->key; \
|
||||
mono_memory_read_barrier (); \
|
||||
if (*prev__ != cur__) { \
|
||||
restart__ = TRUE; \
|
||||
break; \
|
||||
} \
|
||||
if (!mono_lls_pointer_get_mark (next__)) { \
|
||||
if (!progress__ || ckey__ > hkey__) { \
|
||||
progress__ = TRUE; \
|
||||
hkey__ = ckey__; \
|
||||
type *elem = (type *) cur__; \
|
||||
if (filter (elem)) { \
|
||||
gboolean broke__ = TRUE; \
|
||||
gboolean done__ = FALSE; \
|
||||
do { \
|
||||
if (done__) { \
|
||||
broke__ = FALSE; \
|
||||
break; \
|
||||
} \
|
||||
done__ = TRUE;
|
||||
|
||||
#define MONO_LLS_FOREACH_SAFE_END \
|
||||
broke__ = FALSE; \
|
||||
break; \
|
||||
} while (1); \
|
||||
if (broke__) { \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
prev__ = &cur__->next; \
|
||||
mono_hazard_pointer_set (hp__, 2, cur__); \
|
||||
} else { \
|
||||
next__ = (MonoLinkedListSetNode *) mono_lls_pointer_unmask (next__); \
|
||||
if (InterlockedCompareExchangePointer ((volatile gpointer *) prev__, next__, cur__) == cur__) { \
|
||||
mono_memory_write_barrier (); \
|
||||
mono_hazard_pointer_clear (hp__, 1); \
|
||||
if (list__->free_node_func) { \
|
||||
mono_thread_hazardous_free_or_queue (cur__, list__->free_node_func, list__->locking, HAZARD_FREE_ASYNC_CTX); \
|
||||
} \
|
||||
} else { \
|
||||
restart__ = TRUE; \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
cur__ = (MonoLinkedListSetNode *) mono_lls_pointer_unmask (next__); \
|
||||
mono_hazard_pointer_set (hp__, 1, cur__); \
|
||||
} \
|
||||
} while (restart__); \
|
||||
mono_hazard_pointer_clear (hp__, 0); \
|
||||
mono_hazard_pointer_clear (hp__, 1); \
|
||||
mono_hazard_pointer_clear (hp__, 2); \
|
||||
} while (0);
|
||||
|
||||
#define MONO_LLS_FOREACH_SAFE(list, type, elem) \
|
||||
MONO_LLS_FOREACH_FILTERED_SAFE ((list), type, elem, mono_lls_filter_accept_all)
|
||||
|
||||
#endif /* __MONO_SPLIT_ORDERED_LIST_H__ */
|
||||
|
@ -187,7 +187,6 @@ mono_threads_end_global_suspend (void)
|
||||
static void
|
||||
dump_threads (void)
|
||||
{
|
||||
MonoThreadInfo *info;
|
||||
MonoThreadInfo *cur = mono_thread_info_current ();
|
||||
|
||||
MOSTLY_ASYNC_SAFE_PRINTF ("STATE CUE CARD: (? means a positive number, usually 1 or 2, * means any number)\n");
|
||||
@ -210,8 +209,7 @@ dump_threads (void)
|
||||
#else
|
||||
MOSTLY_ASYNC_SAFE_PRINTF ("--thread %p id %p [%p] state %x %s\n", info, (void *) mono_thread_info_get_tid (info), (void*)(size_t)info->native_handle, info->thread_state, info == cur ? "GC INITIATOR" : "" );
|
||||
#endif
|
||||
|
||||
} END_FOREACH_THREAD_SAFE
|
||||
} FOREACH_THREAD_SAFE_END
|
||||
}
|
||||
|
||||
gboolean
|
||||
@ -271,7 +269,7 @@ mono_thread_info_lookup (MonoNativeThreadId id)
|
||||
{
|
||||
MonoThreadHazardPointers *hp = mono_hazard_pointer_get ();
|
||||
|
||||
if (!mono_lls_find (&thread_list, hp, (uintptr_t)id)) {
|
||||
if (!mono_lls_find (&thread_list, hp, (uintptr_t)id, HAZARD_FREE_ASYNC_CTX)) {
|
||||
mono_hazard_pointer_clear_all (hp, -1);
|
||||
return NULL;
|
||||
}
|
||||
@ -285,7 +283,7 @@ mono_thread_info_insert (MonoThreadInfo *info)
|
||||
{
|
||||
MonoThreadHazardPointers *hp = mono_hazard_pointer_get ();
|
||||
|
||||
if (!mono_lls_insert (&thread_list, hp, (MonoLinkedListSetNode*)info)) {
|
||||
if (!mono_lls_insert (&thread_list, hp, (MonoLinkedListSetNode*)info, HAZARD_FREE_SAFE_CTX)) {
|
||||
mono_hazard_pointer_clear_all (hp, -1);
|
||||
return FALSE;
|
||||
}
|
||||
@ -301,7 +299,7 @@ mono_thread_info_remove (MonoThreadInfo *info)
|
||||
gboolean res;
|
||||
|
||||
THREADS_DEBUG ("removing info %p\n", info);
|
||||
res = mono_lls_remove (&thread_list, hp, (MonoLinkedListSetNode*)info);
|
||||
res = mono_lls_remove (&thread_list, hp, (MonoLinkedListSetNode*)info, HAZARD_FREE_SAFE_CTX);
|
||||
mono_hazard_pointer_clear_all (hp, -1);
|
||||
return res;
|
||||
}
|
||||
@ -426,7 +424,7 @@ unregister_thread (void *arg)
|
||||
g_byte_array_free (info->stackdata, /*free_segment=*/TRUE);
|
||||
|
||||
/*now it's safe to free the thread info.*/
|
||||
mono_thread_hazardous_free_or_queue (info, free_thread_info, TRUE, FALSE);
|
||||
mono_thread_hazardous_free_or_queue (info, free_thread_info, HAZARD_FREE_MAY_LOCK, HAZARD_FREE_SAFE_CTX);
|
||||
mono_thread_small_id_free (small_id);
|
||||
}
|
||||
|
||||
@ -637,7 +635,7 @@ mono_threads_init (MonoThreadInfoCallbacks *callbacks, size_t info_size)
|
||||
mono_coop_sem_init (&global_suspend_semaphore, 1);
|
||||
mono_os_sem_init (&suspend_semaphore, 0);
|
||||
|
||||
mono_lls_init (&thread_list, NULL);
|
||||
mono_lls_init (&thread_list, NULL, HAZARD_FREE_NO_LOCK);
|
||||
mono_thread_smr_init ();
|
||||
mono_threads_init_platform ();
|
||||
mono_threads_init_coop ();
|
||||
@ -1124,35 +1122,35 @@ sleep_interrupt (gpointer data)
|
||||
static inline guint32
|
||||
sleep_interruptable (guint32 ms, gboolean *alerted)
|
||||
{
|
||||
guint32 start, now, end;
|
||||
gint64 now, end;
|
||||
|
||||
g_assert (INFINITE == G_MAXUINT32);
|
||||
|
||||
g_assert (alerted);
|
||||
*alerted = FALSE;
|
||||
|
||||
start = mono_msec_ticks ();
|
||||
|
||||
if (start < G_MAXUINT32 - ms) {
|
||||
end = start + ms;
|
||||
} else {
|
||||
/* start + ms would overflow guint32 */
|
||||
end = G_MAXUINT32;
|
||||
}
|
||||
if (ms != INFINITE)
|
||||
end = mono_100ns_ticks () + (ms * 1000 * 10);
|
||||
|
||||
mono_lazy_initialize (&sleep_init, sleep_initialize);
|
||||
|
||||
mono_coop_mutex_lock (&sleep_mutex);
|
||||
|
||||
for (now = mono_msec_ticks (); ms == INFINITE || now - start < ms; now = mono_msec_ticks ()) {
|
||||
for (;;) {
|
||||
if (ms != INFINITE) {
|
||||
now = mono_100ns_ticks ();
|
||||
if (now > end)
|
||||
break;
|
||||
}
|
||||
|
||||
mono_thread_info_install_interrupt (sleep_interrupt, NULL, alerted);
|
||||
if (*alerted) {
|
||||
mono_coop_mutex_unlock (&sleep_mutex);
|
||||
return WAIT_IO_COMPLETION;
|
||||
}
|
||||
|
||||
if (ms < INFINITE)
|
||||
mono_coop_cond_timedwait (&sleep_cond, &sleep_mutex, end - now);
|
||||
if (ms != INFINITE)
|
||||
mono_coop_cond_timedwait (&sleep_cond, &sleep_mutex, (end - now) / 10 / 1000);
|
||||
else
|
||||
mono_coop_cond_wait (&sleep_cond, &sleep_mutex);
|
||||
|
||||
|
@ -297,14 +297,20 @@ mono_threads_filter_tools_threads (THREAD_INFO_TYPE *info)
|
||||
/*
|
||||
Requires the world to be stoped
|
||||
*/
|
||||
#define FOREACH_THREAD(thread) MONO_LLS_FOREACH_FILTERED (mono_thread_info_list_head (), thread, mono_threads_filter_tools_threads, THREAD_INFO_TYPE*)
|
||||
#define END_FOREACH_THREAD MONO_LLS_END_FOREACH
|
||||
#define FOREACH_THREAD(thread) \
|
||||
MONO_LLS_FOREACH_FILTERED (mono_thread_info_list_head (), THREAD_INFO_TYPE, thread, mono_threads_filter_tools_threads)
|
||||
|
||||
#define FOREACH_THREAD_END \
|
||||
MONO_LLS_FOREACH_END
|
||||
|
||||
/*
|
||||
Snapshot iteration.
|
||||
*/
|
||||
#define FOREACH_THREAD_SAFE(thread) MONO_LLS_FOREACH_FILTERED_SAFE (mono_thread_info_list_head (), thread, mono_threads_filter_tools_threads, THREAD_INFO_TYPE*)
|
||||
#define END_FOREACH_THREAD_SAFE MONO_LLS_END_FOREACH_SAFE
|
||||
#define FOREACH_THREAD_SAFE(thread) \
|
||||
MONO_LLS_FOREACH_FILTERED_SAFE (mono_thread_info_list_head (), THREAD_INFO_TYPE, thread, mono_threads_filter_tools_threads)
|
||||
|
||||
#define FOREACH_THREAD_SAFE_END \
|
||||
MONO_LLS_FOREACH_SAFE_END
|
||||
|
||||
static inline MonoNativeThreadId
|
||||
mono_thread_info_get_tid (THREAD_INFO_TYPE *info)
|
||||
|
@ -4,7 +4,7 @@ if exist config.h if not exist cygconfig.h copy config.h cygconfig.h
|
||||
if exist eglib\config.h if not exist eglib\cygconfig.h copy eglib\config.h eglib\cygconfig.h
|
||||
copy winconfig.h config.h
|
||||
copy eglib\winconfig.h eglib\config.h
|
||||
powershell -Command "(Get-Content config.h) -replace '#MONO_VERSION#', (Select-String -path configure.ac -pattern 'AC_INIT\(mono, \[(.*)\]').Matches[0].Groups[1].Value | Set-Content config.h"
|
||||
%windir%\system32\WindowsPowerShell\v1.0\powershell.exe -Command "(Get-Content config.h) -replace '#MONO_VERSION#', (Select-String -path configure.ac -pattern 'AC_INIT\(mono, \[(.*)\]').Matches[0].Groups[1].Value | Set-Content config.h"
|
||||
goto end
|
||||
:error
|
||||
echo fatal error: the VSDepenancies directory was not found in the "mono" directory
|
||||
|
BIN
po/mcs/de.gmo
BIN
po/mcs/de.gmo
Binary file not shown.
@ -1 +1 @@
|
||||
56caa8e71219b6c821001eea2e6bf991bfeb90ef
|
||||
dcc0bb17a9a21c5af4bb5f5ae2d9ee003e4b0be6
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user