Merge pull request #3536 from henricm/fix-machinename-ignorecase
authorNiklas Therning <niklas@therning.org>
Wed, 14 Sep 2016 12:57:03 +0000 (14:57 +0200)
committerGitHub <noreply@github.com>
Wed, 14 Sep 2016 12:57:03 +0000 (14:57 +0200)
Ignoring case for MachineName in EventLogTest

147 files changed:
acceptance-tests/Makefile.am
acceptance-tests/SUBMODULES.json
acceptance-tests/profiler-stress.mk [new file with mode: 0644]
acceptance-tests/profiler-stress/runner.cs [new file with mode: 0644]
acceptance-tests/profiler-stress/runner.exe.sources [new file with mode: 0644]
acceptance-tests/versions.mk
configure.ac
man/mprof-report.1
mcs/class/Mono.Debugger.Soft/Mono.Debugger.Soft.dll.sources
mcs/class/Mono.Debugger.Soft/Mono.Debugger.Soft/Connection.cs
mcs/class/Mono.Debugger.Soft/Mono.Debugger.Soft/LocalScope.cs [new file with mode: 0644]
mcs/class/Mono.Debugger.Soft/Mono.Debugger.Soft/MethodMirror.cs
mcs/class/Mono.Debugger.Soft/Test/dtest.cs
mcs/class/System/System.Net.Sockets/Socket.cs
mcs/class/System/System.Net/HttpListenerResponse.cs
mcs/class/System/System.Net/ServicePointManager.cs
mcs/class/System/System.Net/WebConnection.cs
mcs/class/System/Test/System.Net.Sockets/SocketTest.cs
mcs/class/System/Test/System.Net/HttpListenerTest.cs
mcs/class/corlib/System.Threading/Thread.cs
mcs/class/corlib/System/Environment.cs
mcs/class/corlib/Test/System.Threading/ThreadTest.cs
mcs/class/referencesource/System/net/System/Net/WebHeaderCollection.cs
mono/io-layer/Makefile.am
mono/io-layer/event-private.h [deleted file]
mono/io-layer/events.c [deleted file]
mono/io-layer/events.h [deleted file]
mono/io-layer/io.c
mono/io-layer/mutex-private.h [deleted file]
mono/io-layer/mutexes.c [deleted file]
mono/io-layer/mutexes.h [deleted file]
mono/io-layer/processes.c
mono/io-layer/processes.h
mono/io-layer/semaphore-private.h [deleted file]
mono/io-layer/semaphores.c [deleted file]
mono/io-layer/semaphores.h [deleted file]
mono/io-layer/shared.c [deleted file]
mono/io-layer/shared.h [deleted file]
mono/io-layer/wapi-private.h
mono/io-layer/wapi-remap.h
mono/io-layer/wapi.c
mono/io-layer/wapi.h
mono/io-layer/wapi_glob.c
mono/metadata/Makefile.am
mono/metadata/appdomain.c
mono/metadata/assembly.c
mono/metadata/attach.c
mono/metadata/class-internals.h
mono/metadata/domain-internals.h
mono/metadata/domain.c
mono/metadata/exception.c
mono/metadata/handle.h
mono/metadata/icall.c
mono/metadata/loader.c
mono/metadata/locales.c
mono/metadata/marshal.c
mono/metadata/mempool.c
mono/metadata/monitor.c
mono/metadata/mono-route.c
mono/metadata/null-gc.c
mono/metadata/object-internals.h
mono/metadata/object-offsets.h
mono/metadata/object.c
mono/metadata/sgen-mono.c
mono/metadata/socket-io.c
mono/metadata/sre.c
mono/metadata/threadpool-ms.c
mono/metadata/threads-types.h
mono/metadata/threads.c
mono/metadata/w32event-unix.c [new file with mode: 0644]
mono/metadata/w32event-win32.c [new file with mode: 0644]
mono/metadata/w32event.h [new file with mode: 0644]
mono/metadata/w32handle-namespace.c [new file with mode: 0644]
mono/metadata/w32handle-namespace.h [new file with mode: 0644]
mono/metadata/w32mutex-unix.c [new file with mode: 0644]
mono/metadata/w32mutex-utils.h [new file with mode: 0644]
mono/metadata/w32mutex-win32.c [new file with mode: 0644]
mono/metadata/w32mutex.h [new file with mode: 0644]
mono/metadata/w32semaphore-unix.c [new file with mode: 0644]
mono/metadata/w32semaphore-win32.c [new file with mode: 0644]
mono/metadata/w32semaphore.h [new file with mode: 0644]
mono/mini/aot-compiler.c
mono/mini/aot-runtime.c
mono/mini/debugger-agent.c
mono/mini/driver.c
mono/mini/jit-icalls.c
mono/mini/method-to-ir.c
mono/mini/mini-amd64.c
mono/mini/mini-amd64.h
mono/mini/mini-arm.c
mono/mini/mini-arm.h
mono/mini/mini-arm64.c
mono/mini/mini-arm64.h
mono/mini/mini-exceptions.c
mono/mini/mini-ia64.c
mono/mini/mini-ia64.h
mono/mini/mini-llvm.c
mono/mini/mini-mips.c
mono/mini/mini-mips.h
mono/mini/mini-ppc.c
mono/mini/mini-ppc.h
mono/mini/mini-runtime.c
mono/mini/mini-s390x.c
mono/mini/mini-sparc.c
mono/mini/mini-trampolines.c
mono/mini/mini-x86.c
mono/mini/mini-x86.h
mono/mini/mini.c
mono/mini/mini.h
mono/profiler/decode.c
mono/profiler/mono-profiler-vtune.c
mono/profiler/proflog.c
mono/profiler/utils.c
mono/sgen/sgen-cardtable.c
mono/sgen/sgen-debug.c
mono/sgen/sgen-gc.c
mono/sgen/sgen-gc.h
mono/sgen/sgen-internal.c
mono/sgen/sgen-los.c
mono/sgen/sgen-marksweep.c
mono/sgen/sgen-memory-governor.c
mono/sgen/sgen-memory-governor.h
mono/sgen/sgen-protocol.c
mono/utils/checked-build.c
mono/utils/hazard-pointer.c
mono/utils/lock-free-alloc.c
mono/utils/lock-free-alloc.h
mono/utils/lock-free-array-queue.c
mono/utils/lock-free-array-queue.h
mono/utils/mono-codeman.c
mono/utils/mono-counters.c
mono/utils/mono-dl.c
mono/utils/mono-log-common.c
mono/utils/mono-log-posix.c
mono/utils/mono-log-windows.c
mono/utils/mono-mmap.c
mono/utils/mono-mmap.h
mono/utils/mono-proclib.c
mono/utils/mono-threads-posix.c
mono/utils/mono-threads-windows.c
mono/utils/mono-threads.c
mono/utils/mono-threads.h
mono/utils/mono-uri.c
msvc/libmonoruntime.vcxproj
msvc/libmonoruntime.vcxproj.filters
scripts/ci/run-jenkins.sh
scripts/ci/run-test-profiler-stress-tests.sh [new file with mode: 0755]

index 522cb36c9ea47999dfd6dbe7474f11567a1aa1b8..c03adcc0c45f20f7be507986a6ddd4437ccfdb9b 100644 (file)
@@ -1,4 +1,5 @@
 ACCEPTANCE_TESTS_PATH=external
+BENCHMARKER_PATH=$(ACCEPTANCE_TESTS_PATH)/benchmarker
 ROSLYN_PATH=$(ACCEPTANCE_TESTS_PATH)/roslyn
 CORECLR_PATH=$(ACCEPTANCE_TESTS_PATH)/coreclr
 MSTESTSUITE_PATH=$(ACCEPTANCE_TESTS_PATH)/ms-test-suite
@@ -14,10 +15,11 @@ MCS = $(RUNTIME) $(mcs_topdir)/class/lib/build/mcs.exe
 ILASM = $(RUNTIME) $(CLASS)/ilasm.exe
 
 include versions.mk
+include profiler-stress.mk
 include roslyn.mk
 include coreclr.mk
 include ms-test-suite.mk
 
-check-full: check-roslyn check-coreclr check-ms-test-suite
+check-full: check-profiler-stress check-roslyn check-coreclr check-ms-test-suite
 
 clean-local: clean-local-coreclr
index 8f4b13eb0c50030be75dc7803a15cf4cf7202389..01faee39c981b1215ef68e84e38aa97446d09c14 100644 (file)
     "remote-branch": "origin/master", 
     "branch": "master", 
     "directory": "ms-test-suite"
+  }, 
+  {
+    "name": "benchmarker", 
+    "url": "git://github.com/xamarin/benchmarker.git", 
+    "rev": "97f618cd585af549dd861b7c142656c496f6a89b", 
+    "remote-branch": "origin/master", 
+    "branch": "master", 
+    "directory": "benchmarker"
   }
 ]
diff --git a/acceptance-tests/profiler-stress.mk b/acceptance-tests/profiler-stress.mk
new file mode 100644 (file)
index 0000000..9188b17
--- /dev/null
@@ -0,0 +1,12 @@
+SYS_REFS = \
+       System.dll \
+       System.Core.dll \
+       System.Data.dll \
+       System.Runtime.Serialization.dll \
+       System.Xml.dll \
+       System.Xml.Linq.dll
+
+check-profiler-stress:
+       @$(MAKE) validate-benchmarker RESET_VERSIONS=1
+       cd profiler-stress && $(MCS) -target:exe $(addprefix -r:, $(SYS_REFS)) -out:runner.exe @runner.exe.sources
+       cd profiler-stress && $(RUNTIME) runner.exe
diff --git a/acceptance-tests/profiler-stress/runner.cs b/acceptance-tests/profiler-stress/runner.cs
new file mode 100644 (file)
index 0000000..b2638c1
--- /dev/null
@@ -0,0 +1,108 @@
+using System;
+using System.Diagnostics;
+using System.IO;
+using System.Linq;
+using Newtonsoft.Json;
+
+// Shut up CLS compliance warnings from Json.NET.
+[assembly: CLSCompliant (true)]
+
+namespace Mono.Profiling.Tests.Stress {
+
+       // https://github.com/xamarin/benchmarker/blob/master/tools/libdbmodel/Benchmark.cs
+       class Benchmark {
+               public string Name { get; set; }
+               public string TestDirectory { get; set; }
+               public bool OnlyExplicit { get; set; }
+               public string[] CommandLine { get; set; }
+               public string[] ClientCommandLine { get; set; }
+               public string[] AOTAssemblies { get; set; }
+
+               public static Benchmark Load (string file)
+               {
+                       return JsonConvert.DeserializeObject<Benchmark> (File.ReadAllText (file));
+               }
+       }
+
+       static class Program {
+
+               static int Main ()
+               {
+                       var depDir = Path.Combine ("..", "external", "benchmarker");
+                       var benchDir = Path.Combine (depDir, "benchmarks");
+                       var testDir = Path.Combine (depDir, "tests");
+
+                       var benchmarks = Directory.EnumerateFiles (benchDir, "*.benchmark")
+                                        .Select (Benchmark.Load)
+                                        .Where (b => !b.OnlyExplicit && b.ClientCommandLine == null)
+                                        .OrderBy (b => b.Name)
+                                        .ToArray ();
+
+                       var monoPath = Path.GetFullPath (Path.Combine ("..", "..", "runtime", "mono-wrapper"));
+                       var classDir = Path.GetFullPath (Path.Combine ("..", "..", "mcs", "class", "lib", "net_4_x"));
+
+                       var rand = new Random ();
+                       var cpus = Environment.ProcessorCount;
+
+                       var successes = 0;
+                       var failures = 0;
+
+                       var sw = Stopwatch.StartNew ();
+
+                       for (var i = 0; i < benchmarks.Length; i++) {
+                               var bench = benchmarks [i];
+
+                               var sampleFreq = rand.Next (0, 1001);
+                               var sampleMode = rand.Next (0, 2) == 1 ? "real" : "process";
+                               var maxSamples = rand.Next (0, cpus * 2000 + 1);
+                               var heapShotFreq = rand.Next (0, 11);
+                               var maxFrames = rand.Next (0, 33);
+                               var allocMode = rand.Next (0, 2) == 1 ? "alloc" : "noalloc";
+
+                               var profOptions = $"sample=cycles/{sampleFreq},sampling-{sampleMode},maxsamples={maxSamples},heapshot={heapShotFreq}gc,maxframes={maxFrames},{allocMode},output=/dev/null";
+
+                               var info = new ProcessStartInfo {
+                                       UseShellExecute = false,
+                                       WorkingDirectory = Path.Combine (testDir, bench.TestDirectory),
+                                       FileName = monoPath,
+                                       Arguments = $"--debug --profile=log:{profOptions} " + string.Join (" ", bench.CommandLine),
+                               };
+
+                               info.EnvironmentVariables.Clear ();
+                               info.EnvironmentVariables.Add ("MONO_PATH", classDir);
+
+                               var progress = $"({i + 1}/{benchmarks.Length})";
+
+                               Console.ForegroundColor = ConsoleColor.Blue;
+                               Console.WriteLine ($"[{sw.Elapsed.ToString ("G")}] {progress} Running {bench.Name} with profiler options: {profOptions}");
+                               Console.ResetColor ();
+
+                               var sw2 = Stopwatch.StartNew ();
+
+                               using (var proc = Process.Start (info)) {
+                                       proc.WaitForExit ();
+                                       sw2.Stop ();
+
+                                       Console.WriteLine ();
+
+                                       if (proc.ExitCode != 0)
+                                               failures++;
+                                       else
+                                               successes++;
+
+                                       Console.ForegroundColor = proc.ExitCode != 0 ? ConsoleColor.Red : ConsoleColor.Green;
+                                       Console.WriteLine ($"[{sw.Elapsed.ToString ("G")}] {progress} {bench.Name} took {sw2.Elapsed.ToString ("G")} and exited with code: {proc.ExitCode}");
+                                       Console.ResetColor ();
+                               }
+                       }
+
+                       sw.Stop ();
+
+                       Console.ForegroundColor = failures != 0 ? ConsoleColor.Red : ConsoleColor.Green;
+                       Console.WriteLine ($"[{sw.Elapsed.ToString ("G")}] Finished with {successes}/{benchmarks.Length} passing tests");
+                       Console.ResetColor ();
+
+                       return failures;
+               }
+       }
+}
diff --git a/acceptance-tests/profiler-stress/runner.exe.sources b/acceptance-tests/profiler-stress/runner.exe.sources
new file mode 100644 (file)
index 0000000..fc734ed
--- /dev/null
@@ -0,0 +1,156 @@
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Bson/BsonBinaryType.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Bson/BsonBinaryWriter.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Bson/BsonReader.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Bson/BsonToken.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Bson/BsonType.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Bson/BsonWriter.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Bson/BsonObjectId.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Converters/BinaryConverter.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Converters/DataSetConverter.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Converters/DataTableConverter.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Converters/CustomCreationConverter.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Converters/DateTimeConverterBase.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Converters/EntityKeyMemberConverter.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Converters/ExpandoObjectConverter.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Converters/KeyValuePairConverter.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Converters/BsonObjectIdConverter.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Converters/RegexConverter.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Converters/StringEnumConverter.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/ConstructorHandling.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Converters/VersionConverter.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/DateFormatHandling.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/DateTimeZoneHandling.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Formatting.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/JsonConstructorAttribute.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/JsonPosition.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Linq/JPropertyKeyedCollection.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Utilities/DynamicProxy.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Linq/JPath.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Linq/JRaw.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Required.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Serialization/JsonDynamicContract.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Serialization/JsonFormatterConverter.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Serialization/JsonISerializableContract.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Serialization/JsonLinqContract.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Serialization/JsonPrimitiveContract.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Serialization/DynamicValueProvider.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Serialization/ErrorEventArgs.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Linq/JPropertyDescriptor.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Serialization/DefaultReferenceResolver.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/PreserveReferencesHandling.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/IJsonLineInfo.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/JsonArrayAttribute.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/JsonContainerAttribute.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/DefaultValueHandling.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/JsonConverterAttribute.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/JsonObjectAttribute.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/JsonSerializerSettings.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/JsonValidatingReader.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Linq/IJEnumerable.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Linq/JTokenEqualityComparer.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/MemberSerialization.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/ObjectCreationHandling.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Converters/IsoDateTimeConverter.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Converters/JavaScriptDateTimeConverter.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Converters/XmlNodeConverter.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/JsonTextReader.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/JsonPropertyAttribute.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/JsonIgnoreAttribute.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/JsonTextWriter.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/JsonWriterException.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/JsonReaderException.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/JsonConverter.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/JsonConverterCollection.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/JsonReader.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/JsonConvert.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/JsonSerializationException.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/JsonSerializer.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Linq/Extensions.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Linq/JConstructor.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Linq/JContainer.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Linq/JEnumerable.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Linq/JObject.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Linq/JArray.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Linq/JTokenReader.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Linq/JTokenWriter.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Linq/JToken.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Linq/JProperty.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Linq/JTokenType.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Linq/JValue.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Schema/Extensions.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Schema/JsonSchemaException.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Schema/JsonSchemaModel.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Schema/JsonSchemaModelBuilder.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Schema/JsonSchemaNodeCollection.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Schema/JsonSchemaNode.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Schema/JsonSchemaResolver.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Schema/JsonSchemaWriter.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Schema/UndefinedSchemaIdHandling.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Schema/ValidationEventArgs.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Schema/ValidationEventHandler.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Serialization/CamelCasePropertyNamesContractResolver.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Serialization/DefaultContractResolver.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Serialization/DefaultSerializationBinder.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Serialization/ErrorContext.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Serialization/IContractResolver.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Serialization/IValueProvider.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Serialization/JsonArrayContract.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Serialization/JsonContract.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Serialization/JsonDictionaryContract.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Serialization/JsonProperty.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Serialization/JsonPropertyCollection.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/MissingMemberHandling.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/NullValueHandling.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/ReferenceLoopHandling.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Schema/JsonSchema.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Schema/JsonSchemaBuilder.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Schema/JsonSchemaConstants.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Schema/JsonSchemaGenerator.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Serialization/IReferenceResolver.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Schema/JsonSchemaType.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Serialization/JsonObjectContract.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalBase.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalReader.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalWriter.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Serialization/JsonSerializerProxy.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Serialization/JsonStringContract.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Serialization/JsonTypeReflector.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Serialization/CachedAttributeGetter.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Serialization/LateBoundMetadataTypeAttribute.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Serialization/ReflectionValueProvider.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Serialization/OnErrorAttribute.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Utilities/Base64Encoder.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Utilities/DynamicProxyMetaObject.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Utilities/DynamicUtils.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Utilities/DynamicWrapper.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Utilities/DynamicReflectionDelegateFactory.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Serialization/ObjectConstructor.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Utilities/ILGeneratorExtensions.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Utilities/ReflectionDelegateFactory.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Utilities/LateBoundReflectionDelegateFactory.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Utilities/MethodCall.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Utilities/StringReference.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Utilities/ThreadSafeStore.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/TypeNameHandling.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Utilities/BidirectionalDictionary.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Utilities/ConvertUtils.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Utilities/CollectionWrapper.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Utilities/DateTimeUtils.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Utilities/DictionaryWrapper.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Utilities/EnumUtils.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Utilities/EnumValue.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Utilities/EnumValues.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Utilities/JavaScriptUtils.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/JsonToken.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/JsonWriter.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Utilities/StringBuffer.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Utilities/CollectionUtils.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Utilities/ListWrapper.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Utilities/MathUtils.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Utilities/MiscellaneousUtils.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Utilities/ReflectionUtils.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Utilities/StringUtils.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Utilities/TypeExtensions.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/Utilities/ValidationUtils.cs
+../../external/Newtonsoft.Json/Src/Newtonsoft.Json/WriteState.cs
+runner.cs
index 84b4f85c6cdc1dd693b8a41f339693b0fb73fecf..0c070a0f11462278e44c1b024c2e2408e92bc375 100644 (file)
@@ -3,28 +3,35 @@
 SUBMODULES_CONFIG_FILE = $(top_srcdir)/acceptance-tests/SUBMODULES.json
 include $(top_srcdir)/scripts/submodules/versions.mk
 
+$(eval $(call ValidateVersionTemplate,benchmarker,BENCHMARKER))
 $(eval $(call ValidateVersionTemplate,roslyn,ROSLYN))
 $(eval $(call ValidateVersionTemplate,coreclr,CORECLR))
 $(eval $(call ValidateVersionTemplate,ms-test-suite,MSTESTSUITE))
 
 # Bump the given submodule to the revision given by the REV make variable
 # If COMMIT is 1, commit the change
+bump-benchmarker: __bump-benchmarker
 bump-roslyn: __bump-version-roslyn
 bump-coreclr: __bump-version-coreclr
 bump-ms-test-suite: __bump-version-ms-test-suite
 
 # Bump the given submodule to the branch given by the BRANCH/REMOTE_BRANCH make variables
 # If COMMIT is 1, commit the change
+bump-branch-benchmarker: __bump-branch-benchmarker
 bump-branch-roslyn: __bump-branch-roslyn
 bump-branch-coreclr: __bump-branch-coreclr
 bump-branch-ms-test-suite: __bump-branch-ms-test-suite
 
 # Bump the given submodule to its current GIT version
 # If COMMIT is 1, commit the change
+bump-current-benchmarker: __bump-current-benchmarker
 bump-current-roslyn: __bump-current-version-roslyn
 bump-current-coreclr: __bump-current-version-coreclr
 bump-current-ms-test-suite: __bump-current-version-ms-test-suite
 
+commit-bump-benchmarker:
+       $(MAKE) bump-benchmarker COMMIT=1
+
 commit-bump-roslyn:
        $(MAKE) bump-roslyn COMMIT=1
 
@@ -34,6 +41,9 @@ commit-bump-coreclr:
 commit-bump-ms-test-suite:
        $(MAKE) bump-ms-test-suite COMMIT=1
 
+commit-bump-current-benchmarker:
+       $(MAKE) bump-current-benchmarker COMMIT=1
+
 commit-bump-current-roslyn:
        $(MAKE) bump-current-roslyn COMMIT=1
 
index 21db9420c474e44b3e974d7e4b150795ea41094e..9a10f6d4917d3143ac993bd5f0f59e26fdd941cf 100644 (file)
@@ -2,7 +2,7 @@
 #AC_PREREQ([2.62])
 
 # when bumping version number below, keep it in sync with man/mono.1 too
-AC_INIT(mono, [4.7.0],
+AC_INIT(mono, [4.9.0],
         [http://bugzilla.xamarin.com/enter_bug.cgi?classification=Mono])
 
 AC_CONFIG_SRCDIR([README.md])
index c2020a74450622d51af1303755dde8e3d098861b..c4fd545dd104c5413ea6a5bcb627a25bccf6fec1 100644 (file)
@@ -143,8 +143,8 @@ to the control port
 program behaviour.
 The default is to collect a 100 times per second (100 Hz) the
 instruction pointer.
-This is equivalent to the value \[lq]cycles/100\[rq] for
-\f[I]TYPE\f[].
+This is equivalent to the value \[lq]cycles/100\[rq].
+A value of zero for \f[I]FREQ\f[] effectively disables sampling.
 On some systems, like with recent Linux kernels, it is possible to
 cause the sampling to happen for other events provided by the
 performance counters of the cpu.
index 9313227067d8d83dfe78389c285f6058e8a5c75b..3ea9e744843837ca6d031ee3362ae37393a1c97f 100644 (file)
@@ -40,6 +40,7 @@ Mono.Debugger.Soft/BreakpointEventRequest.cs
 Mono.Debugger.Soft/MethodEntryEventRequest.cs
 Mono.Debugger.Soft/AssemblyLoadEventRequest.cs
 Mono.Debugger.Soft/LocalVariable.cs
+Mono.Debugger.Soft/LocalScope.cs
 Mono.Debugger.Soft/ParameterInfoMirror.cs
 Mono.Debugger.Soft/Event.cs
 Mono.Debugger.Soft/EventSet.cs
index 05ea6bcdaf44aa4a2714b2c8758767164ffb0170..93e9a959eee4900912bf6f521a86a3acd01e9d31 100644 (file)
@@ -117,6 +117,8 @@ namespace Mono.Debugger.Soft
                public string[] names;
                public int[] live_range_start;
                public int[] live_range_end;
+               public int[] scopes_start;
+               public int[] scopes_end;
        }
 
        struct PropInfo {
@@ -418,7 +420,7 @@ namespace Mono.Debugger.Soft
                 * with newer runtimes, and vice versa.
                 */
                internal const int MAJOR_VERSION = 2;
-               internal const int MINOR_VERSION = 42;
+               internal const int MINOR_VERSION = 43;
 
                enum WPSuspendPolicy {
                        NONE = 0,
@@ -1910,6 +1912,19 @@ namespace Mono.Debugger.Soft
                        var res = SendReceive (CommandSet.METHOD, (int)CmdMethod.GET_LOCALS_INFO, new PacketWriter ().WriteId (id));
 
                        LocalsInfo info = new LocalsInfo ();
+
+                       if (Version.AtLeast (2, 43)) {
+                               int nscopes = res.ReadInt ();
+                               info.scopes_start = new int [nscopes];
+                               info.scopes_end = new int [nscopes];
+                               int last_start = 0;
+                               for (int i = 0; i < nscopes; ++i) {
+                                       info.scopes_start [i] = last_start + res.ReadInt ();
+                                       info.scopes_end [i] = info.scopes_start [i] + res.ReadInt ();
+                                       last_start = info.scopes_start [i];
+                               }
+                       }
+
                        int nlocals = res.ReadInt ();
                        info.types = new long [nlocals];
                        for (int i = 0; i < nlocals; ++i)
diff --git a/mcs/class/Mono.Debugger.Soft/Mono.Debugger.Soft/LocalScope.cs b/mcs/class/Mono.Debugger.Soft/Mono.Debugger.Soft/LocalScope.cs
new file mode 100644 (file)
index 0000000..52c58b2
--- /dev/null
@@ -0,0 +1,35 @@
+using System;
+
+namespace Mono.Debugger.Soft
+{
+       public class LocalScope : Mirror {
+
+               MethodMirror method;
+               int live_range_start, live_range_end;
+
+           internal LocalScope (VirtualMachine vm, MethodMirror method, int live_range_start, int live_range_end) : base (vm, 0) {
+                       this.method = method;
+                       this.live_range_start = live_range_start;
+                       this.live_range_end = live_range_end;
+               }
+
+               public MethodMirror Method {
+                       get {
+                               return method;
+                       }
+               }
+
+               public int LiveRangeStart {
+                       get {
+                               return live_range_start;
+                       }
+               }
+
+               public int LiveRangeEnd {
+                       get {
+                               return live_range_end;
+                       }
+               }
+       }
+}
+
index 88dd7277c20262752cb2ecaf7a21f8e5e48432cf..fb10f7117c30258350bad2e93053dac7cbb14cbe 100644 (file)
@@ -19,6 +19,7 @@ namespace Mono.Debugger.Soft
                ParameterInfoMirror[] param_info;
                ParameterInfoMirror ret_param;
                LocalVariable[] locals;
+               LocalScope[] scopes;
                IList<Location> locations;
                MethodBodyMirror body;
                MethodMirror gmd;
@@ -239,6 +240,12 @@ namespace Mono.Debugger.Soft
                        }
                }
 
+               public LocalScope [] GetScopes () {
+                       vm.CheckProtocolVersion (2, 43);
+                       GetLocals ();
+                       return scopes;
+               }
+
                public LocalVariable[] GetLocals () {
                        if (locals == null) {
                                LocalsInfo li = new LocalsInfo ();
@@ -258,6 +265,12 @@ namespace Mono.Debugger.Soft
 
                                for (int i = 0; i < li.names.Length; ++i)
                                        locals [i + pi.Length] = new LocalVariable (vm, this, i, li.types [i], li.names [i], li.live_range_start [i], li.live_range_end [i], false);
+
+                               if (vm.Version.AtLeast (2, 43)) {
+                                       scopes = new LocalScope [li.scopes_start.Length];
+                                       for (int i = 0; i < scopes.Length; ++i)
+                                               scopes [i] = new LocalScope (vm, this, li.scopes_start [i], li.scopes_end [i]);
+                               }
                        }
                        return locals;
                }
index 018435051777ac312d0831c2d71682ef37c6bee6..1933fc5e827372129731655297986401622ff064 100644 (file)
@@ -1846,6 +1846,9 @@ public class DebuggerTests
                                Assert.Fail ();
                        }
                }
+
+               var scopes = frame.Method.GetScopes ();
+               Assert.AreEqual (2, scopes.Length);
        }
 
        Event step_once () {
index d2fa435d45f2be6ef83f95e6632955480085494d..396b16f4c5416c06b77b6666e47c6404ea198e26 100644 (file)
@@ -230,6 +230,9 @@ namespace System.Net.Sockets
                                         * effects on Linux, as the socket option is kludged by
                                         * turning on or off PMTU discovery... */
                                        this.DontFragment = false;
+                                       this.NoDelay = false;
+                               } else if (address_family == AddressFamily.InterNetworkV6) {
+                                       this.DualMode = true;
                                }
 
                                /* Microsoft sets these to 8192, but we are going to keep them
index 329c4a2c19adba4900f992d213bca4ee7d55c2af..15ec5bb59dbf74ce6b8206c6acb1f2a0dc66eaad 100644 (file)
@@ -427,10 +427,10 @@ namespace System.Net {
 
                        StreamWriter writer = new StreamWriter (ms, encoding, 256);
                        writer.Write ("HTTP/{0} {1} {2}\r\n", version, status_code, status_description);
-                       string headers_str = headers.ToString ();
+                       string headers_str = FormatHeaders (headers);
                        writer.Write (headers_str);
                        writer.Flush ();
-                       int preamble = (encoding.CodePage == 65001) ? 3 : encoding.GetPreamble ().Length;
+                       int preamble = encoding.GetPreamble ().Length;
                        if (output_stream == null)
                                output_stream = context.Connection.GetResponseStream ();
 
@@ -439,6 +439,24 @@ namespace System.Net {
                        HeadersSent = true;
                }
 
+               static string FormatHeaders (WebHeaderCollection headers)
+               {
+                       var sb = new StringBuilder();
+
+                       for (int i = 0; i < headers.Count ; i++) {
+                               string key = headers.GetKey (i);
+                               if (WebHeaderCollection.AllowMultiValues (key)) {
+                                       foreach (string v in headers.GetValues (i)) {
+                                               sb.Append (key).Append (": ").Append (v).Append ("\r\n");
+                                       }
+                               } else {
+                                       sb.Append (key).Append (": ").Append (headers.Get (i)).Append ("\r\n");
+                               }
+                       }
+
+                       return sb.Append("\r\n").ToString();
+               }
+
                static string CookieToClientString (Cookie cookie)
                {
                        if (cookie.Name.Length == 0)
index b3c996044ef3eb1fb7c24fa0e5040ffec577ef3b..17308253af502c5f6d2c134ba11acb2a0e4be2c8 100644 (file)
@@ -132,7 +132,7 @@ namespace System.Net
                // Fields
                
                public const int DefaultNonPersistentConnectionLimit = 4;
-#if MONOTOUCH
+#if MOBILE
                public const int DefaultPersistentConnectionLimit = 10;
 #else
                public const int DefaultPersistentConnectionLimit = 2;
index d9d43bf40a735488f12a6daead4b954d790b5ac9..c1bd5271adf78ba7dbb25aac7638d8cb7a676378 100644 (file)
@@ -670,7 +670,7 @@ namespace System.Net
                                                var value = s.Substring (pos_s + 1).Trim ();
 
                                                var h = data.Headers;
-                                               if (h.AllowMultiValues (header)) {
+                                               if (WebHeaderCollection.AllowMultiValues (header)) {
                                                        h.AddInternal (header, value);
                                                } else  {
                                                        h.SetInternal (header, value);
index 9551c1e6027131d4217bd59a13d986438873d5e2..4955d3f3c6096effcfa6a54a0c6dfb2a53b937e7 100755 (executable)
@@ -1207,9 +1207,9 @@ namespace MonoTests.System.Net.Sockets
                        Socket sock = new Socket (AddressFamily.InterNetwork,
                                                  SocketType.Stream,
                                                  ProtocolType.Tcp);
-                       
+
                        Assert.AreEqual (false, sock.NoDelay, "NoDelayDefaultTcp");
-                       
+
                        sock.Close ();
                }
 
@@ -4287,51 +4287,84 @@ namespace MonoTests.System.Net.Sockets
                
                [Test]
                public void ConnectToIPV4EndPointUsingDualModelSocket () {
-                       using (var server = new Socket (SocketType.Stream, ProtocolType.Tcp))
-                       using (var client = new Socket (SocketType.Stream, ProtocolType.Tcp)) {
+                       /*
+                        * IPv6 DualMode sockets are defaults in Mono. Explicitly specify that
+                        * anyways in this test to make it more interoparable with .NET where
+                        * IPv6 and DualMode needs to be specified.
+                        */
+                       using (var server = new Socket (AddressFamily.InterNetworkV6, SocketType.Stream, ProtocolType.Tcp)) {
+
                                var host = new IPEndPoint (IPAddress.Loopback, NetworkHelpers.FindFreePort ());
-                                       
+
+                               server.DualMode = true;
                                server.Bind (host);
-                               server.Listen (0);
+                               /*
+                                * Nothing to Accept the connect - we need a backlog to make sure we don't get 
+                                Connection refused.
+                                */
+                               server.Listen (3);
                                
                                var ep = server.LocalEndPoint as IPEndPoint;
-                               
+                               var client = new Socket (AddressFamily.InterNetworkV6, SocketType.Stream, ProtocolType.Tcp);
+                               client.DualMode = true;
                                client.Connect (ep);
-                               client.Disconnect (true);
-                               
+                               client.Disconnect (false);
+                               client.Close ();
+
+                               client = new Socket (AddressFamily.InterNetworkV6, SocketType.Stream, ProtocolType.Tcp);
+                               client.DualMode = true;
                                client.Connect (IPAddress.Loopback, ep.Port);
-                               client.Disconnect (true);
-                               
-                               client.Connect (new [] {IPAddress.Loopback}, ep.Port);
-                               client.Disconnect (true);
+                               client.Disconnect (false);
+                               client.Close ();
+
+                               client = new Socket (AddressFamily.InterNetworkV6, SocketType.Stream, ProtocolType.Tcp);
+                               client.DualMode = true;
+                               client.Connect (new [] { IPAddress.Loopback }, ep.Port);
+                               client.Disconnect (false);
+                               client.Close ();
                        }
                }
                
                [Test]
                public void BeginConnectToIPV4EndPointUsingDualModelSocket () {
-                       using (var server = new Socket (SocketType.Stream, ProtocolType.Tcp))
-                       using (var client = new Socket (SocketType.Stream, ProtocolType.Tcp)) {
+                       /*
+                        * IPv6 DualMode sockets are defaults in Mono. Explicitly specify that
+                        * anyways in this test to make it more interoparable with .NET where
+                        * IPv6 and DualMode needs to be specified.
+                        */
+                       using (var server = new Socket (AddressFamily.InterNetworkV6, SocketType.Stream, ProtocolType.Tcp))
+                       {
                                var host = new IPEndPoint (IPAddress.Loopback, NetworkHelpers.FindFreePort ());
-                                       
+
+                               server.DualMode = true;
                                server.Bind (host);
-                               server.Listen (0);
+                               server.Listen (10);
                                
                                var ep = server.LocalEndPoint as IPEndPoint;
-                               
+
                                BCCalledBack.Reset ();
+                               var client = new Socket (AddressFamily.InterNetworkV6, SocketType.Stream, ProtocolType.Tcp);
+                               client.DualMode = true;
                                var ar1 = client.BeginConnect (ep, BCCallback, client);
                                Assert.IsTrue (BCCalledBack.WaitOne (10000), "#1");
-                               client.Disconnect (true);
-                               
+                               client.Disconnect (false);
+                               client.Close ();
+
                                BCCalledBack.Reset ();
+                               client = new Socket (AddressFamily.InterNetworkV6, SocketType.Stream, ProtocolType.Tcp);
+                               client.DualMode = true;
                                var ar2 = client.BeginConnect (IPAddress.Loopback, ep.Port, BCCallback, client);
                                Assert.IsTrue (BCCalledBack.WaitOne (10000), "#2");
-                               client.Disconnect (true);
-                               
+                               client.Disconnect (false);
+                               client.Close ();
+
                                BCCalledBack.Reset ();
+                               client = new Socket (AddressFamily.InterNetworkV6, SocketType.Stream, ProtocolType.Tcp);
+                               client.DualMode = true;
                                var ar3 = client.BeginConnect (new [] {IPAddress.Loopback}, ep.Port, BCCallback, client);
                                Assert.IsTrue (BCCalledBack.WaitOne (10000), "#2");
-                               client.Disconnect (true);
+                               client.Disconnect (false);
+                               client.Close();
                        }
                }
 
index 8620d1ce32a9b34bd6b98f40ea9ac0805791250a..70dcede89717281e238f732afa91b55935082777 100644 (file)
@@ -534,6 +534,33 @@ namespace MonoTests.System.Net {
 
                        return clientEndPoint;
                }
+
+               [Test]
+               public void UserHeaderWithDoubleMultiValue ()
+               {
+                       string uri = "http://localhost:" + NetworkHelpers.FindFreePort () + "/";
+
+                       var l = new HttpListener ();
+                       l.Prefixes.Add (uri);
+                       l.Start ();
+                       l.BeginGetContext (ar => {
+                               var ctx = l.EndGetContext (ar);
+
+                               var response = ctx.Response;
+                               response.Headers.Add ("X-Custom-Header", "A");
+                               response.Headers.Add ("X-Custom-Header", "B");
+
+                               response.Close ();
+                       }, null);
+
+                       HttpWebRequest wr = HttpWebRequest.CreateHttp (uri);
+                       var resp = wr.GetResponse ();
+                       var vls = resp.Headers.GetValues ("X-Custom-Header");
+
+                       Assert.AreEqual (2, vls.Length);
+
+                       l.Close ();
+               }
                
                [Test]
                public void HttpClientIsDisconnectedCheckForWriteException()
index f1924b22e07ef7e603d8d2446de8ff0a85ff1e7a..94d6aac785a15beba965aae8f8dff67574385331 100644 (file)
@@ -65,7 +65,6 @@ namespace System.Threading {
                /* start_notify is used by the runtime to signal that Start()
                 * is ok to return
                 */
-               private IntPtr start_notify;
                private IntPtr stack_ptr;
                private UIntPtr static_data; /* GC-tracked */
                private IntPtr runtime_thread_info;
@@ -90,12 +89,20 @@ namespace System.Threading {
                private IntPtr interrupt_on_stop;
                private IntPtr flags;
                private IntPtr thread_pinning_ref;
-               private IntPtr start_notify_refcount;
+               private IntPtr abort_protected_block_count;
+               private int priority = (int) ThreadPriority.Normal;
                /* 
                 * These fields are used to avoid having to increment corlib versions
                 * when a new field is added to the unmanaged MonoThread structure.
                 */
+               private IntPtr unused1;
                private IntPtr unused2;
+
+               /* This is used only to check that we are in sync between the representation
+                * of MonoInternalThread in native and InternalThread in managed
+                *
+                * DO NOT RENAME! DO NOT ADD FIELDS AFTER! */
+               private IntPtr last;
                #endregion
 #pragma warning restore 169, 414, 649
 
@@ -116,7 +123,6 @@ namespace System.Threading {
                private InternalThread internal_thread;
                object m_ThreadStartArg;
                object pending_exception;
-               int priority = (int) ThreadPriority.Normal;
                #endregion
 #pragma warning restore 414
 
index 36ae8687aae76a3cf40e67ae5f76c4dc32993fed..d6b0ec038e4e7ad4878b4fd0e29645994c3e7b26 100644 (file)
@@ -57,7 +57,7 @@ namespace System {
                 * of icalls, do not require an increment.
                 */
 #pragma warning disable 169
-               private const int mono_corlib_version = 153;
+               private const int mono_corlib_version = 155;
 #pragma warning restore 169
 
                [ComVisible (true)]
index a869f7191f7daf9d8ba55795b459e8f909b117a2..4c6694f1e17f137b4112f86e51c0081a24041b53 100644 (file)
@@ -94,25 +94,6 @@ namespace MonoTests.System.Threading
                //TimeSpan MaxValue = TimeSpan.FromMilliseconds ((long) Int32.MaxValue);
                TimeSpan TooLarge = TimeSpan.FromMilliseconds ((long) Int32.MaxValue + 1);
 
-               static bool is_win32;
-               static bool is_mono;
-
-               static ThreadTest ()
-               {
-                       switch (Environment.OSVersion.Platform) {
-                       case PlatformID.Win32NT:
-                       case PlatformID.Win32S:
-                       case PlatformID.Win32Windows:
-                       case PlatformID.WinCE:
-                               is_win32 = true;
-                               break;
-                       }
-
-                       // check a class in mscorlib to determine if we're running on Mono
-                       if (Type.GetType ("Mono.Runtime", false) != null)
-                               is_mono = true;
-               }
-
                //Some Classes to test as threads
                private class C1Test
                {
@@ -327,8 +308,6 @@ namespace MonoTests.System.Threading
                [Category ("NotDotNet")] // it hangs.
                public void TestStart()
                {
-                       if (is_win32 && is_mono)
-                               Assert.Fail ("This test fails on Win32. The test should be fixed.");
                {
                        C1Test test1 = new C1Test();
                        Thread TestThread = new Thread(new ThreadStart(test1.TestMethod));
@@ -370,9 +349,6 @@ namespace MonoTests.System.Threading
                [Test]
                public void TestApartmentState ()
                {
-                       if (is_win32 && is_mono)
-                               Assert.Fail ("This test fails on mono on win32. Our runtime should be fixed.");
-
                        C2Test test1 = new C2Test();
                        Thread TestThread = new Thread(new ThreadStart(test1.TestMethod));
                        Assert.AreEqual (ApartmentState.Unknown, TestThread.ApartmentState, "#1");
@@ -390,9 +366,6 @@ namespace MonoTests.System.Threading
                [Category ("NotWorking")] // setting the priority of a Thread before it is started isn't implemented in Mono yet
                public void TestPriority1()
                {
-                       if (is_win32 && is_mono)
-                               Assert.Fail ("This test fails on mono on Win32. Our runtime should be fixed.");
-
                        C2Test test1 = new C2Test();
                        Thread TestThread = new Thread(new ThreadStart(test1.TestMethod));
                        try {
@@ -487,9 +460,6 @@ namespace MonoTests.System.Threading
                [Test]
                public void TestIsBackground1 ()
                {
-                       if (is_win32 && is_mono)
-                               Assert.Fail ("This test fails on mono on Win32. Our runtime should be fixed.");
-
                        C2Test test1 = new C2Test();
                        Thread TestThread = new Thread(new ThreadStart(test1.TestMethod));
                        try {
@@ -534,9 +504,6 @@ namespace MonoTests.System.Threading
                [Test]
                public void TestName()
                {
-                       if (is_win32 && is_mono)
-                               Assert.Fail ("This test fails on mono on Win32. Our runtime should be fixed.");
-
                        C2Test test1 = new C2Test();
                        Thread TestThread = new Thread(new ThreadStart(test1.TestMethod));
                        try {
@@ -696,9 +663,6 @@ namespace MonoTests.System.Threading
                [Test]
                public void TestThreadState ()
                {
-                       if (is_win32 && is_mono)
-                               Assert.Fail ("This test fails on mono on Win32. Our runtime should be fixed.");
-
                        //TODO: Test The rest of the possible transitions
                        C2Test test1 = new C2Test();
                        Thread TestThread = new Thread(new ThreadStart(test1.TestMethod));
@@ -830,9 +794,6 @@ namespace MonoTests.System.Threading
                [Category("NotDotNet")] // On MS, ThreadStateException is thrown on Abort: "Thread is suspended; attempting to abort"
                public void TestSuspendAbort ()
                {
-                       if (is_win32 && is_mono)
-                               Assert.Fail ("This test fails on Win32. The test should be fixed.");
-
                        Thread t = new Thread (new ThreadStart (DoCount));
                        t.IsBackground = true;
                        t.Start ();
@@ -898,7 +859,6 @@ namespace MonoTests.System.Threading
                }
                
                [Test]
-               [Category ("NotDotNet")] // it crashes nunit.
                public void Test_InterruptCurrentThread ()
                {
                        ManualResetEvent mre = new ManualResetEvent (false);
@@ -937,6 +897,7 @@ namespace MonoTests.System.Threading
 
 #if MONO_FEATURE_MULTIPLE_APPDOMAINS
                [Test]
+               [Category ("NotDotNet")]
                public void CurrentThread_Domains ()
                {
                        AppDomain ad = AppDomain.CreateDomain ("foo");
index 42743232cf72ab204be6f1ea18589b80d6eb29e1..49e6c040ee7e8e9ba4ea1fda118f3390c05e7d82 100644 (file)
@@ -247,7 +247,7 @@ namespace System.Net {
         private WebHeaderCollectionType m_Type;
 
 #if MONO
-        internal bool AllowMultiValues (string name)
+        internal static bool AllowMultiValues (string name)
         {
             var hinfo = HInfo[name];
             // Is common header which supports multi value or it's unknown header
index 0eb885e055e4a843868fbcc00a1f0600a99827a1..dfb60a16c827e5db876948193eef80196708b887 100644 (file)
@@ -14,17 +14,14 @@ OTHER_H = \
        access.h        \
        context.h       \
        error.h         \
-       events.h        \
        io.h            \
        io-trace.h      \
        io-layer.h      \
        io-portability.h        \
        macros.h        \
        messages.h      \
-       mutexes.h       \
        processes.h     \
        security.h      \
-       semaphores.h    \
        sockets.h       \
        status.h        \
        timefuncs.h     \
@@ -41,9 +38,6 @@ OTHER_SRC = \
        context.h               \
        error.c                 \
        error.h                 \
-       events.c                \
-       events.h                \
-       event-private.h         \
        io.c                    \
        io.h                    \
        io-portability.c        \
@@ -54,20 +48,12 @@ OTHER_SRC = \
        macros.h                \
        messages.c              \
        messages.h              \
-       mutexes.c               \
-       mutexes.h               \
-       mutex-private.h         \
        posix.c                 \
        processes.c             \
        processes.h             \
        process-private.h       \
        security.c              \
        security.h              \
-       semaphores.c            \
-       semaphores.h            \
-       semaphore-private.h     \
-       shared.c                \
-       shared.h                \
        sockets.c               \
        sockets.h               \
        socket-private.h        \
diff --git a/mono/io-layer/event-private.h b/mono/io-layer/event-private.h
deleted file mode 100644 (file)
index 07b35e0..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * event-private.h:  Private definitions for event handles
- *
- * Author:
- *     Dick Porter (dick@ximian.com)
- *
- * (C) 2002 Ximian, Inc.
- */
-
-#ifndef _WAPI_EVENT_PRIVATE_H_
-#define _WAPI_EVENT_PRIVATE_H_
-
-#include <config.h>
-#include <glib.h>
-#include <pthread.h>
-
-#include "wapi-private.h"
-
-struct _WapiHandle_event
-{
-       gboolean manual;
-       guint32 set_count;
-};
-
-struct _WapiHandle_namedevent
-{
-       struct _WapiHandle_event e;
-       WapiSharedNamespace sharedns;
-};
-
-void
-_wapi_event_init (void);
-
-#endif /* _WAPI_EVENT_PRIVATE_H_ */
diff --git a/mono/io-layer/events.c b/mono/io-layer/events.c
deleted file mode 100644 (file)
index 8e3fa4a..0000000
+++ /dev/null
@@ -1,516 +0,0 @@
-/*
- * events.c:  Event handles
- *
- * Author:
- *     Dick Porter (dick@ximian.com)
- *
- * (C) 2002 Ximian, Inc.
- */
-
-#include <config.h>
-#include <glib.h>
-#include <pthread.h>
-#include <string.h>
-
-#include <mono/io-layer/wapi.h>
-#include <mono/io-layer/wapi-private.h>
-#include <mono/io-layer/event-private.h>
-#include <mono/io-layer/io-trace.h>
-#include <mono/utils/mono-once.h>
-#include <mono/utils/mono-logger-internals.h>
-#include <mono/utils/w32handle.h>
-
-static void event_signal(gpointer handle);
-static gboolean event_own (gpointer handle);
-static void event_details (gpointer data);
-static const gchar* event_typename (void);
-static gsize event_typesize (void);
-
-static void namedevent_signal (gpointer handle);
-static gboolean namedevent_own (gpointer handle);
-static void namedevent_details (gpointer data);
-static const gchar* namedevent_typename (void);
-static gsize namedevent_typesize (void);
-
-static MonoW32HandleOps _wapi_event_ops = {
-       NULL,                   /* close */
-       event_signal,           /* signal */
-       event_own,              /* own */
-       NULL,                   /* is_owned */
-       NULL,                   /* special_wait */
-       NULL,                   /* prewait */
-       event_details,  /* details */
-       event_typename, /* typename */
-       event_typesize, /* typesize */
-};
-
-static MonoW32HandleOps _wapi_namedevent_ops = {
-       NULL,                   /* close */
-       namedevent_signal,      /* signal */
-       namedevent_own,         /* own */
-       NULL,                   /* is_owned */
-       NULL,                   /* special_wait */
-       NULL,                   /* prewait */
-       namedevent_details,     /* details */
-       namedevent_typename, /* typename */
-       namedevent_typesize, /* typesize */
-};
-
-void
-_wapi_event_init (void)
-{
-       mono_w32handle_register_ops (MONO_W32HANDLE_EVENT,      &_wapi_event_ops);
-       mono_w32handle_register_ops (MONO_W32HANDLE_NAMEDEVENT, &_wapi_namedevent_ops);
-
-       mono_w32handle_register_capabilities (MONO_W32HANDLE_EVENT,
-               (MonoW32HandleCapability)(MONO_W32HANDLE_CAP_WAIT | MONO_W32HANDLE_CAP_SIGNAL));
-       mono_w32handle_register_capabilities (MONO_W32HANDLE_NAMEDEVENT,
-               (MonoW32HandleCapability)(MONO_W32HANDLE_CAP_WAIT | MONO_W32HANDLE_CAP_SIGNAL));
-}
-
-static const char* event_handle_type_to_string (MonoW32HandleType type)
-{
-       switch (type) {
-       case MONO_W32HANDLE_EVENT: return "event";
-       case MONO_W32HANDLE_NAMEDEVENT: return "named event";
-       default:
-               g_assert_not_reached ();
-       }
-}
-
-static gboolean event_handle_own (gpointer handle, MonoW32HandleType type)
-{
-       struct _WapiHandle_event *event_handle;
-       gboolean ok;
-
-       ok = mono_w32handle_lookup (handle, type, (gpointer *)&event_handle);
-       if (!ok) {
-               g_warning ("%s: error looking up %s handle %p",
-                       __func__, event_handle_type_to_string (type), handle);
-               return FALSE;
-       }
-
-       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: owning %s handle %p",
-               __func__, event_handle_type_to_string (type), handle);
-
-       if (!event_handle->manual) {
-               g_assert (event_handle->set_count > 0);
-               event_handle->set_count --;
-
-               if (event_handle->set_count == 0)
-                       mono_w32handle_set_signal_state (handle, FALSE, FALSE);
-       }
-
-       return TRUE;
-}
-
-static void event_signal(gpointer handle)
-{
-       SetEvent(handle);
-}
-
-static gboolean event_own (gpointer handle)
-{
-       return event_handle_own (handle, MONO_W32HANDLE_EVENT);
-}
-
-static void namedevent_signal (gpointer handle)
-{
-       SetEvent (handle);
-}
-
-/* NB, always called with the shared handle lock held */
-static gboolean namedevent_own (gpointer handle)
-{
-       return event_handle_own (handle, MONO_W32HANDLE_NAMEDEVENT);
-}
-
-static void event_details (gpointer data)
-{
-       struct _WapiHandle_event *event = (struct _WapiHandle_event *)data;
-       g_print ("manual: %s, set_count: %d",
-               event->manual ? "TRUE" : "FALSE", event->set_count);
-}
-
-static void namedevent_details (gpointer data)
-{
-       struct _WapiHandle_namedevent *namedevent = (struct _WapiHandle_namedevent *)data;
-       g_print ("manual: %s, set_count: %d, name: \"%s\"",
-               namedevent->e.manual ? "TRUE" : "FALSE", namedevent->e.set_count, namedevent->sharedns.name);
-}
-
-static const gchar* event_typename (void)
-{
-       return "Event";
-}
-
-static gsize event_typesize (void)
-{
-       return sizeof (struct _WapiHandle_event);
-}
-
-static const gchar* namedevent_typename (void)
-{
-       return "N.Event";
-}
-
-static gsize namedevent_typesize (void)
-{
-       return sizeof (struct _WapiHandle_namedevent);
-}
-
-static gpointer event_handle_create (struct _WapiHandle_event *event_handle, MonoW32HandleType type, gboolean manual, gboolean initial)
-{
-       gpointer handle;
-       int thr_ret;
-
-       event_handle->manual = manual;
-       event_handle->set_count = (initial && !manual) ? 1 : 0;
-
-       handle = mono_w32handle_new (type, event_handle);
-       if (handle == INVALID_HANDLE_VALUE) {
-               g_warning ("%s: error creating %s handle",
-                       __func__, event_handle_type_to_string (type));
-               SetLastError (ERROR_GEN_FAILURE);
-               return NULL;
-       }
-
-       thr_ret = mono_w32handle_lock_handle (handle);
-       g_assert (thr_ret == 0);
-
-       if (initial)
-               mono_w32handle_set_signal_state (handle, TRUE, FALSE);
-
-       thr_ret = mono_w32handle_unlock_handle (handle);
-       g_assert (thr_ret == 0);
-
-       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: created %s handle %p",
-               __func__, event_handle_type_to_string (type), handle);
-
-       return handle;
-}
-
-static gpointer event_create (gboolean manual, gboolean initial)
-{
-       struct _WapiHandle_event event_handle;
-       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: creating %s handle",
-               __func__, event_handle_type_to_string (MONO_W32HANDLE_EVENT));
-       return event_handle_create (&event_handle, MONO_W32HANDLE_EVENT, manual, initial);
-}
-
-static gpointer namedevent_create (gboolean manual, gboolean initial, const gunichar2 *name G_GNUC_UNUSED)
-{
-       gpointer handle;
-       gchar *utf8_name;
-       int thr_ret;
-
-       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: creating %s handle",
-               __func__, event_handle_type_to_string (MONO_W32HANDLE_NAMEDEVENT));
-
-       /* w32 seems to guarantee that opening named objects can't race each other */
-       thr_ret = _wapi_namespace_lock ();
-       g_assert (thr_ret == 0);
-
-       utf8_name = g_utf16_to_utf8 (name, -1, NULL, NULL, NULL);
-
-       handle = _wapi_search_handle_namespace (MONO_W32HANDLE_NAMEDEVENT, utf8_name);
-       if (handle == INVALID_HANDLE_VALUE) {
-               /* The name has already been used for a different object. */
-               handle = NULL;
-               SetLastError (ERROR_INVALID_HANDLE);
-       } else if (handle) {
-               /* Not an error, but this is how the caller is informed that the event wasn't freshly created */
-               SetLastError (ERROR_ALREADY_EXISTS);
-
-               /* this is used as creating a new handle */
-               mono_w32handle_ref (handle);
-       } else {
-               /* A new named event */
-               struct _WapiHandle_namedevent namedevent_handle;
-
-               strncpy (&namedevent_handle.sharedns.name [0], utf8_name, MAX_PATH);
-               namedevent_handle.sharedns.name [MAX_PATH] = '\0';
-
-               handle = event_handle_create ((struct _WapiHandle_event*) &namedevent_handle, MONO_W32HANDLE_NAMEDEVENT, manual, initial);
-       }
-
-       g_free (utf8_name);
-
-       thr_ret = _wapi_namespace_unlock (NULL);
-       g_assert (thr_ret == 0);
-
-       return handle;
-}
-
-
-/**
- * CreateEvent:
- * @security: Ignored for now.
- * @manual: Specifies whether the new event handle has manual or auto
- * reset behaviour.
- * @initial: Specifies whether the new event handle is initially
- * signalled or not.
- * @name:Pointer to a string specifying the name of this name, or
- * %NULL.  Currently ignored.
- *
- * Creates a new event handle.
- *
- * An event handle is signalled with SetEvent().  If the new handle is
- * a manual reset event handle, it remains signalled until it is reset
- * with ResetEvent().  An auto reset event remains signalled until a
- * single thread has waited for it, at which time the event handle is
- * automatically reset to unsignalled.
- *
- * Return value: A new handle, or %NULL on error.
- */
-gpointer CreateEvent(WapiSecurityAttributes *security G_GNUC_UNUSED,
-                    gboolean manual, gboolean initial,
-                    const gunichar2 *name G_GNUC_UNUSED)
-{
-       /* Need to blow away any old errors here, because code tests
-        * for ERROR_ALREADY_EXISTS on success (!) to see if an event
-        * was freshly created
-        */
-       SetLastError (ERROR_SUCCESS);
-
-       return name ? namedevent_create (manual, initial, name) : event_create (manual, initial);
-}
-
-/**
- * PulseEvent:
- * @handle: The event handle.
- *
- * Sets the event handle @handle to the signalled state, and then
- * resets it to unsignalled after informing any waiting threads.
- *
- * If @handle is a manual reset event, all waiting threads that can be
- * released immediately are released.  @handle is then reset.  If
- * @handle is an auto reset event, one waiting thread is released even
- * if multiple threads are waiting.
- *
- * Return value: %TRUE on success, %FALSE otherwise.  (Currently only
- * ever returns %TRUE).
- */
-gboolean PulseEvent(gpointer handle)
-{
-       MonoW32HandleType type;
-       struct _WapiHandle_event *event_handle;
-       int thr_ret;
-
-       if (handle == NULL) {
-               SetLastError (ERROR_INVALID_HANDLE);
-               return(FALSE);
-       }
-
-       switch (type = mono_w32handle_get_type (handle)) {
-       case MONO_W32HANDLE_EVENT:
-       case MONO_W32HANDLE_NAMEDEVENT:
-               break;
-       default:
-               SetLastError (ERROR_INVALID_HANDLE);
-               return FALSE;
-       }
-
-       if (!mono_w32handle_lookup (handle, type, (gpointer *)&event_handle)) {
-               g_warning ("%s: error looking up %s handle %p",
-                       __func__, event_handle_type_to_string (type), handle);
-               return FALSE;
-       }
-
-       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: pulsing %s handle %p",
-               __func__, event_handle_type_to_string (type), handle);
-
-       thr_ret = mono_w32handle_lock_handle (handle);
-       g_assert (thr_ret == 0);
-
-       if (!event_handle->manual) {
-               event_handle->set_count = 1;
-               mono_w32handle_set_signal_state (handle, TRUE, FALSE);
-       } else {
-               mono_w32handle_set_signal_state (handle, TRUE, TRUE);
-
-               thr_ret = mono_w32handle_unlock_handle (handle);
-               g_assert (thr_ret == 0);
-
-               /* For a manual-reset event, we're about to try and get the handle
-                * lock again, so give other threads a chance */
-               sched_yield ();
-
-               /* Reset the handle signal state */
-
-               /* I'm not sure whether or not we need a barrier here to make sure
-                * that all threads waiting on the event have proceeded. Currently
-                * we rely on broadcasting a condition. */
-
-               thr_ret = mono_w32handle_lock_handle (handle);
-               g_assert (thr_ret == 0);
-
-               mono_w32handle_set_signal_state (handle, FALSE, FALSE);
-       }
-
-       thr_ret = mono_w32handle_unlock_handle (handle);
-       g_assert (thr_ret == 0);
-
-       return TRUE;
-}
-
-/**
- * ResetEvent:
- * @handle: The event handle.
- *
- * Resets the event handle @handle to the unsignalled state.
- *
- * Return value: %TRUE on success, %FALSE otherwise.  (Currently only
- * ever returns %TRUE).
- */
-gboolean ResetEvent(gpointer handle)
-{
-       MonoW32HandleType type;
-       struct _WapiHandle_event *event_handle;
-       int thr_ret;
-
-       SetLastError (ERROR_SUCCESS);
-       
-       if (handle == NULL) {
-               SetLastError (ERROR_INVALID_HANDLE);
-               return(FALSE);
-       }
-       
-       switch (type = mono_w32handle_get_type (handle)) {
-       case MONO_W32HANDLE_EVENT:
-       case MONO_W32HANDLE_NAMEDEVENT:
-               break;
-       default:
-               SetLastError (ERROR_INVALID_HANDLE);
-               return FALSE;
-       }
-
-       if (!mono_w32handle_lookup (handle, type, (gpointer *)&event_handle)) {
-               g_warning ("%s: error looking up %s handle %p",
-                       __func__, event_handle_type_to_string (type), handle);
-               return FALSE;
-       }
-
-       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: resetting %s handle %p",
-               __func__, event_handle_type_to_string (type), handle);
-
-       thr_ret = mono_w32handle_lock_handle (handle);
-       g_assert (thr_ret == 0);
-
-       if (!mono_w32handle_issignalled (handle)) {
-               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: no need to reset %s handle %p",
-                       __func__, event_handle_type_to_string (type), handle);
-       } else {
-               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: obtained write lock on %s handle %p",
-                       __func__, event_handle_type_to_string (type), handle);
-
-               mono_w32handle_set_signal_state (handle, FALSE, FALSE);
-       }
-
-       event_handle->set_count = 0;
-
-       thr_ret = mono_w32handle_unlock_handle (handle);
-       g_assert (thr_ret == 0);
-
-       return TRUE;
-}
-
-/**
- * SetEvent:
- * @handle: The event handle
- *
- * Sets the event handle @handle to the signalled state.
- *
- * If @handle is a manual reset event, it remains signalled until it
- * is reset with ResetEvent().  An auto reset event remains signalled
- * until a single thread has waited for it, at which time @handle is
- * automatically reset to unsignalled.
- *
- * Return value: %TRUE on success, %FALSE otherwise.  (Currently only
- * ever returns %TRUE).
- */
-gboolean SetEvent(gpointer handle)
-{
-       MonoW32HandleType type;
-       struct _WapiHandle_event *event_handle;
-       int thr_ret;
-       
-       if (handle == NULL) {
-               SetLastError (ERROR_INVALID_HANDLE);
-               return(FALSE);
-       }
-       
-       switch (type = mono_w32handle_get_type (handle)) {
-       case MONO_W32HANDLE_EVENT:
-       case MONO_W32HANDLE_NAMEDEVENT:
-               break;
-       default:
-               SetLastError (ERROR_INVALID_HANDLE);
-               return FALSE;
-       }
-
-       if (!mono_w32handle_lookup (handle, type, (gpointer *)&event_handle)) {
-               g_warning ("%s: error looking up %s handle %p",
-                       __func__, event_handle_type_to_string (type), handle);
-               return FALSE;
-       }
-
-       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: setting %s handle %p",
-               __func__, event_handle_type_to_string (type), handle);
-
-       thr_ret = mono_w32handle_lock_handle (handle);
-       g_assert (thr_ret == 0);
-
-       if (!event_handle->manual) {
-               event_handle->set_count = 1;
-               mono_w32handle_set_signal_state (handle, TRUE, FALSE);
-       } else {
-               mono_w32handle_set_signal_state (handle, TRUE, TRUE);
-       }
-
-       thr_ret = mono_w32handle_unlock_handle (handle);
-       g_assert (thr_ret == 0);
-
-       return TRUE;
-}
-
-gpointer OpenEvent (guint32 access G_GNUC_UNUSED, gboolean inherit G_GNUC_UNUSED, const gunichar2 *name)
-{
-       gpointer handle;
-       gchar *utf8_name;
-       int thr_ret;
-
-       /* w32 seems to guarantee that opening named objects can't
-        * race each other
-        */
-       thr_ret = _wapi_namespace_lock ();
-       g_assert (thr_ret == 0);
-
-       utf8_name = g_utf16_to_utf8 (name, -1, NULL, NULL, NULL);
-       
-       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Opening named event [%s]", __func__, utf8_name);
-       
-       handle = _wapi_search_handle_namespace (MONO_W32HANDLE_NAMEDEVENT,
-                                               utf8_name);
-       if (handle == INVALID_HANDLE_VALUE) {
-               /* The name has already been used for a different
-                * object.
-                */
-               SetLastError (ERROR_INVALID_HANDLE);
-               goto cleanup;
-       } else if (!handle) {
-               /* This name doesn't exist */
-               SetLastError (ERROR_FILE_NOT_FOUND);    /* yes, really */
-               goto cleanup;
-       }
-
-       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: returning named event handle %p", __func__, handle);
-
-cleanup:
-       g_free (utf8_name);
-
-       _wapi_namespace_unlock (NULL);
-       
-       return handle;
-
-}
diff --git a/mono/io-layer/events.h b/mono/io-layer/events.h
deleted file mode 100644 (file)
index 577f57b..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * events.h:  Event handles
- *
- * Author:
- *     Dick Porter (dick@ximian.com)
- *
- * (C) 2002 Ximian, Inc.
- */
-
-#ifndef _WAPI_EVENTS_H_
-#define _WAPI_EVENTS_H_
-
-#include <glib.h>
-
-G_BEGIN_DECLS
-
-extern gpointer CreateEvent (WapiSecurityAttributes *security, gboolean manual,
-                            gboolean initial, const gunichar2 *name);
-extern gboolean PulseEvent (gpointer handle);
-extern gboolean ResetEvent (gpointer handle);
-extern gboolean SetEvent (gpointer handle);
-extern gpointer OpenEvent (guint32 access, gboolean inherit,
-                          const gunichar2 *name);
-
-G_END_DECLS
-
-#endif /* _WAPI_EVENTS_H_ */
index 496efa70bf2c349b406ddb0a722b5e6f5f57a18a..661067dc7b27b1461c9ee63858da5c519e0256f2 100644 (file)
  * 4MB array.
  */
 static GHashTable *file_share_hash;
-static mono_mutex_t file_share_hash_mutex;
-
-#define file_share_hash_lock() mono_os_mutex_lock (&file_share_hash_mutex)
-#define file_share_hash_unlock() mono_os_mutex_unlock (&file_share_hash_mutex)
+static mono_mutex_t file_share_mutex;
 
 static void
 _wapi_handle_share_release (_WapiFileShare *share_info)
 {
-       int thr_ret;
+       /* Prevent new entries racing with us */
+       mono_os_mutex_lock (&file_share_mutex);
 
        g_assert (share_info->handle_refs > 0);
-       
-       /* Prevent new entries racing with us */
-       thr_ret = _wapi_shm_sem_lock (_WAPI_SHARED_SEM_FILESHARE);
-       g_assert(thr_ret == 0);
+       share_info->handle_refs -= 1;
 
-       if (InterlockedDecrement ((gint32 *)&share_info->handle_refs) == 0) {
-               file_share_hash_lock ();
+       if (share_info->handle_refs == 0)
                g_hash_table_remove (file_share_hash, share_info);
-               file_share_hash_unlock ();
-       }
 
-       thr_ret = _wapi_shm_sem_unlock (_WAPI_SHARED_SEM_FILESHARE);
-       g_assert (thr_ret == 0);
+       mono_os_mutex_unlock (&file_share_mutex);
 }
 
 static gint
@@ -101,12 +92,10 @@ _wapi_handle_get_or_set_share (guint64 device, guint64 inode, guint32 new_sharem
        guint32 *old_sharemode, guint32 *old_access, struct _WapiFileShare **share_info)
 {
        struct _WapiFileShare *file_share;
-       int thr_ret;
        gboolean exists = FALSE;
 
        /* Prevent new entries racing with us */
-       thr_ret = _wapi_shm_sem_lock (_WAPI_SHARED_SEM_FILESHARE);
-       g_assert (thr_ret == 0);
+       mono_os_mutex_lock (&file_share_mutex);
 
        _WapiFileShare tmp;
 
@@ -115,23 +104,21 @@ _wapi_handle_get_or_set_share (guint64 device, guint64 inode, guint32 new_sharem
         * info. This is needed even if SHM is disabled, to track sharing inside
         * the current process.
         */
-       if (!file_share_hash) {
+       if (!file_share_hash)
                file_share_hash = g_hash_table_new_full (wapi_share_info_hash, wapi_share_info_equal, NULL, g_free);
-               mono_os_mutex_init_recursive (&file_share_hash_mutex);
-       }
 
        tmp.device = device;
        tmp.inode = inode;
 
-       file_share_hash_lock ();
-
        file_share = (_WapiFileShare *)g_hash_table_lookup (file_share_hash, &tmp);
        if (file_share) {
                *old_sharemode = file_share->sharemode;
                *old_access = file_share->access;
                *share_info = file_share;
 
-               InterlockedIncrement ((gint32 *)&file_share->handle_refs);
+               g_assert (file_share->handle_refs > 0);
+               file_share->handle_refs += 1;
+
                exists = TRUE;
        } else {
                file_share = g_new0 (_WapiFileShare, 1);
@@ -147,10 +134,7 @@ _wapi_handle_get_or_set_share (guint64 device, guint64 inode, guint32 new_sharem
                g_hash_table_insert (file_share_hash, file_share, file_share);
        }
 
-       file_share_hash_unlock ();
-       
-       thr_ret = _wapi_shm_sem_unlock (_WAPI_SHARED_SEM_FILESHARE);
-       g_assert (thr_ret == 0);
+       mono_os_mutex_unlock (&file_share_mutex);
 
        return(exists);
 }
@@ -2038,7 +2022,7 @@ write_file (int src_fd, int dest_fd, struct stat *st_src, gboolean report_errors
        MonoThreadInfo *info = mono_thread_info_current ();
 
        buf_size = buf_size < 8192 ? 8192 : (buf_size > 65536 ? 65536 : buf_size);
-       buf = (char *) malloc (buf_size);
+       buf = (char *) g_malloc (buf_size);
 
        for (;;) {
                remain = read (src_fd, buf, buf_size);
@@ -2049,7 +2033,7 @@ write_file (int src_fd, int dest_fd, struct stat *st_src, gboolean report_errors
                        if (report_errors)
                                _wapi_set_last_error_from_errno ();
 
-                       free (buf);
+                       g_free (buf);
                        return FALSE;
                }
                if (remain == 0) {
@@ -2065,7 +2049,7 @@ write_file (int src_fd, int dest_fd, struct stat *st_src, gboolean report_errors
                                if (report_errors)
                                        _wapi_set_last_error_from_errno ();
                                MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: write failed.", __func__);
-                               free (buf);
+                               g_free (buf);
                                return FALSE;
                        }
 
@@ -2074,7 +2058,7 @@ write_file (int src_fd, int dest_fd, struct stat *st_src, gboolean report_errors
                }
        }
 
-       free (buf);
+       g_free (buf);
        return TRUE ;
 }
 
@@ -4435,6 +4419,7 @@ void
 _wapi_io_init (void)
 {
        mono_os_mutex_init (&stdhandle_mutex);
+       mono_os_mutex_init (&file_share_mutex);
 
        mono_w32handle_register_ops (MONO_W32HANDLE_FILE,    &_wapi_file_ops);
        mono_w32handle_register_ops (MONO_W32HANDLE_CONSOLE, &_wapi_console_ops);
@@ -4453,8 +4438,8 @@ _wapi_io_init (void)
 void
 _wapi_io_cleanup (void)
 {
-       if (file_share_hash) {
+       mono_os_mutex_destroy (&file_share_mutex);
+
+       if (file_share_hash)
                g_hash_table_destroy (file_share_hash);
-               mono_os_mutex_destroy (&file_share_hash_mutex);
-       }
 }
diff --git a/mono/io-layer/mutex-private.h b/mono/io-layer/mutex-private.h
deleted file mode 100644 (file)
index 50e5b14..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * mutex-private.h:  Private definitions for mutex handles
- *
- * Author:
- *     Dick Porter (dick@ximian.com)
- *
- * (C) 2002 Ximian, Inc.
- */
-
-#ifndef _WAPI_MUTEX_PRIVATE_H_
-#define _WAPI_MUTEX_PRIVATE_H_
-
-#include <config.h>
-#include <glib.h>
-#include <pthread.h>
-#include <sys/types.h>
-
-#include "wapi-private.h"
-
-struct _WapiHandle_mutex
-{
-       pthread_t tid;
-       guint32 recursion;
-};
-
-struct _WapiHandle_namedmutex 
-{
-       struct _WapiHandle_mutex m;
-       WapiSharedNamespace sharedns;
-};
-
-void
-_wapi_mutex_init (void);
-
-#endif /* _WAPI_MUTEX_PRIVATE_H_ */
diff --git a/mono/io-layer/mutexes.c b/mono/io-layer/mutexes.c
deleted file mode 100644 (file)
index dbfe8b1..0000000
+++ /dev/null
@@ -1,507 +0,0 @@
-/*
- * mutexes.c:  Mutex handles
- *
- * Author:
- *     Dick Porter (dick@ximian.com)
- *
- * (C) 2002-2006 Ximian, Inc.
- */
-
-#include <config.h>
-#include <glib.h>
-#include <pthread.h>
-#include <string.h>
-#include <unistd.h>
-
-#include <mono/io-layer/wapi.h>
-#include <mono/io-layer/wapi-private.h>
-#include <mono/io-layer/mutex-private.h>
-#include <mono/io-layer/io-trace.h>
-#include <mono/utils/mono-once.h>
-#include <mono/utils/mono-logger-internals.h>
-#include <mono/utils/w32handle.h>
-
-static void mutex_signal(gpointer handle);
-static gboolean mutex_own (gpointer handle);
-static gboolean mutex_is_owned (gpointer handle);
-static void mutex_prewait (gpointer handle);
-static void mutex_details (gpointer data);
-static const gchar* mutex_typename (void);
-static gsize mutex_typesize (void);
-
-static void namedmutex_signal (gpointer handle);
-static gboolean namedmutex_own (gpointer handle);
-static gboolean namedmutex_is_owned (gpointer handle);
-static void namedmutex_prewait (gpointer handle);
-static void namedmutex_details (gpointer data);
-static const gchar* namedmutex_typename (void);
-static gsize namedmutex_typesize (void);
-
-static MonoW32HandleOps _wapi_mutex_ops = {
-       NULL,                   /* close */
-       mutex_signal,           /* signal */
-       mutex_own,              /* own */
-       mutex_is_owned,         /* is_owned */
-       NULL,                   /* special_wait */
-       mutex_prewait,                  /* prewait */
-       mutex_details,  /* details */
-       mutex_typename, /* typename */
-       mutex_typesize, /* typesize */
-};
-
-static MonoW32HandleOps _wapi_namedmutex_ops = {
-       NULL,                   /* close */
-       namedmutex_signal,      /* signal */
-       namedmutex_own,         /* own */
-       namedmutex_is_owned,    /* is_owned */
-       NULL,                   /* special_wait */
-       namedmutex_prewait,     /* prewait */
-       namedmutex_details,     /* details */
-       namedmutex_typename,    /* typename */
-       namedmutex_typesize,    /* typesize */
-};
-
-void
-_wapi_mutex_init (void)
-{
-       mono_w32handle_register_ops (MONO_W32HANDLE_MUTEX,      &_wapi_mutex_ops);
-       mono_w32handle_register_ops (MONO_W32HANDLE_NAMEDMUTEX, &_wapi_namedmutex_ops);
-
-       mono_w32handle_register_capabilities (MONO_W32HANDLE_MUTEX,
-               (MonoW32HandleCapability)(MONO_W32HANDLE_CAP_WAIT | MONO_W32HANDLE_CAP_SIGNAL | MONO_W32HANDLE_CAP_OWN));
-       mono_w32handle_register_capabilities (MONO_W32HANDLE_NAMEDMUTEX,
-               (MonoW32HandleCapability)(MONO_W32HANDLE_CAP_WAIT | MONO_W32HANDLE_CAP_SIGNAL | MONO_W32HANDLE_CAP_OWN));
-}
-
-static const char* mutex_handle_type_to_string (MonoW32HandleType type)
-{
-       switch (type) {
-       case MONO_W32HANDLE_MUTEX: return "mutex";
-       case MONO_W32HANDLE_NAMEDMUTEX: return "named mutex";
-       default:
-               g_assert_not_reached ();
-       }
-}
-
-static gboolean
-mutex_handle_own (gpointer handle, MonoW32HandleType type)
-{
-       struct _WapiHandle_mutex *mutex_handle;
-
-       if (!mono_w32handle_lookup (handle, type, (gpointer *)&mutex_handle)) {
-               g_warning ("%s: error looking up %s handle %p", __func__, mutex_handle_type_to_string (type), handle);
-               return FALSE;
-       }
-
-       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: owning %s handle %p, tid %p, recursion %u",
-               __func__, mutex_handle_type_to_string (type), handle, (gpointer) mutex_handle->tid, mutex_handle->recursion);
-
-       mono_thread_info_own_mutex (mono_thread_info_current (), handle);
-
-       mutex_handle->tid = pthread_self ();
-       mutex_handle->recursion++;
-
-       mono_w32handle_set_signal_state (handle, FALSE, FALSE);
-
-       return TRUE;
-}
-
-static gboolean
-mutex_handle_is_owned (gpointer handle, MonoW32HandleType type)
-{
-       struct _WapiHandle_mutex *mutex_handle;
-
-       if (!mono_w32handle_lookup (handle, type, (gpointer *)&mutex_handle)) {
-               g_warning ("%s: error looking up %s handle %p", __func__, mutex_handle_type_to_string (type), handle);
-               return FALSE;
-       }
-
-       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: testing ownership %s handle %p",
-               __func__, mutex_handle_type_to_string (type), handle);
-
-       if (mutex_handle->recursion > 0 && pthread_equal (mutex_handle->tid, pthread_self ())) {
-               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: %s handle %p owned by %p",
-                       __func__, mutex_handle_type_to_string (type), handle, (gpointer) pthread_self ());
-               return TRUE;
-       } else {
-               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: %s handle %p not owned by %p, but locked %d times by %p",
-                       __func__, mutex_handle_type_to_string (type), handle, (gpointer) pthread_self (), mutex_handle->recursion, (gpointer) mutex_handle->tid);
-               return FALSE;
-       }
-}
-
-static void mutex_signal(gpointer handle)
-{
-       ReleaseMutex(handle);
-}
-
-static gboolean mutex_own (gpointer handle)
-{
-       return mutex_handle_own (handle, MONO_W32HANDLE_MUTEX);
-}
-
-static gboolean mutex_is_owned (gpointer handle)
-{
-       
-       return mutex_handle_is_owned (handle, MONO_W32HANDLE_MUTEX);
-}
-
-static void namedmutex_signal (gpointer handle)
-{
-       ReleaseMutex(handle);
-}
-
-/* NB, always called with the shared handle lock held */
-static gboolean namedmutex_own (gpointer handle)
-{
-       return mutex_handle_own (handle, MONO_W32HANDLE_NAMEDMUTEX);
-}
-
-static gboolean namedmutex_is_owned (gpointer handle)
-{
-       return mutex_handle_is_owned (handle, MONO_W32HANDLE_NAMEDMUTEX);
-}
-
-static void mutex_handle_prewait (gpointer handle, MonoW32HandleType type)
-{
-       /* If the mutex is not currently owned, do nothing and let the
-        * usual wait carry on.  If it is owned, check that the owner
-        * is still alive; if it isn't we override the previous owner
-        * and assume that process exited abnormally and failed to
-        * clean up.
-        */
-       struct _WapiHandle_mutex *mutex_handle;
-
-       if (!mono_w32handle_lookup (handle, type, (gpointer *)&mutex_handle)) {
-               g_warning ("%s: error looking up %s handle %p",
-                       __func__, mutex_handle_type_to_string (type), handle);
-               return;
-       }
-
-       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: pre-waiting %s handle %p, owned? %s",
-               __func__, mutex_handle_type_to_string (type), handle, mutex_handle->recursion != 0 ? "true" : "false");
-}
-
-/* The shared state is not locked when prewait methods are called */
-static void mutex_prewait (gpointer handle)
-{
-       mutex_handle_prewait (handle, MONO_W32HANDLE_MUTEX);
-}
-
-/* The shared state is not locked when prewait methods are called */
-static void namedmutex_prewait (gpointer handle)
-{
-       mutex_handle_prewait (handle, MONO_W32HANDLE_NAMEDMUTEX);
-}
-
-static void mutex_details (gpointer data)
-{
-       struct _WapiHandle_mutex *mut = (struct _WapiHandle_mutex *)data;
-       
-#ifdef PTHREAD_POINTER_ID
-       g_print ("own: %5p, count: %5u", mut->tid, mut->recursion);
-#else
-       g_print ("own: %5ld, count: %5u", mut->tid, mut->recursion);
-#endif
-}
-
-static void namedmutex_details (gpointer data)
-{
-       struct _WapiHandle_namedmutex *namedmut = (struct _WapiHandle_namedmutex *)data;
-       
-#ifdef PTHREAD_POINTER_ID
-       g_print ("own: %5p, count: %5u, name: \"%s\"",
-               namedmut->m.tid, namedmut->m.recursion, namedmut->sharedns.name);
-#else
-       g_print ("own: %5ld, count: %5u, name: \"%s\"",
-               namedmut->m.tid, namedmut->m.recursion, namedmut->sharedns.name);
-#endif
-}
-
-static const gchar* mutex_typename (void)
-{
-       return "Mutex";
-}
-
-static gsize mutex_typesize (void)
-{
-       return sizeof (struct _WapiHandle_mutex);
-}
-
-static const gchar* namedmutex_typename (void)
-{
-       return "N.Mutex";
-}
-
-static gsize namedmutex_typesize (void)
-{
-       return sizeof (struct _WapiHandle_namedmutex);
-}
-
-/* When a thread exits, any mutexes it still holds need to be signalled. */
-void wapi_mutex_abandon (gpointer handle, pid_t pid, pthread_t tid)
-{
-       MonoW32HandleType type;
-       struct _WapiHandle_mutex *mutex_handle;
-       int thr_ret;
-
-       switch (type = mono_w32handle_get_type (handle)) {
-       case MONO_W32HANDLE_MUTEX:
-       case MONO_W32HANDLE_NAMEDMUTEX:
-               break;
-       default:
-               g_assert_not_reached ();
-       }
-
-       if (!mono_w32handle_lookup (handle, type, (gpointer *)&mutex_handle)) {
-               g_warning ("%s: error looking up %s handle %p",
-                       __func__, mutex_handle_type_to_string (type), handle);
-               return;
-       }
-
-       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: abandon %s handle %p",
-               __func__, mutex_handle_type_to_string (type), handle);
-
-       thr_ret = mono_w32handle_lock_handle (handle);
-       g_assert (thr_ret == 0);
-
-       if (pthread_equal (mutex_handle->tid, tid)) {
-               mutex_handle->recursion = 0;
-               mutex_handle->tid = 0;
-
-               mono_w32handle_set_signal_state (handle, TRUE, FALSE);
-
-               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: abandoned %s handle %p",
-                       __func__, mutex_handle_type_to_string (type), handle);
-       }
-
-       thr_ret = mono_w32handle_unlock_handle (handle);
-       g_assert (thr_ret == 0);
-}
-
-static gpointer mutex_handle_create (struct _WapiHandle_mutex *mutex_handle, MonoW32HandleType type, gboolean owned)
-{
-       gpointer handle;
-       int thr_ret;
-
-       mutex_handle->tid = 0;
-       mutex_handle->recursion = 0;
-
-       handle = mono_w32handle_new (type, mutex_handle);
-       if (handle == INVALID_HANDLE_VALUE) {
-               g_warning ("%s: error creating %s handle",
-                       __func__, mutex_handle_type_to_string (type));
-               SetLastError (ERROR_GEN_FAILURE);
-               return NULL;
-       }
-
-       thr_ret = mono_w32handle_lock_handle (handle);
-       g_assert (thr_ret == 0);
-
-       if (owned)
-               mutex_handle_own (handle, type);
-       else
-               mono_w32handle_set_signal_state (handle, TRUE, FALSE);
-
-       thr_ret = mono_w32handle_unlock_handle (handle);
-       g_assert (thr_ret == 0);
-
-       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: created %s handle %p",
-               __func__, mutex_handle_type_to_string (type), handle);
-
-       return handle;
-}
-
-static gpointer mutex_create (gboolean owned)
-{
-       struct _WapiHandle_mutex mutex_handle;
-       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: creating %s handle",
-               __func__, mutex_handle_type_to_string (MONO_W32HANDLE_MUTEX));
-       return mutex_handle_create (&mutex_handle, MONO_W32HANDLE_MUTEX, owned);
-}
-
-static gpointer namedmutex_create (gboolean owned, const gunichar2 *name)
-{
-       gpointer handle;
-       gchar *utf8_name;
-       int thr_ret;
-
-       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: creating %s handle",
-               __func__, mutex_handle_type_to_string (MONO_W32HANDLE_NAMEDMUTEX));
-
-       /* w32 seems to guarantee that opening named objects can't race each other */
-       thr_ret = _wapi_namespace_lock ();
-       g_assert (thr_ret == 0);
-
-       utf8_name = g_utf16_to_utf8 (name, -1, NULL, NULL, NULL);
-
-       handle = _wapi_search_handle_namespace (MONO_W32HANDLE_NAMEDMUTEX, utf8_name);
-       if (handle == INVALID_HANDLE_VALUE) {
-               /* The name has already been used for a different object. */
-               handle = NULL;
-               SetLastError (ERROR_INVALID_HANDLE);
-       } else if (handle) {
-               /* Not an error, but this is how the caller is informed that the mutex wasn't freshly created */
-               SetLastError (ERROR_ALREADY_EXISTS);
-
-               /* this is used as creating a new handle */
-               mono_w32handle_ref (handle);
-       } else {
-               /* A new named mutex */
-               struct _WapiHandle_namedmutex namedmutex_handle;
-
-               strncpy (&namedmutex_handle.sharedns.name [0], utf8_name, MAX_PATH);
-               namedmutex_handle.sharedns.name [MAX_PATH] = '\0';
-
-               handle = mutex_handle_create ((struct _WapiHandle_mutex*) &namedmutex_handle, MONO_W32HANDLE_NAMEDMUTEX, owned);
-       }
-
-       g_free (utf8_name);
-
-       thr_ret = _wapi_namespace_unlock (NULL);
-       g_assert (thr_ret == 0);
-
-       return handle;
-}
-
-/**
- * CreateMutex:
- * @security: Ignored for now.
- * @owned: If %TRUE, the mutex is created with the calling thread
- * already owning the mutex.
- * @name:Pointer to a string specifying the name of this mutex, or
- * %NULL.
- *
- * Creates a new mutex handle.  A mutex is signalled when no thread
- * owns it.  A thread acquires ownership of the mutex by waiting for
- * it with WaitForSingleObject() or WaitForMultipleObjects().  A
- * thread relinquishes ownership with ReleaseMutex().
- *
- * A thread that owns a mutex can specify the same mutex in repeated
- * wait function calls without blocking.  The thread must call
- * ReleaseMutex() an equal number of times to release the mutex.
- *
- * Return value: A new handle, or %NULL on error.
- */
-gpointer CreateMutex(WapiSecurityAttributes *security G_GNUC_UNUSED, gboolean owned, const gunichar2 *name)
-{
-       /* Need to blow away any old errors here, because code tests
-        * for ERROR_ALREADY_EXISTS on success (!) to see if a mutex
-        * was freshly created */
-       SetLastError (ERROR_SUCCESS);
-
-       return name ? namedmutex_create (owned, name) : mutex_create (owned);
-}
-
-/**
- * ReleaseMutex:
- * @handle: The mutex handle.
- *
- * Releases ownership if the mutex handle @handle.
- *
- * Return value: %TRUE on success, %FALSE otherwise.  This function
- * fails if the calling thread does not own the mutex @handle.
- */
-gboolean ReleaseMutex(gpointer handle)
-{
-       MonoW32HandleType type;
-       struct _WapiHandle_mutex *mutex_handle;
-       pthread_t tid;
-       int thr_ret;
-       gboolean ret;
-
-       if (handle == NULL) {
-               SetLastError (ERROR_INVALID_HANDLE);
-               return FALSE;
-       }
-
-       switch (type = mono_w32handle_get_type (handle)) {
-       case MONO_W32HANDLE_MUTEX:
-       case MONO_W32HANDLE_NAMEDMUTEX:
-               break;
-       default:
-               SetLastError (ERROR_INVALID_HANDLE);
-               return FALSE;
-       }
-
-       if (!mono_w32handle_lookup (handle, type, (gpointer *)&mutex_handle)) {
-               g_warning ("%s: error looking up %s handle %p",
-                       __func__, mutex_handle_type_to_string (type), handle);
-               return FALSE;
-       }
-
-       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: releasing %s handle %p",
-               __func__, mutex_handle_type_to_string (type), handle);
-
-       thr_ret = mono_w32handle_lock_handle (handle);
-       g_assert (thr_ret == 0);
-
-       tid = pthread_self ();
-
-       if (!pthread_equal (mutex_handle->tid, tid)) {
-               ret = FALSE;
-
-               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: we don't own %s handle %p (owned by %ld, me %ld)",
-                       __func__, mutex_handle_type_to_string (type), handle, mutex_handle->tid, tid);
-       } else {
-               ret = TRUE;
-
-               /* OK, we own this mutex */
-               mutex_handle->recursion--;
-
-               if (mutex_handle->recursion == 0) {
-                       mono_thread_info_disown_mutex (mono_thread_info_current (), handle);
-
-                       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: unlocking %s handle %p",
-                               __func__, mutex_handle_type_to_string (type), handle);
-
-                       mutex_handle->tid = 0;
-                       mono_w32handle_set_signal_state (handle, TRUE, FALSE);
-               }
-       }
-
-       thr_ret = mono_w32handle_unlock_handle (handle);
-       g_assert (thr_ret == 0);
-
-       return ret;
-}
-
-gpointer OpenMutex (guint32 access G_GNUC_UNUSED, gboolean inherit G_GNUC_UNUSED, const gunichar2 *name)
-{
-       gpointer handle;
-       gchar *utf8_name;
-       int thr_ret;
-
-       /* w32 seems to guarantee that opening named objects can't
-        * race each other
-        */
-       thr_ret = _wapi_namespace_lock ();
-       g_assert (thr_ret == 0);
-
-       utf8_name = g_utf16_to_utf8 (name, -1, NULL, NULL, NULL);
-       
-       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Opening named mutex [%s]", __func__, utf8_name);
-       
-       handle = _wapi_search_handle_namespace (MONO_W32HANDLE_NAMEDMUTEX,
-                                               utf8_name);
-       if (handle == INVALID_HANDLE_VALUE) {
-               /* The name has already been used for a different
-                * object.
-                */
-               SetLastError (ERROR_INVALID_HANDLE);
-               goto cleanup;
-       } else if (!handle) {
-               /* This name doesn't exist */
-               SetLastError (ERROR_FILE_NOT_FOUND);    /* yes, really */
-               goto cleanup;
-       }
-
-       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: returning named mutex handle %p", __func__, handle);
-
-cleanup:
-       g_free (utf8_name);
-
-       _wapi_namespace_unlock (NULL);
-       
-       return handle;
-}
diff --git a/mono/io-layer/mutexes.h b/mono/io-layer/mutexes.h
deleted file mode 100644 (file)
index d1b7a68..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * mutexes.h: Mutex handles
- *
- * Author:
- *     Dick Porter (dick@ximian.com)
- *
- * (C) 2002 Ximian, Inc.
- */
-
-#ifndef _WAPI_MUTEXES_H_
-#define _WAPI_MUTEXES_H_
-
-#include <glib.h>
-
-#include <pthread.h>
-
-G_BEGIN_DECLS
-
-extern gpointer CreateMutex (WapiSecurityAttributes *security, gboolean owned,
-                            const gunichar2 *name);
-extern gboolean ReleaseMutex (gpointer handle);
-extern gpointer OpenMutex (guint32 access, gboolean inherit,
-                          const gunichar2 *name);
-
-void
-wapi_mutex_abandon (gpointer data, pid_t pid, pthread_t tid);
-
-G_END_DECLS
-
-#endif /* _WAPI_MUTEXES_H_ */
index 654c43771ebd5b4ad8e3bb421b227e61cca5dba0..35cd67eb5c0d60435aad18ee1a774c2ee52f94b9 100644 (file)
@@ -1476,7 +1476,7 @@ static int load_modules_callback (struct dl_phdr_info *info, size_t size, void *
            + sizeof (info->dlpi_phnum))
                return (-1);
 
-       struct dl_phdr_info *cpy = calloc(1, sizeof(struct dl_phdr_info));
+       struct dl_phdr_info *cpy = g_calloc (1, sizeof(struct dl_phdr_info));
        if (!cpy)
                return (-1);
 
@@ -1512,7 +1512,7 @@ static GSList *load_modules (void)
                MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: inode=%d, filename=%s, address_start=%p, address_end=%p", __func__,
                                   mod->inode, mod->filename, mod->address_start, mod->address_end);
 
-               free(info);
+               g_free (info);
 
                if (g_slist_find_custom (ret, mod, find_procmodule) == NULL) {
                        ret = g_slist_prepend (ret, mod);
@@ -1911,12 +1911,12 @@ get_process_name_from_proc (pid_t pid)
        if (sysctl(mib, 4, NULL, &size, NULL, 0) < 0)
                return(ret);
 
-       if ((pi = malloc(size)) == NULL)
+       if ((pi = g_malloc (size)) == NULL)
                return(ret);
 
        if (sysctl (mib, 4, pi, &size, NULL, 0) < 0) {
                if (errno == ENOMEM) {
-                       free(pi);
+                       g_free (pi);
                        MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Didn't allocate enough memory for kproc info", __func__);
                }
                return(ret);
@@ -1925,7 +1925,7 @@ get_process_name_from_proc (pid_t pid)
        if (strlen (pi->kp_proc.p_comm) > 0)
                ret = g_strdup (pi->kp_proc.p_comm);
 
-       free(pi);
+       g_free (pi);
 #endif
 #elif defined(USE_BSD_LOADER)
 #if defined(__FreeBSD__)
@@ -1938,12 +1938,12 @@ get_process_name_from_proc (pid_t pid)
                return(ret);
        }
 
-       if ((pi = malloc(size)) == NULL)
+       if ((pi = g_malloc (size)) == NULL)
                return(ret);
 
        if (sysctl (mib, 4, pi, &size, NULL, 0) < 0) {
                if (errno == ENOMEM) {
-                       free(pi);
+                       g_free (pi);
                        MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Didn't allocate enough memory for kproc info", __func__);
                }
                return(ret);
@@ -1951,7 +1951,7 @@ get_process_name_from_proc (pid_t pid)
 
        if (strlen (pi->ki_comm) > 0)
                ret = g_strdup (pi->ki_comm);
-       free(pi);
+       g_free (pi);
 #elif defined(__OpenBSD__)
        mib [0] = CTL_KERN;
        mib [1] = KERN_PROC;
@@ -1966,7 +1966,7 @@ retry:
                return(ret);
        }
 
-       if ((pi = malloc(size)) == NULL)
+       if ((pi = g_malloc (size)) == NULL)
                return(ret);
 
        mib[5] = (int)(size / sizeof(struct kinfo_proc));
@@ -1974,7 +1974,7 @@ retry:
        if ((sysctl (mib, 6, pi, &size, NULL, 0) < 0) ||
                (size != sizeof (struct kinfo_proc))) {
                if (errno == ENOMEM) {
-                       free(pi);
+                       g_free (pi);
                        goto retry;
                }
                return(ret);
@@ -1983,7 +1983,7 @@ retry:
        if (strlen (pi->p_comm) > 0)
                ret = g_strdup (pi->p_comm);
 
-       free(pi);
+       g_free (pi);
 #endif
 #elif defined(USE_HAIKU_LOADER)
        image_info imageInfo;
index 3193bc58731a248858f96506a52c25fd1d34b09d..c4da3eceee1b54378d22bcca0c7675f6624cb081 100644 (file)
@@ -130,7 +130,6 @@ struct _WapiShellExecuteInfo
        
 #define DEBUG_PROCESS 0x00000001
 #define DEBUG_ONLY_THIS_PROCESS 0x00000002
-#define CREATE_SUSPENDED 0x00000004
 #define DETACHED_PROCESS 0x00000008
 #define CREATE_NEW_CONSOLE 0x00000010
 #define NORMAL_PRIORITY_CLASS 0x00000020
diff --git a/mono/io-layer/semaphore-private.h b/mono/io-layer/semaphore-private.h
deleted file mode 100644 (file)
index 3c27eef..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * semaphore-private.h:  Private definitions for semaphore handles
- *
- * Author:
- *     Dick Porter (dick@ximian.com)
- *
- * (C) 2002 Ximian, Inc.
- */
-
-#ifndef _WAPI_SEMAPHORE_PRIVATE_H_
-#define _WAPI_SEMAPHORE_PRIVATE_H_
-
-#include <config.h>
-#include <glib.h>
-
-#include "wapi-private.h"
-
-/* emulate sem_t, so that we can prod the internal state more easily */
-struct _WapiHandle_sem
-{
-       guint32 val;
-       gint32 max;
-};
-
-struct _WapiHandle_namedsem
-{
-       struct _WapiHandle_sem s;
-       WapiSharedNamespace sharedns;
-};
-
-void
-_wapi_semaphore_init (void);
-
-#endif /* _WAPI_SEMAPHORE_PRIVATE_H_ */
diff --git a/mono/io-layer/semaphores.c b/mono/io-layer/semaphores.c
deleted file mode 100644 (file)
index c473f4d..0000000
+++ /dev/null
@@ -1,399 +0,0 @@
-/*
- * semaphores.c:  Semaphore handles
- *
- * Author:
- *     Dick Porter (dick@ximian.com)
- *
- * (C) 2002 Ximian, Inc.
- */
-
-#include <config.h>
-#include <glib.h>
-#include <pthread.h>
-#ifdef HAVE_SEMAPHORE_H
-#include <semaphore.h>
-#endif
-#include <errno.h>
-#include <string.h>
-#include <sys/time.h>
-
-#include <mono/io-layer/wapi.h>
-#include <mono/io-layer/wapi-private.h>
-#include <mono/io-layer/semaphore-private.h>
-#include <mono/io-layer/io-trace.h>
-#include <mono/utils/mono-once.h>
-#include <mono/utils/mono-logger-internals.h>
-#include <mono/utils/w32handle.h>
-
-static void sema_signal(gpointer handle);
-static gboolean sema_own (gpointer handle);
-static void sema_details (gpointer data);
-static const gchar* sema_typename (void);
-static gsize sema_typesize (void);
-
-static void namedsema_signal (gpointer handle);
-static gboolean namedsema_own (gpointer handle);
-static void namedsema_details (gpointer data);
-static const gchar* namedsema_typename (void);
-static gsize namedsema_typesize (void);
-
-static MonoW32HandleOps _wapi_sem_ops = {
-       NULL,                   /* close */
-       sema_signal,            /* signal */
-       sema_own,               /* own */
-       NULL,                   /* is_owned */
-       NULL,                   /* special_wait */
-       NULL,                   /* prewait */
-       sema_details,   /* details */
-       sema_typename,  /* typename */
-       sema_typesize,  /* typesize */
-};
-
-static MonoW32HandleOps _wapi_namedsem_ops = {
-       NULL,                   /* close */
-       namedsema_signal,       /* signal */
-       namedsema_own,          /* own */
-       NULL,                   /* is_owned */
-       NULL,                   /* special_wait */
-       NULL,                   /* prewait */
-       namedsema_details,      /* details */
-       namedsema_typename,     /* typename */
-       namedsema_typesize,     /* typesize */
-};
-
-void
-_wapi_semaphore_init (void)
-{
-       mono_w32handle_register_ops (MONO_W32HANDLE_SEM,      &_wapi_sem_ops);
-       mono_w32handle_register_ops (MONO_W32HANDLE_NAMEDSEM, &_wapi_namedsem_ops);
-
-       mono_w32handle_register_capabilities (MONO_W32HANDLE_SEM,
-               (MonoW32HandleCapability)(MONO_W32HANDLE_CAP_WAIT | MONO_W32HANDLE_CAP_SIGNAL));
-       mono_w32handle_register_capabilities (MONO_W32HANDLE_NAMEDSEM,
-               (MonoW32HandleCapability)(MONO_W32HANDLE_CAP_WAIT | MONO_W32HANDLE_CAP_SIGNAL));
-}
-
-static const char* sem_handle_type_to_string (MonoW32HandleType type)
-{
-       switch (type) {
-       case MONO_W32HANDLE_SEM: return "sem";
-       case MONO_W32HANDLE_NAMEDSEM: return "named sem";
-       default:
-               g_assert_not_reached ();
-       }
-}
-
-static gboolean sem_handle_own (gpointer handle, MonoW32HandleType type)
-{
-       struct _WapiHandle_sem *sem_handle;
-
-       if (!mono_w32handle_lookup (handle, type, (gpointer *)&sem_handle)) {
-               g_warning ("%s: error looking up %s handle %p",
-                       __func__, sem_handle_type_to_string (type), handle);
-               return FALSE;
-       }
-
-       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: owning %s handle %p",
-               __func__, sem_handle_type_to_string (type), handle);
-
-       sem_handle->val--;
-
-       if (sem_handle->val == 0)
-               mono_w32handle_set_signal_state (handle, FALSE, FALSE);
-
-       return TRUE;
-}
-
-static void sema_signal(gpointer handle)
-{
-       ReleaseSemaphore(handle, 1, NULL);
-}
-
-static gboolean sema_own (gpointer handle)
-{
-       return sem_handle_own (handle, MONO_W32HANDLE_SEM);
-}
-
-static void namedsema_signal (gpointer handle)
-{
-       ReleaseSemaphore (handle, 1, NULL);
-}
-
-/* NB, always called with the shared handle lock held */
-static gboolean namedsema_own (gpointer handle)
-{
-       return sem_handle_own (handle, MONO_W32HANDLE_NAMEDSEM);
-}
-
-static void sema_details (gpointer data)
-{
-       struct _WapiHandle_sem *sem = (struct _WapiHandle_sem *)data;
-       g_print ("val: %5u, max: %5d", sem->val, sem->max);
-}
-
-static void namedsema_details (gpointer data)
-{
-       struct _WapiHandle_namedsem *namedsem = (struct _WapiHandle_namedsem *)data;
-       g_print ("val: %5u, max: %5d, name: \"%s\"", namedsem->s.val, namedsem->s.max, namedsem->sharedns.name);
-}
-
-static const gchar* sema_typename (void)
-{
-       return "Semaphore";
-}
-
-static gsize sema_typesize (void)
-{
-       return sizeof (struct _WapiHandle_sem);
-}
-
-static const gchar* namedsema_typename (void)
-{
-       return "N.Semaphore";
-}
-
-static gsize namedsema_typesize (void)
-{
-       return sizeof (struct _WapiHandle_namedsem);
-}
-
-static gpointer sem_handle_create (struct _WapiHandle_sem *sem_handle, MonoW32HandleType type, gint32 initial, gint32 max)
-{
-       gpointer handle;
-       int thr_ret;
-
-       sem_handle->val = initial;
-       sem_handle->max = max;
-
-       handle = mono_w32handle_new (type, sem_handle);
-       if (handle == INVALID_HANDLE_VALUE) {
-               g_warning ("%s: error creating %s handle",
-                       __func__, sem_handle_type_to_string (type));
-               SetLastError (ERROR_GEN_FAILURE);
-               return NULL;
-       }
-
-       thr_ret = mono_w32handle_lock_handle (handle);
-       g_assert (thr_ret == 0);
-
-       if (initial != 0)
-               mono_w32handle_set_signal_state (handle, TRUE, FALSE);
-
-       thr_ret = mono_w32handle_unlock_handle (handle);
-       g_assert (thr_ret == 0);
-
-       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: created %s handle %p",
-               __func__, sem_handle_type_to_string (type), handle);
-
-       return handle;
-}
-
-static gpointer sem_create (gint32 initial, gint32 max)
-{
-       struct _WapiHandle_sem sem_handle;
-       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: creating %s handle, initial %d max %d",
-               __func__, sem_handle_type_to_string (MONO_W32HANDLE_SEM), initial, max);
-       return sem_handle_create (&sem_handle, MONO_W32HANDLE_SEM, initial, max);
-}
-
-static gpointer namedsem_create (gint32 initial, gint32 max, const gunichar2 *name)
-{
-       gpointer handle;
-       gchar *utf8_name;
-       int thr_ret;
-
-       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: creating %s handle, initial %d max %d name \"%s\"",
-               __func__, sem_handle_type_to_string (MONO_W32HANDLE_NAMEDSEM), initial, max, name);
-
-       /* w32 seems to guarantee that opening named objects can't race each other */
-       thr_ret = _wapi_namespace_lock ();
-       g_assert (thr_ret == 0);
-
-       utf8_name = g_utf16_to_utf8 (name, -1, NULL, NULL, NULL);
-
-       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Creating named sem name [%s] initial %d max %d", __func__, utf8_name, initial, max);
-
-       handle = _wapi_search_handle_namespace (MONO_W32HANDLE_NAMEDSEM, utf8_name);
-       if (handle == INVALID_HANDLE_VALUE) {
-               /* The name has already been used for a different object. */
-               handle = NULL;
-               SetLastError (ERROR_INVALID_HANDLE);
-       } else if (handle) {
-               /* Not an error, but this is how the caller is informed that the semaphore wasn't freshly created */
-               SetLastError (ERROR_ALREADY_EXISTS);
-
-               /* this is used as creating a new handle */
-               mono_w32handle_ref (handle);
-       } else {
-               /* A new named semaphore */
-               struct _WapiHandle_namedsem namedsem_handle;
-
-               strncpy (&namedsem_handle.sharedns.name [0], utf8_name, MAX_PATH);
-               namedsem_handle.sharedns.name [MAX_PATH] = '\0';
-
-               handle = sem_handle_create ((struct _WapiHandle_sem*) &namedsem_handle, MONO_W32HANDLE_NAMEDSEM, initial, max);
-       }
-
-       g_free (utf8_name);
-
-       thr_ret = _wapi_namespace_unlock (NULL);
-       g_assert (thr_ret == 0);
-
-       return handle;
-}
-
-
-/**
- * CreateSemaphore:
- * @security: Ignored for now.
- * @initial: The initial count for the semaphore.  The value must be
- * greater than or equal to zero, and less than or equal to @max.
- * @max: The maximum count for this semaphore.  The value must be
- * greater than zero.
- * @name: Pointer to a string specifying the name of this semaphore,
- * or %NULL.  Currently ignored.
- *
- * Creates a new semaphore handle.  A semaphore is signalled when its
- * count is greater than zero, and unsignalled otherwise.  The count
- * is decreased by one whenever a wait function releases a thread that
- * was waiting for the semaphore.  The count is increased by calling
- * ReleaseSemaphore().
- *
- * Return value: a new handle, or NULL
- */
-gpointer CreateSemaphore(WapiSecurityAttributes *security G_GNUC_UNUSED, gint32 initial, gint32 max, const gunichar2 *name)
-{
-       if (max <= 0) {
-               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: max <= 0", __func__);
-
-               SetLastError (ERROR_INVALID_PARAMETER);
-               return(NULL);
-       }
-       
-       if (initial > max || initial < 0) {
-               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: initial>max or < 0", __func__);
-
-               SetLastError (ERROR_INVALID_PARAMETER);
-               return(NULL);
-       }
-
-       /* Need to blow away any old errors here, because code tests
-        * for ERROR_ALREADY_EXISTS on success (!) to see if a
-        * semaphore was freshly created
-        */
-       SetLastError (ERROR_SUCCESS);
-
-       return name ? namedsem_create (initial, max, name) : sem_create (initial, max);
-}
-
-/**
- * ReleaseSemaphore:
- * @handle: The semaphore handle to release.
- * @count: The amount by which the semaphore's count should be
- * increased.
- * @prevcount: Pointer to a location to store the previous count of
- * the semaphore, or %NULL.
- *
- * Increases the count of semaphore @handle by @count.
- *
- * Return value: %TRUE on success, %FALSE otherwise.
- */
-gboolean ReleaseSemaphore(gpointer handle, gint32 count, gint32 *prevcount)
-{
-       MonoW32HandleType type;
-       struct _WapiHandle_sem *sem_handle;
-       int thr_ret;
-       gboolean ret;
-
-       if (!handle) {
-               SetLastError (ERROR_INVALID_HANDLE);
-               return FALSE;
-       }
-
-       switch (type = mono_w32handle_get_type (handle)) {
-       case MONO_W32HANDLE_SEM:
-       case MONO_W32HANDLE_NAMEDSEM:
-               break;
-       default:
-               SetLastError (ERROR_INVALID_HANDLE);
-               return FALSE;
-       }
-
-       if (!mono_w32handle_lookup (handle, type, (gpointer *)&sem_handle)) {
-               g_warning ("%s: error looking up sem handle %p", __func__, handle);
-               return FALSE;
-       }
-
-       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: releasing %s handle %p",
-               __func__, sem_handle_type_to_string (type), handle);
-
-       thr_ret = mono_w32handle_lock_handle (handle);
-       g_assert (thr_ret == 0);
-
-       /* Do this before checking for count overflow, because overflowing
-        * max is a listed technique for finding the current value */
-       if (prevcount)
-               *prevcount = sem_handle->val;
-
-       /* No idea why max is signed, but thats the spec :-( */
-       if (sem_handle->val + count > (guint32)sem_handle->max) {
-               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: %s handle %p val %d count %d max %d, max value would be exceeded",
-                       __func__, sem_handle_type_to_string (type), handle, sem_handle->val, count, sem_handle->max, count);
-
-               ret = FALSE;
-       } else {
-               MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: %s handle %p val %d count %d max %d",
-                       __func__, sem_handle_type_to_string (type), handle, sem_handle->val, count, sem_handle->max, count);
-
-               sem_handle->val += count;
-               mono_w32handle_set_signal_state (handle, TRUE, TRUE);
-
-               ret = TRUE;
-       }
-
-       thr_ret = mono_w32handle_unlock_handle (handle);
-       g_assert (thr_ret == 0);
-
-       return ret;
-}
-
-gpointer OpenSemaphore (guint32 access G_GNUC_UNUSED, gboolean inherit G_GNUC_UNUSED,
-                       const gunichar2 *name)
-{
-       gpointer handle;
-       gchar *utf8_name;
-       int thr_ret;
-
-       /* w32 seems to guarantee that opening named objects can't
-        * race each other
-        */
-       thr_ret = _wapi_namespace_lock ();
-       g_assert (thr_ret == 0);
-       
-       utf8_name = g_utf16_to_utf8 (name, -1, NULL, NULL, NULL);
-       
-       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Opening named sem [%s]", __func__, utf8_name);
-
-       handle = _wapi_search_handle_namespace (MONO_W32HANDLE_NAMEDSEM,
-                                               utf8_name);
-       if (handle == INVALID_HANDLE_VALUE) {
-               /* The name has already been used for a different
-                * object.
-                */
-               SetLastError (ERROR_INVALID_HANDLE);
-               goto cleanup;
-       } else if (!handle) {
-               /* This name doesn't exist */
-               SetLastError (ERROR_FILE_NOT_FOUND);    /* yes, really */
-               goto cleanup;
-       }
-
-       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: returning named sem handle %p", __func__, handle);
-
-cleanup:
-       g_free (utf8_name);
-       
-       _wapi_namespace_unlock (NULL);
-       
-       return handle;
-}
diff --git a/mono/io-layer/semaphores.h b/mono/io-layer/semaphores.h
deleted file mode 100644 (file)
index 1cdaee0..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * semaphores.h:  Semaphore handles
- *
- * Author:
- *     Dick Porter (dick@ximian.com)
- *
- * (C) 2002 Ximian, Inc.
- */
-
-#ifndef _WAPI_SEMAPHORES_H_
-#define _WAPI_SEMAPHORES_H_
-
-#include <glib.h>
-
-G_BEGIN_DECLS
-
-extern gpointer CreateSemaphore(WapiSecurityAttributes *security,
-                               gint32 initial, gint32 max,
-                               const gunichar2 *name);
-extern gboolean ReleaseSemaphore(gpointer handle, gint32 count,
-                                gint32 *prevcount);
-extern gpointer OpenSemaphore (guint32 access, gboolean inherit,
-                              const gunichar2 *name);
-
-G_END_DECLS
-#endif /* _WAPI_SEMAPHORES_H_ */
diff --git a/mono/io-layer/shared.c b/mono/io-layer/shared.c
deleted file mode 100644 (file)
index 8fb0e27..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * shared.c:  Shared memory handling, and daemon launching
- *
- * Author:
- *     Dick Porter (dick@ximian.com)
- *
- * (C) 2002-2006 Novell, Inc.
- */
-
-#include <config.h>
-#include <glib.h>
-
-#include <mono/io-layer/wapi-private.h>
-#include <mono/io-layer/shared.h>
-#include <mono/utils/mono-os-mutex.h>
-
-#define DEBUGLOG(...)
-//#define DEBUGLOG(...) g_message(__VA_ARGS__);
-
-static mono_mutex_t noshm_sems[_WAPI_SHARED_SEM_COUNT];
-
-void
-_wapi_shm_semaphores_init (void)
-{
-       int i;
-       for (i = 0; i < _WAPI_SHARED_SEM_COUNT; i++) 
-               mono_os_mutex_init (&noshm_sems [i]);
-}
-
-int
-_wapi_shm_sem_lock (int sem)
-{
-       DEBUGLOG ("%s: locking nosem %d", __func__, sem);
-       mono_os_mutex_lock (&noshm_sems[sem]);
-       return 0;
-}
-
-int
-_wapi_shm_sem_trylock (int sem)
-{
-       DEBUGLOG ("%s: trying to lock nosem %d", __func__, sem);
-       return mono_os_mutex_trylock (&noshm_sems[sem]);
-}
-
-int
-_wapi_shm_sem_unlock (int sem)
-{
-       DEBUGLOG ("%s: unlocking nosem %d", __func__, sem);
-       mono_os_mutex_unlock (&noshm_sems[sem]);
-       return 0;
-}
diff --git a/mono/io-layer/shared.h b/mono/io-layer/shared.h
deleted file mode 100644 (file)
index 204f506..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * shared.h:  Shared memory handle, and daemon launching
- *
- * Author:
- *     Dick Porter (dick@ximian.com)
- *
- * (C) 2002-2006 Novell, Inc.
- */
-
-#ifndef _WAPI_SHARED_H_
-#define _WAPI_SHARED_H_
-
-extern void _wapi_shm_semaphores_init (void);
-extern int _wapi_shm_sem_lock (int sem);
-extern int _wapi_shm_sem_trylock (int sem);
-extern int _wapi_shm_sem_unlock (int sem);
-
-#endif /* _WAPI_SHARED_H_ */
index ee961002d9eec7152e3741e77299836cab989d14..8b82b609d1976be0cf356e0d13904f970aa8b585 100644 (file)
@@ -16,7 +16,6 @@
 
 #include <mono/io-layer/wapi.h>
 #include <mono/io-layer/io.h>
-#include <mono/io-layer/shared.h>
 
 #include <mono/utils/mono-os-mutex.h>
 
 
 extern gboolean _wapi_has_shut_down;
 
-typedef struct 
-{
-       gchar name[MAX_PATH + 1];
-} WapiSharedNamespace;
-
-#include <mono/io-layer/event-private.h>
 #include <mono/io-layer/io-private.h>
-#include <mono/io-layer/mutex-private.h>
-#include <mono/io-layer/semaphore-private.h>
 #include <mono/io-layer/socket-private.h>
 #include <mono/io-layer/process-private.h>
 #include <mono/utils/w32handle.h>
@@ -46,13 +37,6 @@ struct _WapiHandle_shared_ref
        guint32 offset;
 };
 
-#define _WAPI_SHARED_SEM_NAMESPACE 0
-/*#define _WAPI_SHARED_SEM_COLLECTION 1*/
-#define _WAPI_SHARED_SEM_FILESHARE 2
-#define _WAPI_SHARED_SEM_PROCESS_COUNT_LOCK 6
-#define _WAPI_SHARED_SEM_PROCESS_COUNT 7
-#define _WAPI_SHARED_SEM_COUNT 8       /* Leave some future expansion space */
-
 struct _WapiFileShare
 {
 #ifdef WAPI_FILE_SHARE_PLATFORM_EXTRA_DATA
@@ -69,18 +53,4 @@ struct _WapiFileShare
 
 typedef struct _WapiFileShare _WapiFileShare;
 
-gpointer
-_wapi_search_handle_namespace (MonoW32HandleType type, gchar *utf8_name);
-
-static inline int _wapi_namespace_lock (void)
-{
-       return(_wapi_shm_sem_lock (_WAPI_SHARED_SEM_NAMESPACE));
-}
-
-/* This signature makes it easier to use in pthread cleanup handlers */
-static inline int _wapi_namespace_unlock (gpointer data G_GNUC_UNUSED)
-{
-       return(_wapi_shm_sem_unlock (_WAPI_SHARED_SEM_NAMESPACE));
-}
-
 #endif /* _WAPI_PRIVATE_H_ */
index 8f8b4ff549d87ad0e142368bf773277c4e5351d7..935d257722557872189afa90b439e60a2d57ff99 100644 (file)
 #define SetLastError wapi_SetLastError
 #define TransmitFile wapi_TransmitFile
 #define GetThreadContext wapi_GetThreadContext
-#define CreateEvent wapi_CreateEvent 
-#define PulseEvent wapi_PulseEvent 
-#define ResetEvent wapi_ResetEvent 
-#define SetEvent wapi_SetEvent 
-#define OpenEvent wapi_OpenEvent 
 #define CloseHandle wapi_CloseHandle 
 #define DuplicateHandle wapi_DuplicateHandle 
 #define CreateFile wapi_CreateFile
@@ -57,9 +52,6 @@
 #define UnlockFile wapi_UnlockFile 
 #define GetVolumeInformation wapi_GetVolumeInformation 
 #define FormatMessage wapi_FormatMessage 
-#define CreateMutex wapi_CreateMutex 
-#define ReleaseMutex wapi_ReleaseMutex 
-#define OpenMutex wapi_OpenMutex 
 #define ShellExecuteEx wapi_ShellExecuteEx 
 #define CreateProcess wapi_CreateProcess 
 #define CreateProcessWithLogonW wapi_CreateProcessWithLogonW 
@@ -80,9 +72,6 @@
 #define SetPriorityClass wapi_SetPriorityClass 
 #define ImpersonateLoggedOnUser wapi_ImpersonateLoggedOnUser 
 #define RevertToSelf wapi_RevertToSelf 
-#define CreateSemaphore wapi_CreateSemaphore
-#define ReleaseSemaphore wapi_ReleaseSemaphore
-#define OpenSemaphore wapi_OpenSemaphore 
 #define WSASetLastError wapi_WSASetLastError
 #define WSAGetLastError wapi_WSAGetLastError
 #define WSAIoctl wapi_WSAIoctl 
index a9f93692400dbc03c96557e20ef08fc86a7aa793..f1674179d9a194f0d2dcb4d992acbf5bb6926d3c 100644 (file)
@@ -1,13 +1,9 @@
 
 #include "wapi.h"
 
-#include "event-private.h"
 #include "io-trace.h"
 #include "io.h"
-#include "mutex-private.h"
 #include "process-private.h"
-#include "semaphore-private.h"
-#include "shared.h"
 #include "socket-private.h"
 
 #include "mono/utils/mono-lazy-init.h"
@@ -18,12 +14,8 @@ gboolean _wapi_has_shut_down = FALSE;
 void
 wapi_init (void)
 {
-       _wapi_shm_semaphores_init ();
        _wapi_io_init ();
        _wapi_processes_init ();
-       _wapi_semaphore_init ();
-       _wapi_mutex_init ();
-       _wapi_event_init ();
        _wapi_socket_init ();
 }
 
@@ -57,82 +49,6 @@ wapi_getpid (void)
        return _wapi_pid;
 }
 
-static gboolean
-_WAPI_SHARED_NAMESPACE (MonoW32HandleType type)
-{
-       switch (type) {
-       case MONO_W32HANDLE_NAMEDMUTEX:
-       case MONO_W32HANDLE_NAMEDSEM:
-       case MONO_W32HANDLE_NAMEDEVENT:
-               return TRUE;
-       default:
-               return FALSE;
-       }
-}
-
-typedef struct {
-       gpointer ret;
-       MonoW32HandleType type;
-       gchar *utf8_name;
-} _WapiSearchHandleNamespaceData;
-
-static gboolean mono_w32handle_search_namespace_callback (gpointer handle, gpointer data, gpointer user_data)
-{
-       _WapiSearchHandleNamespaceData *search_data;
-       MonoW32HandleType type;
-       WapiSharedNamespace *sharedns;
-
-       type = mono_w32handle_get_type (handle);
-       if (!_WAPI_SHARED_NAMESPACE (type))
-               return FALSE;
-
-       search_data = (_WapiSearchHandleNamespaceData*) user_data;
-
-       switch (type) {
-       case MONO_W32HANDLE_NAMEDMUTEX: sharedns = &((struct _WapiHandle_namedmutex*) data)->sharedns; break;
-       case MONO_W32HANDLE_NAMEDSEM:   sharedns = &((struct _WapiHandle_namedsem*)   data)->sharedns; break;
-       case MONO_W32HANDLE_NAMEDEVENT: sharedns = &((struct _WapiHandle_namedevent*) data)->sharedns; break;
-       default:
-               g_assert_not_reached ();
-       }
-
-       if (strcmp (sharedns->name, search_data->utf8_name) == 0) {
-               if (type != search_data->type) {
-                       /* Its the wrong type, so fail now */
-                       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p matches name but is wrong type: %s",
-                               __func__, handle, mono_w32handle_ops_typename (type));
-                       search_data->ret = INVALID_HANDLE_VALUE;
-               } else {
-                       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p matches name and type",
-                               __func__, handle);
-                       search_data->ret = handle;
-               }
-
-               return TRUE;
-       }
-
-       return FALSE;
-}
-
-/* Returns the offset of the metadata array, or INVALID_HANDLE_VALUE on error, or NULL for
- * not found
- */
-gpointer _wapi_search_handle_namespace (MonoW32HandleType type, gchar *utf8_name)
-{
-       _WapiSearchHandleNamespaceData search_data;
-
-       g_assert(_WAPI_SHARED_NAMESPACE(type));
-
-       MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Lookup for handle named [%s] type %s",
-               __func__, utf8_name, mono_w32handle_ops_typename (type));
-
-       search_data.ret = NULL;
-       search_data.type = type;
-       search_data.utf8_name = utf8_name;
-       mono_w32handle_foreach (mono_w32handle_search_namespace_callback, &search_data);
-       return search_data.ret;
-}
-
 /* Lots more to implement here, but this is all we need at the moment */
 gboolean
 DuplicateHandle (gpointer srcprocess, gpointer src, gpointer targetprocess, gpointer *target,
index 4e0a688063984ad671543a10f51a4bc2d27290c7..c56622ea91c003c548288148cf8c49f9998c22bd 100644 (file)
 #include <mono/io-layer/access.h>
 #include <mono/io-layer/context.h>
 #include <mono/io-layer/error.h>
-#include <mono/io-layer/events.h>
 #include <mono/io-layer/messages.h>
-#include <mono/io-layer/mutexes.h>
 #include <mono/io-layer/processes.h>
 #include <mono/io-layer/security.h>
-#include <mono/io-layer/semaphores.h>
 #include <mono/io-layer/sockets.h>
 #include <mono/io-layer/status.h>
 #include <mono/io-layer/timefuncs.h>
index 88864821be44d394939dd5d19a9c87239eee38f7..013b778a86579d088ef71551af526cffb572b192 100644 (file)
@@ -267,11 +267,11 @@ globextend(const gchar *path, wapi_glob_t *pglob, size_t *limitp)
 
        newsize = sizeof(*pathv) * (2 + pglob->gl_pathc + pglob->gl_offs);
        /* FIXME: Can just use realloc(). */
-       pathv = (char **)(pglob->gl_pathv ? realloc((char *)pglob->gl_pathv, newsize) :
-           malloc(newsize));
+       pathv = (char **)(pglob->gl_pathv ? g_realloc ((char *)pglob->gl_pathv, newsize) :
+           g_malloc (newsize));
        if (pathv == NULL) {
                if (pglob->gl_pathv) {
-                       free(pglob->gl_pathv);
+                       g_free (pglob->gl_pathv);
                        pglob->gl_pathv = NULL;
                }
                return(WAPI_GLOB_NOSPACE);
@@ -291,7 +291,7 @@ globextend(const gchar *path, wapi_glob_t *pglob, size_t *limitp)
        *limitp += len;
        if ((copy = (char *)malloc(len)) != NULL) {
                if (g_Ctoc(path, copy, len)) {
-                       free(copy);
+                       g_free (copy);
                        return(WAPI_GLOB_NOSPACE);
                }
                pathv[pglob->gl_offs + pglob->gl_pathc++] = copy;
@@ -361,8 +361,8 @@ _wapi_globfree(wapi_glob_t *pglob)
                pp = pglob->gl_pathv + pglob->gl_offs;
                for (i = pglob->gl_pathc; i--; ++pp)
                        if (*pp)
-                               free(*pp);
-               free(pglob->gl_pathv);
+                               g_free (*pp);
+               g_free (pglob->gl_pathv);
                pglob->gl_pathv = NULL;
        }
 }
index f49dde50193159d9d0525370300142fe2551b50c..f19773b6a2ffa8e1c1bafb1ea9a866b3b7e049c2 100644 (file)
@@ -1,6 +1,9 @@
 if HOST_WIN32
 win32_sources = \
-       console-win32.c
+       console-win32.c \
+       w32mutex-win32.c \
+       w32semaphore-win32.c \
+       w32event-win32.c
 
 platform_sources = $(win32_sources)
 
@@ -23,7 +26,10 @@ else
 assembliesdir = $(exec_prefix)/lib
 confdir = $(sysconfdir)
 unix_sources = \
-       console-unix.c
+       console-unix.c \
+       w32mutex-unix.c \
+       w32semaphore-unix.c \
+       w32event-unix.c
 
 platform_sources = $(unix_sources)
 endif
@@ -217,8 +223,12 @@ common_sources = \
        seq-points-data.h       \
        seq-points-data.c       \
        handle.c        \
-       handle.h
-
+       handle.h        \
+       w32mutex.h      \
+       w32semaphore.h  \
+       w32event.h      \
+       w32handle-namespace.h   \
+       w32handle-namespace.c
 
 # These source files have compile time dependencies on GC code
 gc_dependent_sources = \
index bc214cc92e2f598e3a6d5f62e5b8d1e88448dadb..174b4c9f28b285009c4ef3e353d8ee56c370c8c7 100644 (file)
@@ -83,7 +83,7 @@
  * Changes which are already detected at runtime, like the addition
  * of icalls, do not require an increment.
  */
-#define MONO_CORLIB_VERSION 153
+#define MONO_CORLIB_VERSION 155
 
 typedef struct
 {
@@ -2530,7 +2530,6 @@ mono_domain_try_unload (MonoDomain *domain, MonoObject **exc)
        unload_data *thread_data;
        MonoNativeThreadId tid;
        MonoDomain *caller_domain = mono_domain_get ();
-       MonoThreadParm tp;
 
        /* printf ("UNLOAD STARTING FOR %s (%p) IN THREAD 0x%x.\n", domain->friendly_name, domain, mono_native_thread_id_get ()); */
 
@@ -2587,24 +2586,23 @@ mono_domain_try_unload (MonoDomain *domain, MonoObject **exc)
         * First we create a separate thread for unloading, since
         * we might have to abort some threads, including the current one.
         */
-       tp.priority = MONO_THREAD_PRIORITY_NORMAL;
-       tp.stack_size = 0;
-       tp.creation_flags = CREATE_SUSPENDED;
-       thread_handle = mono_threads_create_thread (unload_thread_main, thread_data, &tp, &tid);
+       thread_handle = mono_threads_create_thread (unload_thread_main, thread_data, 0, &tid);
        if (thread_handle == NULL)
                return;
-       mono_thread_info_resume (tid);
 
        /* Wait for the thread */       
        while (!thread_data->done && guarded_wait (thread_handle, INFINITE, TRUE) == WAIT_IO_COMPLETION) {
                if (mono_thread_internal_has_appdomain_ref (mono_thread_internal_current (), domain) && (mono_thread_interruption_requested ())) {
                        /* The unload thread tries to abort us */
                        /* The icall wrapper will execute the abort */
+                       mono_threads_close_thread_handle (thread_handle);
                        unload_data_unref (thread_data);
                        return;
                }
        }
 
+       mono_threads_close_thread_handle (thread_handle);
+
        if (thread_data->failure_reason) {
                /* Roll back the state change */
                domain->state = MONO_APPDOMAIN_CREATED;
index 0744389c400bf4539c0d88f3e530df2a95436b6e..96025d9d06a775c5539634654ff4fedeb998bc18 100644 (file)
@@ -2355,11 +2355,11 @@ mono_assembly_name_parse_full (const char *name, MonoAssemblyName *aname, gboole
                        if (!g_ascii_strcasecmp (retargetable, "yes")) {
                                flags |= ASSEMBLYREF_RETARGETABLE_FLAG;
                        } else if (g_ascii_strcasecmp (retargetable, "no")) {
-                               free (retargetable_uq);
+                               g_free (retargetable_uq);
                                goto cleanup_and_fail;
                        }
 
-                       free (retargetable_uq);
+                       g_free (retargetable_uq);
                        tmp++;
                        continue;
                }
@@ -2379,11 +2379,11 @@ mono_assembly_name_parse_full (const char *name, MonoAssemblyName *aname, gboole
                        else if (!g_ascii_strcasecmp (procarch, "AMD64"))
                                arch = MONO_PROCESSOR_ARCHITECTURE_AMD64;
                        else {
-                               free (procarch_uq);
+                               g_free (procarch_uq);
                                goto cleanup_and_fail;
                        }
 
-                       free (procarch_uq);
+                       g_free (procarch_uq);
                        tmp++;
                        continue;
                }
@@ -2411,11 +2411,11 @@ mono_assembly_name_parse_full (const char *name, MonoAssemblyName *aname, gboole
                key_uq == NULL ? key : key_uq,
                flags, arch, aname, save_public_key);
 
-       free (dllname_uq);
-       free (version_uq);
-       free (culture_uq);
-       free (token_uq);
-       free (key_uq);
+       g_free (dllname_uq);
+       g_free (version_uq);
+       g_free (culture_uq);
+       g_free (token_uq);
+       g_free (key_uq);
 
        g_strfreev (parts);
        return res;
index 4372397aa5740f6fae868ffabf4ce2ce6bea96de..ea7fa289a3899b91b7917f21311f394b2726788f 100644 (file)
@@ -475,17 +475,12 @@ transport_send (int fd, guint8 *data, int len)
 static void
 transport_start_receive (void)
 {
-       MonoThreadParm tp;
-
        transport_connect ();
 
        if (!listen_fd)
                return;
 
-       tp.priority = MONO_THREAD_PRIORITY_NORMAL;
-       tp.stack_size = 0;
-       tp.creation_flags = 0;
-       receiver_thread_handle = mono_threads_create_thread (receiver_thread, NULL, &tp, NULL);
+       receiver_thread_handle = mono_threads_create_thread (receiver_thread, NULL, 0, NULL);
        g_assert (receiver_thread_handle);
 }
 
index de54bd07a4d97ebde27235f64988583de477ac8b..b62d6155f91e3bd40e6c204c16bfd1b4eb94143b 100644 (file)
@@ -771,7 +771,7 @@ typedef struct {
        size_t imt_slots_with_collisions;
        size_t imt_max_collisions_in_slot;
        size_t imt_method_count_when_max_collisions;
-       size_t imt_thunks_size;
+       size_t imt_trampolines_size;
        size_t jit_info_table_insert_count;
        size_t jit_info_table_remove_count;
        size_t jit_info_table_lookup_count;
index 500a87da63c77a146a2c5afd63e62a8d600ace00..575e6d07ed3fa18dfc87f960697f1c9567773cbb 100644 (file)
@@ -385,14 +385,14 @@ struct _MonoDomain {
        GHashTable         *generic_virtual_cases;
        MonoThunkFreeList **thunk_free_lists;
 
-       GHashTable     *generic_virtual_thunks;
+       GHashTable     *generic_virtual_trampolines;
 
        /* Information maintained by the JIT engine */
        gpointer runtime_info;
 
        /*thread pool jobs, used to coordinate shutdown.*/
        volatile int                    threadpool_jobs;
-       HANDLE                          cleanup_semaphore;
+       gpointer                                cleanup_semaphore;
        
        /* Contains the compiled runtime invoke wrapper used by finalizers */
        gpointer            finalize_runtime_invoke;
index 6cfd0dbbb9ea31c1a6ff8ba24d0db0e423381f01..b5d5a26d417c979511f47401c6512e34bfb579e0 100644 (file)
@@ -40,6 +40,9 @@
 #include <mono/metadata/mono-config.h>
 #include <mono/metadata/threads-types.h>
 #include <mono/metadata/runtime.h>
+#include <mono/metadata/w32mutex.h>
+#include <mono/metadata/w32semaphore.h>
+#include <mono/metadata/w32event.h>
 #include <metadata/threads.h>
 #include <metadata/profiler-private.h>
 #include <mono/metadata/coree.h>
@@ -179,7 +182,7 @@ lock_free_mempool_free (LockFreeMempool *mp)
        chunk = mp->chunks;
        while (chunk) {
                next = (LockFreeMempoolChunk *)chunk->prev;
-               mono_vfree (chunk, mono_pagesize ());
+               mono_vfree (chunk, mono_pagesize (), MONO_MEM_ACCOUNT_DOMAIN);
                chunk = next;
        }
        g_free (mp);
@@ -197,7 +200,7 @@ lock_free_mempool_chunk_new (LockFreeMempool *mp, int len)
        size = mono_pagesize ();
        while (size - sizeof (LockFreeMempoolChunk) < len)
                size += mono_pagesize ();
-       chunk = (LockFreeMempoolChunk *)mono_valloc (0, size, MONO_MMAP_READ|MONO_MMAP_WRITE);
+       chunk = (LockFreeMempoolChunk *)mono_valloc (0, size, MONO_MMAP_READ|MONO_MMAP_WRITE, MONO_MEM_ACCOUNT_DOMAIN);
        g_assert (chunk);
        chunk->mem = (guint8 *)ALIGN_PTR_TO ((char*)chunk + sizeof (LockFreeMempoolChunk), 16);
        chunk->size = ((char*)chunk + size) - (char*)chunk->mem;
@@ -526,9 +529,14 @@ mono_init_internal (const char *filename, const char *exe_filename, const char *
 
 #ifndef HOST_WIN32
        mono_w32handle_init ();
+       mono_w32handle_namespace_init ();
        wapi_init ();
 #endif
 
+       mono_w32mutex_init ();
+       mono_w32semaphore_init ();
+       mono_w32event_init ();
+
 #ifndef DISABLE_PERFCOUNTERS
        mono_perfcounters_init ();
 #endif
@@ -1250,9 +1258,9 @@ mono_domain_free (MonoDomain *domain, gboolean force)
                g_hash_table_destroy (domain->generic_virtual_cases);
                domain->generic_virtual_cases = NULL;
        }
-       if (domain->generic_virtual_thunks) {
-               g_hash_table_destroy (domain->generic_virtual_thunks);
-               domain->generic_virtual_thunks = NULL;
+       if (domain->generic_virtual_trampolines) {
+               g_hash_table_destroy (domain->generic_virtual_trampolines);
+               domain->generic_virtual_trampolines = NULL;
        }
        if (domain->ftnptrs_hash) {
                g_hash_table_destroy (domain->ftnptrs_hash);
index 09b498ab559bdeabe7fa97e88f6c76634f203809..02b738556c597c72fbc7ed9fe76a5acead5d97eb 100644 (file)
@@ -991,7 +991,7 @@ mono_exception_get_native_backtrace (MonoException *exc)
                }
        }
 
-       free (messages);
+       g_free (messages);
        return g_string_free (text, FALSE);
 #else
        return g_strdup ("");
index 76495a807d56109ecdb674f9158324052ee91916..102f9f4da7244fbb8aac1b0909d239bd1a49b190 100644 (file)
@@ -79,7 +79,7 @@ void mono_handle_stack_free (HandleStack *handlestack);
 MonoRawHandle mono_stack_mark_pop_value (MonoThreadInfo *info, HandleStackMark *stackmark, MonoRawHandle value);
 void mono_stack_mark_record_size (MonoThreadInfo *info, HandleStackMark *stackmark, const char *func_name);
 
-static void
+static inline void
 mono_stack_mark_init (MonoThreadInfo *info, HandleStackMark *stackmark)
 {
        HandleStack *handles = (HandleStack *)info->handle_stack;
@@ -87,7 +87,7 @@ mono_stack_mark_init (MonoThreadInfo *info, HandleStackMark *stackmark)
        stackmark->chunk = handles->top;
 }
 
-static void
+static inline void
 mono_stack_mark_pop (MonoThreadInfo *info, HandleStackMark *stackmark)
 {
        HandleStack *handles = (HandleStack *)info->handle_stack;
index b331969129c56a55224645737b08f9170aabb97f..6403f1975e91d48c89fe2a8b4a70a8d04940e351 100644 (file)
@@ -83,6 +83,9 @@
 #include <mono/metadata/file-mmap.h>
 #include <mono/metadata/seq-points-data.h>
 #include <mono/metadata/handle.h>
+#include <mono/metadata/w32mutex.h>
+#include <mono/metadata/w32semaphore.h>
+#include <mono/metadata/w32event.h>
 #include <mono/io-layer/io-layer.h>
 #include <mono/utils/monobitset.h>
 #include <mono/utils/mono-time.h>
@@ -6940,7 +6943,7 @@ ves_icall_System_Text_EncodingHelper_InternalCodePage (gint32 *int_code_page)
        
        if (strstr (codepage, "utf_8") != NULL)
                *int_code_page |= 0x10000000;
-       free (codepage);
+       g_free (codepage);
        
        if (want_name && *int_code_page == -1)
                return mono_string_new (mono_domain_get (), cset);
index 4f36ba3c82c11fd5f55a5e8e10866928fdf0a9a5..64e7d06e56ffdded117edf0dc1ebf5233ba48bfa 100644 (file)
@@ -2224,7 +2224,7 @@ mono_stack_walk_async_safe (MonoStackWalkAsyncSafe func, void *initial_sig_conte
        AsyncStackWalkUserData ud = { func, user_data };
 
        mono_sigctx_to_monoctx (initial_sig_context, &ctx);
-       mono_get_eh_callbacks ()->mono_walk_stack_with_ctx (async_stack_walk_adapter, NULL, MONO_UNWIND_SIGNAL_SAFE, &ud);
+       mono_get_eh_callbacks ()->mono_walk_stack_with_ctx (async_stack_walk_adapter, &ctx, MONO_UNWIND_SIGNAL_SAFE, &ud);
 }
 
 static gboolean
index bcb0dc3c0146748719a55c6a9002fc609a2c61b4..783b528339c41d84657ab7ae50fcd0b0eb5831b9 100644 (file)
@@ -434,7 +434,7 @@ get_darwin_locale (void)
                                        len += bytes_converted + 1;
                                }
 
-                               darwin_locale = (char *) malloc (len + 1);
+                               darwin_locale = (char *) g_malloc (len + 1);
                                CFStringGetBytes (locale_language, CFRangeMake (0, CFStringGetLength (locale_language)), kCFStringEncodingMacRoman, 0, FALSE, (UInt8 *) darwin_locale, len, &bytes_converted);
 
                                darwin_locale[bytes_converted] = '-';
@@ -454,9 +454,9 @@ get_darwin_locale (void)
 
                        if (locale_cfstr) {
                                len = CFStringGetMaximumSizeForEncoding (CFStringGetLength (locale_cfstr), kCFStringEncodingMacRoman) + 1;
-                               darwin_locale = (char *) malloc (len);
+                               darwin_locale = (char *) g_malloc (len);
                                if (!CFStringGetCString (locale_cfstr, darwin_locale, len, kCFStringEncodingMacRoman)) {
-                                       free (darwin_locale);
+                                       g_free (darwin_locale);
                                        CFRelease (locale);
                                        darwin_locale = NULL;
                                        return NULL;
index 5b290e74947ff5143a963c5a2e891c4d7d71fc3f..b457211c83da5d2ffd2116bae62c9acb98e4e408 100644 (file)
@@ -778,7 +778,7 @@ mono_free_lparray (MonoArray *array, gpointer* nativeArray)
        if (klass->element_class->byval_arg.type == MONO_TYPE_CLASS) {
                for(i = 0; i < array->max_length; ++i)
                        mono_marshal_free_ccw (mono_array_get (array, MonoObject*, i));
-               free(nativeArray);
+               g_free (nativeArray);
        }
 #endif
 }
index 6bf3410d818ec7115921f01c4e9c45dd27109e80..214c9e2128fd5349d51d9d9f46c6e542e9751db3 100644 (file)
@@ -215,7 +215,7 @@ mono_backtrace (int size)
         for (i = 1; i < symbols; ++i) {
                 g_print ("\t%s\n", names [i]);
         }
-        free (names);
+        g_free (names);
         mono_os_mutex_unlock (&mempool_tracing_lock);
 }
 
index ef01f3d5305c7d40fd2194627280ea832f174698..8b7418e9659e139dd21ba614910f4b2a9aea97e6 100644 (file)
@@ -26,6 +26,7 @@
 #include <mono/metadata/debug-helpers.h>
 #include <mono/metadata/tabledefs.h>
 #include <mono/metadata/marshal.h>
+#include <mono/metadata/w32event.h>
 #include <mono/utils/mono-threads.h>
 #include <mono/metadata/profiler-private.h>
 #include <mono/utils/mono-time.h>
@@ -877,7 +878,25 @@ retry_contended:
 #endif
        thread = mono_thread_internal_current ();
 
-       mono_thread_set_state (thread, ThreadState_WaitSleepJoin);
+       /*
+        * If we allow interruption, we check the test state for an abort request before going into sleep.
+        * This is a workaround to the fact that Thread.Abort does non-sticky interruption of semaphores.
+        *
+        * Semaphores don't support the sticky interruption with mono_thread_info_install_interrupt.
+        *
+        * A better fix would be to switch to wait with something that allows sticky interrupts together
+        * with wrapping it with abort_protected_block_count for the non-alertable cases.
+        * And somehow make this whole dance atomic and not crazy expensive. Good luck.
+        *
+        */
+       if (allow_interruption) {
+               if (!mono_thread_test_and_set_state (thread, (MonoThreadState)(ThreadState_StopRequested | ThreadState_AbortRequested), ThreadState_WaitSleepJoin)) {
+                       wait_ret = MONO_SEM_TIMEDWAIT_RET_ALERTED;
+                       goto done_waiting;
+               }
+       } else {
+               mono_thread_set_state (thread, ThreadState_WaitSleepJoin);
+       }
 
        /*
         * We pass ALERTABLE instead of allow_interruption since we have to check for the
@@ -886,7 +905,8 @@ retry_contended:
        wait_ret = mono_coop_sem_timedwait (mon->entry_sem, waitms, MONO_SEM_FLAGS_ALERTABLE);
 
        mono_thread_clr_state (thread, ThreadState_WaitSleepJoin);
-       
+
+done_waiting:
 #ifndef DISABLE_PERFCOUNTERS
        mono_perfcounters->thread_queue_len--;
 #endif
@@ -996,11 +1016,35 @@ mono_monitor_try_enter_internal (MonoObject *obj, guint32 ms, gboolean allow_int
 gboolean 
 mono_monitor_enter (MonoObject *obj)
 {
+       gint32 res;
+       gboolean allow_interruption = TRUE;
        if (G_UNLIKELY (!obj)) {
                mono_set_pending_exception (mono_get_exception_argument_null ("obj"));
                return FALSE;
        }
-       return mono_monitor_try_enter_internal (obj, INFINITE, FALSE) == 1;
+
+       /*
+        * An inquisitive mind could ask what's the deal with this loop.
+        * It exists to deal with interrupting a monitor enter that happened within an abort-protected block, like a .cctor.
+        *
+        * The thread will be set with a pending abort and the wait might even be interrupted. Either way, once we call mono_thread_interruption_checkpoint,
+        * it will return NULL meaning we can't be aborted right now. Once that happens we switch to non-alertable.
+        */
+       do {
+               res = mono_monitor_try_enter_internal (obj, INFINITE, allow_interruption);
+               /*This means we got interrupted during the wait and didn't got the monitor.*/
+               if (res == -1) {
+                       MonoException *exc = mono_thread_interruption_checkpoint ();
+                       if (exc) {
+                               mono_set_pending_exception (exc);
+                               return FALSE;
+                       } else {
+                               //we detected a pending interruption but it turned out to be a false positive, we ignore it from now on (this feels like a hack, right?, threads.c should give us less confusing directions)
+                               allow_interruption = FALSE;
+                       }
+               }
+       } while (res == -1);
+       return TRUE;
 }
 
 gboolean 
@@ -1083,18 +1127,22 @@ void
 ves_icall_System_Threading_Monitor_Monitor_try_enter_with_atomic_var (MonoObject *obj, guint32 ms, char *lockTaken)
 {
        gint32 res;
+       gboolean allow_interruption = TRUE;
        if (G_UNLIKELY (!obj)) {
                mono_set_pending_exception (mono_get_exception_argument_null ("obj"));
                return;
        }
        do {
-               res = mono_monitor_try_enter_internal (obj, ms, TRUE);
+               res = mono_monitor_try_enter_internal (obj, ms, allow_interruption);
                /*This means we got interrupted during the wait and didn't got the monitor.*/
                if (res == -1) {
                        MonoException *exc = mono_thread_interruption_checkpoint ();
                        if (exc) {
                                mono_set_pending_exception (exc);
                                return;
+                       } else {
+                               //we detected a pending interruption but it turned out to be a false positive, we ignore it from now on (this feels like a hack, right?, threads.c should give us less confusing directions)
+                               allow_interruption = FALSE;
                        }
                }
        } while (res == -1);
@@ -1199,7 +1247,7 @@ ves_icall_System_Threading_Monitor_Monitor_pulse (MonoObject *obj)
        if (mon->wait_list != NULL) {
                LOCK_DEBUG (g_message ("%s: (%d) signalling and dequeuing handle %p", __func__, mono_thread_info_get_small_id (), mon->wait_list->data));
        
-               SetEvent (mon->wait_list->data);
+               mono_w32event_set (mon->wait_list->data);
                mon->wait_list = g_slist_remove (mon->wait_list, mon->wait_list->data);
        }
 }
@@ -1230,7 +1278,7 @@ ves_icall_System_Threading_Monitor_Monitor_pulse_all (MonoObject *obj)
        while (mon->wait_list != NULL) {
                LOCK_DEBUG (g_message ("%s: (%d) signalling and dequeuing handle %p", __func__, mono_thread_info_get_small_id (), mon->wait_list->data));
        
-               SetEvent (mon->wait_list->data);
+               mono_w32event_set (mon->wait_list->data);
                mon->wait_list = g_slist_remove (mon->wait_list, mon->wait_list->data);
        }
 }
@@ -1265,7 +1313,7 @@ ves_icall_System_Threading_Monitor_Monitor_wait (MonoObject *obj, guint32 ms)
        if (mono_thread_current_check_pending_interrupt ())
                return FALSE;
        
-       event = CreateEvent (NULL, FALSE, FALSE, NULL);
+       event = mono_w32event_create (FALSE, FALSE);
        if (event == NULL) {
                mono_set_pending_exception (mono_get_exception_synchronization_lock ("Failed to set up wait event"));
                return FALSE;
index d651b0e5b08387b9b4829e0ce74b612e1fc3cc54..5f3ecb93ea65582aaadb6081e7cfa9e1f2f0c7dc 100644 (file)
@@ -53,7 +53,7 @@ extern MonoBoolean ves_icall_System_Net_NetworkInformation_MacOsIPInterfacePrope
                return FALSE;
 
        // Allocate suffcient memory for available data based on the previous sysctl call
-       if ((buf = malloc(needed)) == NULL)
+       if ((buf = g_malloc (needed)) == NULL)
                return FALSE;
 
        // Second sysctl call to retrieve data into appropriately sized buffer
@@ -102,7 +102,7 @@ extern MonoBoolean ves_icall_System_Net_NetworkInformation_MacOsIPInterfacePrope
                mono_array_setref (*gw_addr_list, gwnum, addr_string);
                gwnum++;
        }
-       free(buf);
+       g_free (buf);
        return TRUE;
 }
 
index 47d7dc5b1decdcde5b5cec33b24527f639ddc41d..1ab1e0ebb2d3279e98a411d2151779e1bdfc1062 100644 (file)
@@ -191,7 +191,7 @@ mono_gc_free_fixed (void* addr)
 void *
 mono_gc_alloc_obj (MonoVTable *vtable, size_t size)
 {
-       MonoObject *obj = calloc (1, size);
+       MonoObject *obj = g_calloc (1, size);
 
        obj->vtable = vtable;
 
@@ -201,7 +201,7 @@ mono_gc_alloc_obj (MonoVTable *vtable, size_t size)
 void *
 mono_gc_alloc_vector (MonoVTable *vtable, size_t size, uintptr_t max_length)
 {
-       MonoArray *obj = calloc (1, size);
+       MonoArray *obj = g_calloc (1, size);
 
        obj->obj.vtable = vtable;
        obj->max_length = max_length;
@@ -212,7 +212,7 @@ mono_gc_alloc_vector (MonoVTable *vtable, size_t size, uintptr_t max_length)
 void *
 mono_gc_alloc_array (MonoVTable *vtable, size_t size, uintptr_t max_length, uintptr_t bounds_size)
 {
-       MonoArray *obj = calloc (1, size);
+       MonoArray *obj = g_calloc (1, size);
 
        obj->obj.vtable = vtable;
        obj->max_length = max_length;
@@ -226,7 +226,7 @@ mono_gc_alloc_array (MonoVTable *vtable, size_t size, uintptr_t max_length, uint
 void *
 mono_gc_alloc_string (MonoVTable *vtable, size_t size, gint32 len)
 {
-       MonoString *obj = calloc (1, size);
+       MonoString *obj = g_calloc (1, size);
 
        obj->object.vtable = vtable;
        obj->length = len;
index 9d128319a76846a8a7a90eee3bacffd3c17cc903..d28bd6c9f7997479f5cf34cbce3c6f37b1f43faa 100644 (file)
@@ -357,7 +357,6 @@ struct _MonoInternalThread {
        MonoException *abort_exc;
        int abort_state_handle;
        guint64 tid;    /* This is accessed as a gsize in the code (so it can hold a 64bit pointer on systems that need it), but needs to reserve 64 bits of space on all machines as it corresponds to a field in managed code */
-       MonoCoopSem *start_notify;
        gpointer stack_ptr;
        gpointer *static_data;
        void *thread_info; /*This is MonoThreadInfo*, but to simplify dependencies, let's make it a void* here. */
@@ -380,14 +379,22 @@ struct _MonoInternalThread {
        gpointer interrupt_on_stop;
        gsize    flags;
        gpointer thread_pinning_ref;
+       gsize abort_protected_block_count;
+       gint32 priority;
        /* 
         * These fields are used to avoid having to increment corlib versions
         * when a new field is added to this structure.
         * Please synchronize any changes with InternalThread in Thread.cs, i.e. add the
         * same field there.
         */
-       gsize start_notify_refcount;
-       gsize abort_protected_block_count;
+       gsize unused1;
+       gsize unused2;
+
+       /* This is used only to check that we are in sync between the representation
+        * of MonoInternalThread in native and InternalThread in managed
+        *
+        * DO NOT RENAME! DO NOT ADD FIELDS AFTER! */
+       gpointer last;
 };
 
 struct _MonoThread {
@@ -395,7 +402,6 @@ struct _MonoThread {
        struct _MonoInternalThread *internal_thread;
        MonoObject *start_obj;
        MonoException *pending_exception;
-       gint32 priority;
 };
 
 typedef struct {
@@ -1517,14 +1523,14 @@ struct _MonoIMTCheckItem {
        guint8            has_target_code;
 };
 
-typedef gpointer (*MonoImtThunkBuilder) (MonoVTable *vtable, MonoDomain *domain,
+typedef gpointer (*MonoImtTrampolineBuilder) (MonoVTable *vtable, MonoDomain *domain,
                MonoIMTCheckItem **imt_entries, int count, gpointer fail_trunk);
 
 void
-mono_install_imt_thunk_builder (MonoImtThunkBuilder func);
+mono_install_imt_trampoline_builder (MonoImtTrampolineBuilder func);
 
 void
-mono_set_always_build_imt_thunks (gboolean value);
+mono_set_always_build_imt_trampolines (gboolean value);
 
 void
 mono_vtable_build_imt_slot (MonoVTable* vtable, int imt_slot);
@@ -1538,7 +1544,7 @@ mono_method_add_generic_virtual_invocation (MonoDomain *domain, MonoVTable *vtab
                                                                                        MonoMethod *method, gpointer code);
 
 gpointer
-mono_method_alloc_generic_virtual_thunk (MonoDomain *domain, int size);
+mono_method_alloc_generic_virtual_trampoline (MonoDomain *domain, int size);
 
 typedef enum {
        MONO_UNHANDLED_POLICY_LEGACY,
index 0085528adb4891ab77d4b0dce98b45e6015a1fbc..e4965a512a758da60f6db8a0512e36588a3b3bce 100644 (file)
@@ -92,6 +92,7 @@ DECL_OFFSET(MonoDelegate, extra_arg)
 DECL_OFFSET(MonoInternalThread, tid)
 DECL_OFFSET(MonoInternalThread, small_id)
 DECL_OFFSET(MonoInternalThread, static_data)
+DECL_OFFSET(MonoInternalThread, last)
 
 DECL_OFFSET(MonoMulticastDelegate, delegates)
 
index 0aede5fbb2092feb2ec7ad9c1b53ddfce4a1e903..16571fd270f88715d29ab70282e3fab650096aac 100644 (file)
@@ -41,6 +41,7 @@
 #include <mono/metadata/gc-internals.h>
 #include <mono/metadata/verify-internals.h>
 #include <mono/metadata/reflection-internals.h>
+#include <mono/metadata/w32event.h>
 #include <mono/utils/strenc.h>
 #include <mono/utils/mono-counters.h>
 #include <mono/utils/mono-error-internals.h>
@@ -571,8 +572,8 @@ default_delegate_trampoline (MonoDomain *domain, MonoClass *klass)
 }
 
 static MonoDelegateTrampoline arch_create_delegate_trampoline = default_delegate_trampoline;
-static MonoImtThunkBuilder imt_thunk_builder;
-static gboolean always_build_imt_thunks;
+static MonoImtTrampolineBuilder imt_trampoline_builder;
+static gboolean always_build_imt_trampolines;
 
 #if (MONO_IMT_SIZE > 32)
 #error "MONO_IMT_SIZE cannot be larger than 32"
@@ -605,14 +606,15 @@ mono_install_delegate_trampoline (MonoDelegateTrampoline func)
 }
 
 void
-mono_install_imt_thunk_builder (MonoImtThunkBuilder func) {
-       imt_thunk_builder = func;
+mono_install_imt_trampoline_builder (MonoImtTrampolineBuilder func)
+{
+       imt_trampoline_builder = func;
 }
 
 void
-mono_set_always_build_imt_thunks (gboolean value)
+mono_set_always_build_imt_trampolines (gboolean value)
 {
-       always_build_imt_thunks = value;
+       always_build_imt_trampolines = value;
 }
 
 /**
@@ -1206,7 +1208,7 @@ mono_method_get_imt_slot (MonoMethod *method)
                break;
        }
        
-       free (hashes_start);
+       g_free (hashes_start);
        /* Report the result */
        return c % MONO_IMT_SIZE;
 }
@@ -1334,7 +1336,7 @@ imt_sort_slot_entries (MonoImtBuilderEntry *entries) {
 
        imt_emit_ir (sorted_array, 0, number_of_entries, result);
 
-       free (sorted_array);
+       g_free (sorted_array);
        return result;
 }
 
@@ -1344,15 +1346,15 @@ initialize_imt_slot (MonoVTable *vtable, MonoDomain *domain, MonoImtBuilderEntry
        MONO_REQ_GC_NEUTRAL_MODE;
 
        if (imt_builder_entry != NULL) {
-               if (imt_builder_entry->children == 0 && !fail_tramp && !always_build_imt_thunks) {
+               if (imt_builder_entry->children == 0 && !fail_tramp && !always_build_imt_trampolines) {
                        /* No collision, return the vtable slot contents */
                        return vtable->vtable [imt_builder_entry->value.vtable_slot];
                } else {
-                       /* Collision, build the thunk */
+                       /* Collision, build the trampoline */
                        GPtrArray *imt_ir = imt_sort_slot_entries (imt_builder_entry);
                        gpointer result;
                        int i;
-                       result = imt_thunk_builder (vtable, domain,
+                       result = imt_trampoline_builder (vtable, domain,
                                (MonoIMTCheckItem**)imt_ir->pdata, imt_ir->len, fail_tramp);
                        for (i = 0; i < imt_ir->len; ++i)
                                g_free (g_ptr_array_index (imt_ir, i));
@@ -1474,12 +1476,12 @@ build_imt_slots (MonoClass *klass, MonoVTable *vt, MonoDomain *domain, gpointer*
 
                        if (has_generic_virtual || has_variant_iface) {
                                /*
-                                * There might be collisions later when the the thunk is expanded.
+                                * There might be collisions later when the the trampoline is expanded.
                                 */
                                imt_collisions_bitmap |= (1 << i);
 
                                /* 
-                                * The IMT thunk might be called with an instance of one of the 
+                                * The IMT trampoline might be called with an instance of one of the 
                                 * generic virtual methods, so has to fallback to the IMT trampoline.
                                 */
                                imt [i] = initialize_imt_slot (vt, domain, imt_builder [i], callbacks.get_imt_trampoline (vt, i));
@@ -1514,7 +1516,7 @@ build_imt_slots (MonoClass *klass, MonoVTable *vt, MonoDomain *domain, gpointer*
                        entry = next;
                }
        }
-       free (imt_builder);
+       g_free (imt_builder);
        /* we OR the bitmap since we may build just a single imt slot at a time */
        vt->imt_collisions_bitmap |= imt_collisions_bitmap;
 }
@@ -1532,7 +1534,7 @@ build_imt (MonoClass *klass, MonoVTable *vt, MonoDomain *domain, gpointer* imt,
  * @imt_slot: slot in the IMT table
  *
  * Fill the given @imt_slot in the IMT table of @vtable with
- * a trampoline or a thunk for the case of collisions.
+ * a trampoline or a trampoline for the case of collisions.
  * This is part of the internal mono API.
  *
  * LOCKING: Take the domain lock.
@@ -1604,23 +1606,23 @@ list_index_for_size (int item_size)
 }
 
 /**
- * mono_method_alloc_generic_virtual_thunk:
+ * mono_method_alloc_generic_virtual_trampoline:
  * @domain: a domain
  * @size: size in bytes
  *
  * Allocs size bytes to be used for the code of a generic virtual
- * thunk.  It's either allocated from the domain's code manager or
+ * trampoline.  It's either allocated from the domain's code manager or
  * reused from a previously invalidated piece.
  *
  * LOCKING: The domain lock must be held.
  */
 gpointer
-mono_method_alloc_generic_virtual_thunk (MonoDomain *domain, int size)
+mono_method_alloc_generic_virtual_trampoline (MonoDomain *domain, int size)
 {
        MONO_REQ_GC_NEUTRAL_MODE;
 
        static gboolean inited = FALSE;
-       static int generic_virtual_thunks_size = 0;
+       static int generic_virtual_trampolines_size = 0;
 
        guint32 *p;
        int i;
@@ -1653,19 +1655,19 @@ mono_method_alloc_generic_virtual_thunk (MonoDomain *domain, int size)
 
        /* still nothing found - allocate it */
        if (!inited) {
-               mono_counters_register ("Generic virtual thunk bytes",
-                               MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &generic_virtual_thunks_size);
+               mono_counters_register ("Generic virtual trampoline bytes",
+                               MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &generic_virtual_trampolines_size);
                inited = TRUE;
        }
-       generic_virtual_thunks_size += size;
+       generic_virtual_trampolines_size += size;
 
        p = (guint32 *)mono_domain_code_reserve (domain, size);
        *p = size;
 
        mono_domain_lock (domain);
-       if (!domain->generic_virtual_thunks)
-               domain->generic_virtual_thunks = g_hash_table_new (NULL, NULL);
-       g_hash_table_insert (domain->generic_virtual_thunks, p, p);
+       if (!domain->generic_virtual_trampolines)
+               domain->generic_virtual_trampolines = g_hash_table_new (NULL, NULL);
+       g_hash_table_insert (domain->generic_virtual_trampolines, p, p);
        mono_domain_unlock (domain);
 
        return p + 1;
@@ -1675,7 +1677,7 @@ mono_method_alloc_generic_virtual_thunk (MonoDomain *domain, int size)
  * LOCKING: The domain lock must be held.
  */
 static void
-invalidate_generic_virtual_thunk (MonoDomain *domain, gpointer code)
+invalidate_generic_virtual_trampoline (MonoDomain *domain, gpointer code)
 {
        MONO_REQ_GC_NEUTRAL_MODE;
 
@@ -1684,14 +1686,14 @@ invalidate_generic_virtual_thunk (MonoDomain *domain, gpointer code)
        gboolean found = FALSE;
 
        mono_domain_lock (domain);
-       if (!domain->generic_virtual_thunks)
-               domain->generic_virtual_thunks = g_hash_table_new (NULL, NULL);
-       if (g_hash_table_lookup (domain->generic_virtual_thunks, l))
+       if (!domain->generic_virtual_trampolines)
+               domain->generic_virtual_trampolines = g_hash_table_new (NULL, NULL);
+       if (g_hash_table_lookup (domain->generic_virtual_trampolines, l))
                found = TRUE;
        mono_domain_unlock (domain);
 
        if (!found)
-               /* Not allocated by mono_method_alloc_generic_virtual_thunk (), i.e. AOT */
+               /* Not allocated by mono_method_alloc_generic_virtual_trampoline (), i.e. AOT */
                return;
        init_thunk_free_lists (domain);
 
@@ -1784,7 +1786,7 @@ get_generic_virtual_entries (MonoDomain *domain, gpointer *vtable_slot)
  * Registers a call via unmanaged code to a generic virtual method
  * instantiation or variant interface method.  If the number of calls reaches a threshold
  * (THUNK_THRESHOLD), the method is added to the vtable slot's generic
- * virtual method thunk.
+ * virtual method trampoline.
  */
 void
 mono_method_add_generic_virtual_invocation (MonoDomain *domain, MonoVTable *vtable,
@@ -1840,7 +1842,7 @@ mono_method_add_generic_virtual_invocation (MonoDomain *domain, MonoVTable *vtab
                        int displacement = (gpointer*)vtable_slot - (gpointer*)vtable;
                        int imt_slot = MONO_IMT_SIZE + displacement;
 
-                       /* Force the rebuild of the thunk at the next call */
+                       /* Force the rebuild of the trampoline at the next call */
                        imt_trampoline = callbacks.get_imt_trampoline (vtable, imt_slot);
                        *vtable_slot = imt_trampoline;
                } else {
@@ -1850,8 +1852,8 @@ mono_method_add_generic_virtual_invocation (MonoDomain *domain, MonoVTable *vtab
 
                        sorted = imt_sort_slot_entries (entries);
 
-                       *vtable_slot = imt_thunk_builder (NULL, domain, (MonoIMTCheckItem**)sorted->pdata, sorted->len,
-                                                                                         vtable_trampoline);
+                       *vtable_slot = imt_trampoline_builder (NULL, domain, (MonoIMTCheckItem**)sorted->pdata, sorted->len,
+                                                                                                  vtable_trampoline);
 
                        while (entries) {
                                MonoImtBuilderEntry *next = entries->next;
@@ -1865,10 +1867,10 @@ mono_method_add_generic_virtual_invocation (MonoDomain *domain, MonoVTable *vtab
                }
 
 #ifndef __native_client__
-               /* We don't re-use any thunks as there is a lot of overhead */
+               /* We don't re-use any trampolines as there is a lot of overhead */
                /* to deleting and re-using code in Native Client.          */
                if (old_thunk != vtable_trampoline && old_thunk != imt_trampoline)
-                       invalidate_generic_virtual_thunk (domain, old_thunk);
+                       invalidate_generic_virtual_trampoline (domain, old_thunk);
 #endif
        }
 
@@ -7568,7 +7570,7 @@ ves_icall_System_Runtime_Remoting_Messaging_AsyncResult_Invoke (MonoAsyncResult
                mono_monitor_exit ((MonoObject*) ares);
 
                if (wait_event != NULL)
-                       SetEvent (wait_event);
+                       mono_w32event_set (wait_event);
 
                mono_error_init (&error); //the else branch would leave it in an undefined state
                if (ac->cb_method)
index c4feb7fa150a82831e45d81a6abd870d995ad25c..c902fcdbe5a92ad3aa5427b21c4bceed9ce42e0a 100644 (file)
@@ -968,11 +968,11 @@ void*
 mono_gc_alloc_fixed (size_t size, MonoGCDescriptor descr, MonoGCRootSource source, const char *msg)
 {
        /* FIXME: do a single allocation */
-       void *res = calloc (1, size);
+       void *res = g_calloc (1, size);
        if (!res)
                return NULL;
        if (!mono_gc_register_root ((char *)res, size, descr, source, msg)) {
-               free (res);
+               g_free (res);
                res = NULL;
        }
        return res;
@@ -982,7 +982,7 @@ void
 mono_gc_free_fixed (void* addr)
 {
        mono_gc_deregister_root ((char *)addr);
-       free (addr);
+       g_free (addr);
 }
 
 /*
index 04c55e7241bc4a85ced64fc6cf8bfbc3ae11a192..d4d168da76691a76c3f041b40cf2c45dde95d775 100644 (file)
@@ -774,16 +774,15 @@ ves_icall_System_Net_Sockets_Socket_Accept_internal (SOCKET sock, gint32 *werror
 
        MONO_EXIT_GC_SAFE;
 
+       if (newsock == INVALID_SOCKET)
+               *werror = WSAGetLastError ();
+
        mono_thread_info_uninstall_interrupt (&interrupted);
-       if (interrupted) {
+       if (interrupted)
                *werror = WSAEINTR;
-               return NULL;
-       }
 
-       if (newsock == INVALID_SOCKET) {
-               *werror = WSAGetLastError ();
+       if (*werror)
                return NULL;
-       }
        
        return GUINT_TO_POINTER (newsock);
 }
@@ -1336,15 +1335,13 @@ ves_icall_System_Net_Sockets_Socket_Connect_internal (SOCKET sock, MonoObject *s
 
        MONO_EXIT_GC_SAFE;
 
-       mono_thread_info_uninstall_interrupt (&interrupted);
-       if (interrupted) {
-               *werror = WSAEINTR;
-               return;
-       }
-
        if (ret == SOCKET_ERROR)
                *werror = WSAGetLastError ();
 
+       mono_thread_info_uninstall_interrupt (&interrupted);
+       if (interrupted)
+               *werror = WSAEINTR;
+
        g_free (sa);
 }
 
@@ -1423,10 +1420,10 @@ ves_icall_System_Net_Sockets_Socket_Disconnect_internal (SOCKET sock, MonoBoolea
        MONO_ENTER_GC_SAFE;
 
        if (_wapi_disconnectex != NULL) {
-               if (!_wapi_disconnectex (sock, NULL, TF_REUSE_SOCKET, 0))
+               if (!_wapi_disconnectex (sock, NULL, reuse ? TF_REUSE_SOCKET : 0, 0))
                        *werror = WSAGetLastError ();
        } else if (_wapi_transmitfile != NULL) {
-               if (!_wapi_transmitfile (sock, NULL, 0, 0, NULL, NULL, TF_DISCONNECT | TF_REUSE_SOCKET))
+               if (!_wapi_transmitfile (sock, NULL, 0, 0, NULL, NULL, TF_DISCONNECT | (reuse ? TF_REUSE_SOCKET : 0)))
                        *werror = WSAGetLastError ();
        } else {
                *werror = ERROR_NOT_SUPPORTED;
@@ -1481,16 +1478,15 @@ ves_icall_System_Net_Sockets_Socket_Receive_internal (SOCKET sock, MonoArray *bu
 
        MONO_EXIT_GC_SAFE;
 
+       if (ret == SOCKET_ERROR)
+               *werror = WSAGetLastError ();
+
        mono_thread_info_uninstall_interrupt (&interrupted);
-       if (interrupted) {
+       if (interrupted)
                *werror = WSAEINTR;
-               return 0;
-       }
 
-       if (ret == SOCKET_ERROR) {
-               *werror = WSAGetLastError ();
+       if (*werror)
                return 0;
-       }
 
        return ret;
 }
@@ -1527,16 +1523,15 @@ ves_icall_System_Net_Sockets_Socket_Receive_array_internal (SOCKET sock, MonoArr
 
        MONO_EXIT_GC_SAFE;
 
+       if (ret == SOCKET_ERROR)
+               *werror = WSAGetLastError ();
+
        mono_thread_info_uninstall_interrupt (&interrupted);
-       if (interrupted) {
+       if (interrupted)
                *werror = WSAEINTR;
-               return 0;
-       }
 
-       if (ret == SOCKET_ERROR) {
-               *werror = WSAGetLastError ();
+       if (*werror)
                return 0;
-       }
 
        return recv;
 }
@@ -1588,16 +1583,16 @@ ves_icall_System_Net_Sockets_Socket_ReceiveFrom_internal (SOCKET sock, MonoArray
 
        MONO_EXIT_GC_SAFE;
 
+       if (ret == SOCKET_ERROR)
+               *werror = WSAGetLastError ();
+
        mono_thread_info_uninstall_interrupt (&interrupted);
-       if (interrupted) {
-               g_free (sa);
+
+       if (interrupted)
                *werror = WSAEINTR;
-               return 0;
-       }
 
-       if (ret==SOCKET_ERROR) {
-               g_free (sa);
-               *werror = WSAGetLastError ();
+       if (*werror) {
+               g_free(sa);
                return 0;
        }
 
@@ -1660,16 +1655,15 @@ ves_icall_System_Net_Sockets_Socket_Send_internal (SOCKET sock, MonoArray *buffe
 
        MONO_EXIT_GC_SAFE;
 
+       if (ret == SOCKET_ERROR)
+               *werror = WSAGetLastError ();
+
        mono_thread_info_uninstall_interrupt (&interrupted);
-       if (interrupted) {
+       if (interrupted)
                *werror = WSAEINTR;
-               return 0;
-       }
 
-       if (ret == SOCKET_ERROR) {
-               *werror = WSAGetLastError ();
+       if (*werror)
                return 0;
-       }
 
        return ret;
 }
@@ -1706,17 +1700,16 @@ ves_icall_System_Net_Sockets_Socket_Send_array_internal (SOCKET sock, MonoArray
 
        MONO_EXIT_GC_SAFE;
 
+       if (ret == SOCKET_ERROR)
+               *werror = WSAGetLastError ();
+
        mono_thread_info_uninstall_interrupt (&interrupted);
-       if (interrupted) {
+       if (interrupted)
                *werror = WSAEINTR;
-               return 0;
-       }
 
-       if (ret == SOCKET_ERROR) {
-               *werror = WSAGetLastError ();
+       if (*werror)
                return 0;
-       }
-       
+
        return sent;
 }
 
@@ -1773,18 +1766,18 @@ ves_icall_System_Net_Sockets_Socket_SendTo_internal (SOCKET sock, MonoArray *buf
 
        MONO_EXIT_GC_SAFE;
 
+       if (ret == SOCKET_ERROR)
+               *werror = WSAGetLastError ();
+
        mono_thread_info_uninstall_interrupt (&interrupted);
-       if (interrupted) {
-               g_free (sa);
+       if (interrupted)
                *werror = WSAEINTR;
-               return 0;
-       }
 
-       if (ret == SOCKET_ERROR)
-               *werror = WSAGetLastError ();
+       g_free(sa);
+
+       if (*werror)
+               return 0;
 
-       g_free (sa);
-       
        return ret;
 }
 
@@ -1961,7 +1954,7 @@ ves_icall_System_Net_Sockets_Socket_GetSocketOption_obj_internal (SOCKET sock, g
        int system_level = 0;
        int system_name = 0;
        int ret;
-       int val;
+       int val = 0;
        socklen_t valsize = sizeof (val);
        struct linger linger;
        socklen_t lingersize = sizeof (linger);
@@ -2454,14 +2447,14 @@ ves_icall_System_Net_Sockets_Socket_Shutdown_internal (SOCKET sock, gint32 how,
 
        MONO_EXIT_GC_SAFE;
 
+       if (ret == SOCKET_ERROR)
+               *werror = WSAGetLastError ();
+
        mono_thread_info_uninstall_interrupt (&interrupted);
        if (interrupted) {
                *werror = WSAEINTR;
-               return;
        }
 
-       if (ret == SOCKET_ERROR)
-               *werror = WSAGetLastError ();
 }
 
 gint
index 50d7635ca41d5259200c67f8db6118e5d8e5b1dc..c15bd42b74aabd2b63709a831bcd20cc338e128d 100644 (file)
@@ -42,8 +42,6 @@ mono_sre_generic_param_table_entry_free (GenericParamTableEntry *entry)
        g_free (entry);
 }
 
-
-
 static GENERATE_GET_CLASS_WITH_CACHE (marshal_as_attribute, System.Runtime.InteropServices, MarshalAsAttribute);
 
 #ifndef DISABLE_REFLECTION_EMIT
@@ -75,8 +73,6 @@ static guint32 mono_image_get_methodspec_token (MonoDynamicImage *assembly, Mono
 static guint32 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m);
 static MonoMethod * inflate_method (MonoReflectionType *type, MonoObject *obj, MonoError *error);
 
-static guint32 create_typespec (MonoDynamicImage *assembly, MonoType *type);
-
 #define mono_type_array_get_and_resolve(array, index, error) mono_reflection_type_get_handle ((MonoReflectionType*)mono_array_get (array, gpointer, index), error)
 
 static void mono_image_module_basic_init (MonoReflectionModuleBuilder *module);
@@ -200,30 +196,12 @@ string_heap_insert (MonoDynamicStream *sh, const char *str)
        return mono_dynstream_insert_string (sh, str);
 }
 
-static guint32
-string_heap_insert_mstring (MonoDynamicStream *sh, MonoString *str, MonoError *error)
-{
-       return mono_dynstream_insert_mstring (sh, str, error);
-}
-
 static guint32
 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
 {
        return mono_dynstream_add_data (stream, data, len);
 }
 
-static guint32
-mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
-{
-       return mono_dynstream_add_zero (stream, len);
-}
-
-static void
-stream_data_align (MonoDynamicStream *stream)
-{
-       mono_dynstream_data_align (stream);
-}
-
 /*
  * Despite the name, we handle also TypeSpec (with the above helper).
  */
@@ -279,56 +257,6 @@ swap_with_size (char *dest, const char* val, int len, int nelem) {
 #endif
 }
 
-#ifndef DISABLE_REFLECTION_EMIT
-static MonoClass *
-default_class_from_mono_type (MonoType *type)
-{
-       MONO_REQ_GC_NEUTRAL_MODE;
-
-       switch (type->type) {
-       case MONO_TYPE_OBJECT:
-               return mono_defaults.object_class;
-       case MONO_TYPE_VOID:
-               return mono_defaults.void_class;
-       case MONO_TYPE_BOOLEAN:
-               return mono_defaults.boolean_class;
-       case MONO_TYPE_CHAR:
-               return mono_defaults.char_class;
-       case MONO_TYPE_I1:
-               return mono_defaults.sbyte_class;
-       case MONO_TYPE_U1:
-               return mono_defaults.byte_class;
-       case MONO_TYPE_I2:
-               return mono_defaults.int16_class;
-       case MONO_TYPE_U2:
-               return mono_defaults.uint16_class;
-       case MONO_TYPE_I4:
-               return mono_defaults.int32_class;
-       case MONO_TYPE_U4:
-               return mono_defaults.uint32_class;
-       case MONO_TYPE_I:
-               return mono_defaults.int_class;
-       case MONO_TYPE_U:
-               return mono_defaults.uint_class;
-       case MONO_TYPE_I8:
-               return mono_defaults.int64_class;
-       case MONO_TYPE_U8:
-               return mono_defaults.uint64_class;
-       case MONO_TYPE_R4:
-               return mono_defaults.single_class;
-       case MONO_TYPE_R8:
-               return mono_defaults.double_class;
-       case MONO_TYPE_STRING:
-               return mono_defaults.string_class;
-       default:
-               g_warning ("default_class_from_mono_type: implement me 0x%02x\n", type->type);
-               g_assert_not_reached ();
-       }
-       
-       return NULL;
-}
-#endif
-
 guint32
 mono_reflection_method_count_clauses (MonoReflectionILGen *ilgen)
 {
@@ -3563,53 +3491,6 @@ methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb,
        }
        return mb->mhandle;
 }
-
-static MonoClassField*
-fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb, MonoError *error)
-{
-       MonoClassField *field;
-       MonoType *custom;
-
-       mono_error_init (error);
-
-       field = g_new0 (MonoClassField, 1);
-
-       field->name = mono_string_to_utf8_image (klass->image, fb->name, error);
-       mono_error_assert_ok (error);
-       if (fb->attrs || fb->modreq || fb->modopt) {
-               MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
-               if (!is_ok (error)) {
-                       g_free (field);
-                       return NULL;
-               }
-               field->type = mono_metadata_type_dup (NULL, type);
-               field->type->attrs = fb->attrs;
-
-               g_assert (image_is_dynamic (klass->image));
-               custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt, error);
-               g_free (field->type);
-               if (!is_ok (error)) {
-                       g_free (field);
-                       return NULL;
-               }
-               field->type = mono_metadata_type_dup (klass->image, custom);
-               g_free (custom);
-       } else {
-               field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
-               if (!is_ok (error)) {
-                       g_free (field);
-                       return NULL;
-               }
-       }
-       if (fb->offset != -1)
-               field->offset = fb->offset;
-       field->parent = klass;
-       mono_save_custom_attrs (klass->image, field, fb->cattrs);
-
-       // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
-
-       return field;
-}
 #endif
 
 #ifndef DISABLE_REFLECTION_EMIT
index f999bee533924130c9db5ff7a966e2d9f5c0573e..462fd69a77f172521b3ff983aae71160b2099aa4 100644 (file)
@@ -33,6 +33,7 @@
 #include <mono/metadata/object-internals.h>
 #include <mono/metadata/threadpool-ms.h>
 #include <mono/metadata/threadpool-ms-io.h>
+#include <mono/metadata/w32event.h>
 #include <mono/utils/atomic.h>
 #include <mono/utils/mono-compiler.h>
 #include <mono/utils/mono-complex.h>
@@ -159,6 +160,11 @@ typedef struct {
        gboolean suspended;
 } ThreadPool;
 
+typedef struct {
+       gint32 ref;
+       MonoCoopSem sem;
+} ThreadPoolDomainCleanupSemaphore;
+
 typedef enum {
        TRANSITION_WARMUP,
        TRANSITION_INITIALIZING,
@@ -430,6 +436,14 @@ domain_get (MonoDomain *domain, gboolean create)
        }
 
        if (create) {
+               ThreadPoolDomainCleanupSemaphore *cleanup_semaphore;
+               cleanup_semaphore = g_new0 (ThreadPoolDomainCleanupSemaphore, 1);
+               cleanup_semaphore->ref = 2;
+               mono_coop_sem_init (&cleanup_semaphore->sem, 0);
+
+               g_assert(!domain->cleanup_semaphore);
+               domain->cleanup_semaphore = cleanup_semaphore;
+
                tpdomain = g_new0 (ThreadPoolDomain, 1);
                tpdomain->domain = domain;
                domain_add (tpdomain);
@@ -681,10 +695,22 @@ worker_thread (gpointer data)
                g_assert (tpdomain->domain->threadpool_jobs >= 0);
 
                if (tpdomain->domain->threadpool_jobs == 0 && mono_domain_is_unloading (tpdomain->domain)) {
-                       gboolean removed = domain_remove (tpdomain);
+                       ThreadPoolDomainCleanupSemaphore *cleanup_semaphore;
+                       gboolean removed;
+
+                       removed = domain_remove(tpdomain);
                        g_assert (removed);
-                       if (tpdomain->domain->cleanup_semaphore)
-                               ReleaseSemaphore (tpdomain->domain->cleanup_semaphore, 1, NULL);
+
+                       cleanup_semaphore = (ThreadPoolDomainCleanupSemaphore*) tpdomain->domain->cleanup_semaphore;
+
+                       g_assert(cleanup_semaphore);
+                       mono_coop_sem_post (&cleanup_semaphore->sem);
+                       if (InterlockedDecrement (&cleanup_semaphore->ref) == 0) {
+                               mono_coop_sem_destroy (&cleanup_semaphore->sem);
+                               g_free (cleanup_semaphore);
+                               tpdomain->domain->cleanup_semaphore = NULL;
+                       }
+
                        domain_free (tpdomain);
                        tpdomain = NULL;
                }
@@ -1401,7 +1427,7 @@ mono_threadpool_ms_end_invoke (MonoAsyncResult *ares, MonoArray **out_args, Mono
                if (ares->handle) {
                        wait_event = mono_wait_handle_get_handle ((MonoWaitHandle*) ares->handle);
                } else {
-                       wait_event = CreateEvent (NULL, TRUE, FALSE, NULL);
+                       wait_event = mono_w32event_create (TRUE, FALSE);
                        g_assert(wait_event);
                        MonoWaitHandle *wait_handle = mono_wait_handle_new (mono_object_domain (ares), wait_event, error);
                        if (!is_ok (error)) {
@@ -1427,9 +1453,10 @@ mono_threadpool_ms_end_invoke (MonoAsyncResult *ares, MonoArray **out_args, Mono
 gboolean
 mono_threadpool_ms_remove_domain_jobs (MonoDomain *domain, int timeout)
 {
-       gboolean res = TRUE;
-       gint64 end;
-       gpointer sem;
+       gint res;
+       gint64 now, end;
+       ThreadPoolDomain *tpdomain;
+       ThreadPoolDomainCleanupSemaphore *cleanup_semaphore;
 
        g_assert (domain);
        g_assert (timeout >= -1);
@@ -1448,38 +1475,47 @@ mono_threadpool_ms_remove_domain_jobs (MonoDomain *domain, int timeout)
 #endif
 
        /*
-        * There might be some threads out that could be about to execute stuff from the given domain.
-        * We avoid that by setting up a semaphore to be pulsed by the thread that reaches zero.
-        */
-       sem = domain->cleanup_semaphore = CreateSemaphore (NULL, 0, 1, NULL);
+       * There might be some threads out that could be about to execute stuff from the given domain.
+       * We avoid that by waiting on a semaphore to be pulsed by the thread that reaches zero.
+       * The semaphore is only created for domains which queued threadpool jobs.
+       * We always wait on the semaphore rather than ensuring domain->threadpool_jobs is 0.
+       * There may be pending outstanding requests which will create new jobs.
+       * The semaphore is signaled the threadpool domain has been removed from list
+       * and we know no more jobs for the domain will be processed.
+       */
+
+       mono_lazy_initialize(&status, initialize);
+       mono_coop_mutex_lock(&threadpool->domains_lock);
+
+       tpdomain = domain_get (domain, FALSE);
+       if (!tpdomain || tpdomain->outstanding_request == 0) {
+               mono_coop_mutex_unlock(&threadpool->domains_lock);
+               return TRUE;
+       }
 
-       /*
-        * The memory barrier here is required to have global ordering between assigning to cleanup_semaphone
-        * and reading threadpool_jobs. Otherwise this thread could read a stale version of threadpool_jobs
-        * and wait forever.
-        */
-       mono_memory_write_barrier ();
-
-       while (domain->threadpool_jobs) {
-               gint64 now;
-
-               if (timeout != -1) {
-                       now = mono_msec_ticks ();
-                       if (now > end) {
-                               res = FALSE;
-                               break;
-                       }
-               }
+       mono_coop_mutex_unlock(&threadpool->domains_lock);
 
-               MONO_ENTER_GC_SAFE;
-               WaitForSingleObjectEx (sem, timeout != -1 ? end - now : timeout, FALSE);
-               MONO_EXIT_GC_SAFE;
+       g_assert (domain->cleanup_semaphore);
+
+       cleanup_semaphore = (ThreadPoolDomainCleanupSemaphore*) domain->cleanup_semaphore;
+
+       if (timeout == -1) {
+               res = mono_coop_sem_wait (&cleanup_semaphore->sem, MONO_SEM_FLAGS_NONE);
+               g_assert (res == MONO_SEM_TIMEDWAIT_RET_SUCCESS);
+       } else {
+               now = mono_msec_ticks();
+               if (now > end)
+                       return FALSE;
+               res = mono_coop_sem_timedwait (&cleanup_semaphore->sem, end - now, MONO_SEM_FLAGS_NONE);
        }
 
-       domain->cleanup_semaphore = NULL;
-       CloseHandle (sem);
+       if (InterlockedDecrement (&cleanup_semaphore->ref) == 0) {
+               mono_coop_sem_destroy (&cleanup_semaphore->sem);
+               g_free (cleanup_semaphore);
+               domain->cleanup_semaphore = NULL;
+       }
 
-       return res;
+       return res == MONO_SEM_TIMEDWAIT_RET_SUCCESS;
 }
 
 void
index e27e89bb6f088f3df2316861be72abb028de114e..ad472a0b9c06030dcc1e3cba4a235bc9c6287517 100644 (file)
@@ -42,6 +42,14 @@ typedef enum {
        ThreadApartmentState_Unknown = 0x00000002
 } MonoThreadApartmentState;
 
+typedef enum {
+       MONO_THREAD_PRIORITY_LOWEST       = 0,
+       MONO_THREAD_PRIORITY_BELOW_NORMAL = 1,
+       MONO_THREAD_PRIORITY_NORMAL       = 2,
+       MONO_THREAD_PRIORITY_ABOVE_NORMAL = 3,
+       MONO_THREAD_PRIORITY_HIGHEST      = 4,
+} MonoThreadPriority;
+
 #define SPECIAL_STATIC_NONE 0
 #define SPECIAL_STATIC_THREAD 1
 #define SPECIAL_STATIC_CONTEXT 2
@@ -75,17 +83,6 @@ MonoObject* ves_icall_System_Threading_Thread_GetCachedCurrentCulture (MonoInter
 void ves_icall_System_Threading_Thread_SetCachedCurrentCulture (MonoThread *this_obj, MonoObject *culture);
 MonoObject* ves_icall_System_Threading_Thread_GetCachedCurrentUICulture (MonoInternalThread *this_obj);
 void ves_icall_System_Threading_Thread_SetCachedCurrentUICulture (MonoThread *this_obj, MonoObject *culture);
-HANDLE ves_icall_System_Threading_Mutex_CreateMutex_internal(MonoBoolean owned, MonoString *name, MonoBoolean *created);
-MonoBoolean ves_icall_System_Threading_Mutex_ReleaseMutex_internal (HANDLE handle );
-HANDLE ves_icall_System_Threading_Mutex_OpenMutex_internal (MonoString *name, gint32 rights, gint32 *error);
-HANDLE ves_icall_System_Threading_Semaphore_CreateSemaphore_internal (gint32 initialCount, gint32 maximumCount, MonoString *name, gint32 *error);
-MonoBoolean ves_icall_System_Threading_Semaphore_ReleaseSemaphore_internal (HANDLE handle, gint32 releaseCount, gint32 *prevcount);
-HANDLE ves_icall_System_Threading_Semaphore_OpenSemaphore_internal (MonoString *name, gint32 rights, gint32 *error);
-HANDLE ves_icall_System_Threading_Events_CreateEvent_internal (MonoBoolean manual, MonoBoolean initial, MonoString *name, gint32 *error);
-gboolean ves_icall_System_Threading_Events_SetEvent_internal (HANDLE handle);
-gboolean ves_icall_System_Threading_Events_ResetEvent_internal (HANDLE handle);
-void ves_icall_System_Threading_Events_CloseEvent_internal (HANDLE handle);
-HANDLE ves_icall_System_Threading_Events_OpenEvent_internal (MonoString *name, gint32 rights, gint32 *error);
 
 gint32 ves_icall_System_Threading_WaitHandle_WaitAll_internal(MonoArray *mono_handles, gint32 ms);
 gint32 ves_icall_System_Threading_WaitHandle_WaitAny_internal(MonoArray *mono_handles, gint32 ms);
@@ -198,6 +195,7 @@ gboolean mono_thread_current_check_pending_interrupt (void);
 void mono_thread_set_state (MonoInternalThread *thread, MonoThreadState state);
 void mono_thread_clr_state (MonoInternalThread *thread, MonoThreadState state);
 gboolean mono_thread_test_state (MonoInternalThread *thread, MonoThreadState test);
+gboolean mono_thread_test_and_set_state (MonoInternalThread *thread, MonoThreadState test, MonoThreadState set);
 
 void mono_thread_init_apartment_state (void);
 void mono_thread_cleanup_apartment_state (void);
index e76f38a473fea6d941e6c05ed260bfd7f36f647e..ab3a11ea5f15e329d54147c82839ff1f3909a639 100644 (file)
 #include <mono/utils/mono-threads-coop.h>
 #include <mono/utils/mono-error-internals.h>
 #include <mono/utils/w32handle.h>
+#include <mono/metadata/w32event.h>
 
 #include <mono/metadata/gc-internals.h>
 #include <mono/metadata/reflection-internals.h>
+#include <mono/metadata/abi-details.h>
 
 #ifdef HAVE_SIGNAL_H
 #include <signal.h>
@@ -83,14 +85,6 @@ extern int tkill (pid_t tid, int signal);
 #define LOCK_THREAD(thread) lock_thread((thread))
 #define UNLOCK_THREAD(thread) unlock_thread((thread))
 
-typedef struct
-{
-       guint32 (*func)(void *);
-       MonoThread *obj;
-       MonoObject *delegate;
-       void *start_arg;
-} StartInfo;
-
 typedef union {
        gint32 ival;
        gfloat fval;
@@ -151,7 +145,7 @@ static MonoReferenceQueue *context_queue;
 
 /*
  * Threads which are starting up and they are not in the 'threads' hash yet.
- * When handle_store is called for a thread, it will be removed from this hash table.
+ * When mono_thread_attach_internal is called for a thread, it will be removed from this hash table.
  * Protected by mono_threads_lock ().
  */
 static MonoGHashTable *threads_starting_up = NULL;
@@ -192,7 +186,6 @@ static MonoThreadCleanupFunc mono_thread_cleanup_fn = NULL;
 static guint32 default_stacksize = 0;
 #define default_stacksize_for_thread(thread) ((thread)->stack_size? (thread)->stack_size: default_stacksize)
 
-static void thread_adjust_static_data (MonoInternalThread *thread);
 static void context_adjust_static_data (MonoAppContext *ctx);
 static void mono_free_static_data (gpointer* static_data);
 static void mono_init_static_data_info (StaticDataInfo *static_data);
@@ -270,87 +263,6 @@ thread_get_tid (MonoInternalThread *thread)
        return MONO_UINT_TO_NATIVE_THREAD_ID (thread->tid);
 }
 
-/* handle_store() and handle_remove() manage the array of threads that
- * still need to be waited for when the main thread exits.
- *
- * If handle_store() returns FALSE the thread must not be started
- * because Mono is shutting down.
- */
-static gboolean handle_store(MonoThread *thread, gboolean force_attach)
-{
-       mono_threads_lock ();
-
-       THREAD_DEBUG (g_message ("%s: thread %p ID %"G_GSIZE_FORMAT, __func__, thread, (gsize)thread->internal_thread->tid));
-
-       if (threads_starting_up)
-               mono_g_hash_table_remove (threads_starting_up, thread);
-
-       if (shutting_down && !force_attach) {
-               mono_threads_unlock ();
-               return FALSE;
-       }
-
-       if(threads==NULL) {
-               MONO_GC_REGISTER_ROOT_FIXED (threads, MONO_ROOT_SOURCE_THREADING, "threads table");
-               threads=mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_THREADING, "threads table");
-       }
-
-       /* We don't need to duplicate thread->handle, because it is
-        * only closed when the thread object is finalized by the GC.
-        */
-       g_assert (thread->internal_thread);
-       mono_g_hash_table_insert(threads, (gpointer)(gsize)(thread->internal_thread->tid),
-                                thread->internal_thread);
-
-       mono_threads_unlock ();
-
-       return TRUE;
-}
-
-static gboolean handle_remove(MonoInternalThread *thread)
-{
-       gboolean ret;
-       gsize tid = thread->tid;
-
-       THREAD_DEBUG (g_message ("%s: thread ID %"G_GSIZE_FORMAT, __func__, tid));
-
-       mono_threads_lock ();
-
-       if (threads) {
-               /* We have to check whether the thread object for the
-                * tid is still the same in the table because the
-                * thread might have been destroyed and the tid reused
-                * in the meantime, in which case the tid would be in
-                * the table, but with another thread object.
-                */
-               if (mono_g_hash_table_lookup (threads, (gpointer)tid) == thread) {
-                       mono_g_hash_table_remove (threads, (gpointer)tid);
-                       ret = TRUE;
-               } else {
-                       ret = FALSE;
-               }
-       }
-       else
-               ret = FALSE;
-       
-       mono_threads_unlock ();
-
-       /* Don't close the handle here, wait for the object finalizer
-        * to do it. Otherwise, the following race condition applies:
-        *
-        * 1) Thread exits (and handle_remove() closes the handle)
-        *
-        * 2) Some other handle is reassigned the same slot
-        *
-        * 3) Another thread tries to join the first thread, and
-        * blocks waiting for the reassigned handle to be signalled
-        * (which might never happen).  This is possible, because the
-        * thread calling Join() still has a reference to the first
-        * thread's object.
-        */
-       return ret;
-}
-
 static void ensure_synch_cs_set (MonoInternalThread *thread)
 {
        MonoCoopMutex *synch_cs;
@@ -406,6 +318,8 @@ is_threadabort_exception (MonoClass *klass)
  */
 static void thread_cleanup (MonoInternalThread *thread)
 {
+       gboolean ret;
+
        g_assert (thread != NULL);
 
        if (thread->abort_state_handle) {
@@ -454,13 +368,45 @@ static void thread_cleanup (MonoInternalThread *thread)
        if (InterlockedExchange (&thread->interruption_requested, 0))
                InterlockedDecrement (&thread_interruption_requested);
 
+       mono_threads_lock ();
+
+       if (!threads) {
+               ret = FALSE;
+       } else if (mono_g_hash_table_lookup (threads, (gpointer)thread->tid) != thread) {
+               /* We have to check whether the thread object for the
+                * tid is still the same in the table because the
+                * thread might have been destroyed and the tid reused
+                * in the meantime, in which case the tid would be in
+                * the table, but with another thread object.
+                */
+               ret = FALSE;
+       } else {
+               mono_g_hash_table_remove (threads, (gpointer)thread->tid);
+               ret = TRUE;
+       }
+
+       mono_threads_unlock ();
+
+       /* Don't close the handle here, wait for the object finalizer
+        * to do it. Otherwise, the following race condition applies:
+        *
+        * 1) Thread exits (and thread_cleanup() closes the handle)
+        *
+        * 2) Some other handle is reassigned the same slot
+        *
+        * 3) Another thread tries to join the first thread, and
+        * blocks waiting for the reassigned handle to be signalled
+        * (which might never happen).  This is possible, because the
+        * thread calling Join() still has a reference to the first
+        * thread's object.
+        */
+
        /* if the thread is not in the hash it has been removed already */
-       if (!handle_remove (thread)) {
+       if (!ret) {
                if (thread == mono_thread_internal_current ()) {
                        mono_domain_unset ();
                        mono_memory_barrier ();
                }
-               /* This needs to be called even if handle_remove () fails */
                if (mono_thread_cleanup_fn)
                        mono_thread_cleanup_fn (thread_get_tid (thread));
                return;
@@ -604,7 +550,6 @@ new_thread_with_internal (MonoDomain *domain, MonoInternalThread *internal)
        MonoThread *thread;
 
        thread = create_thread_object (domain);
-       thread->priority = MONO_THREAD_PRIORITY_NORMAL;
 
        MONO_OBJECT_SETREF (thread, internal_thread, internal);
 
@@ -633,88 +578,226 @@ create_internal_thread (void)
                MONO_GC_REGISTER_ROOT_PINNING (thread->thread_pinning_ref, MONO_ROOT_SOURCE_THREADING, "thread pinning reference");
        }
 
+       thread->priority = MONO_THREAD_PRIORITY_NORMAL;
+
        return thread;
 }
 
+static void
+mono_thread_internal_set_priority (MonoInternalThread *internal, MonoThreadPriority priority)
+{
+       g_assert (internal);
+       g_assert (internal->handle);
+
+       g_assert (priority >= MONO_THREAD_PRIORITY_LOWEST);
+       g_assert (priority <= MONO_THREAD_PRIORITY_HIGHEST);
+       g_assert (MONO_THREAD_PRIORITY_LOWEST < MONO_THREAD_PRIORITY_HIGHEST);
+
+#ifdef HOST_WIN32
+       BOOL res;
+
+       res = SetThreadPriority (internal->handle, priority - 2);
+       if (!res)
+               g_error ("%s: SetThreadPriority failed, error %d", __func__, GetLastError ());
+#else /* HOST_WIN32 */
+       pthread_t tid;
+       int policy;
+       struct sched_param param;
+       gint res;
+
+       tid = thread_get_tid (internal);
+
+       res = pthread_getschedparam (tid, &policy, &param);
+       if (res != 0)
+               g_error ("%s: pthread_getschedparam failed, error: \"%s\" (%d)", __func__, g_strerror (res), res);
+
+#ifdef _POSIX_PRIORITY_SCHEDULING
+       int max, min;
+
+       /* Necessary to get valid priority range */
+
+       min = sched_get_priority_min (policy);
+       max = sched_get_priority_max (policy);
+
+       if (max > 0 && min >= 0 && max > min) {
+               double srange, drange, sposition, dposition;
+               srange = MONO_THREAD_PRIORITY_HIGHEST - MONO_THREAD_PRIORITY_LOWEST;
+               drange = max - min;
+               sposition = priority - MONO_THREAD_PRIORITY_LOWEST;
+               dposition = (sposition / srange) * drange;
+               param.sched_priority = (int)(dposition + min);
+       } else
+#endif
+       {
+               switch (policy) {
+               case SCHED_FIFO:
+               case SCHED_RR:
+                       param.sched_priority = 50;
+                       break;
+#ifdef SCHED_BATCH
+               case SCHED_BATCH:
+#endif
+               case SCHED_OTHER:
+                       param.sched_priority = 0;
+                       break;
+               default:
+                       g_error ("%s: unknown policy %d", __func__, policy);
+               }
+       }
+
+       res = pthread_setschedparam (tid, policy, &param);
+       if (res != 0) {
+               if (res == EPERM) {
+                       g_warning ("%s: pthread_setschedparam failed, error: \"%s\" (%d)", __func__, g_strerror (res), res);
+                       return;
+               }
+               g_error ("%s: pthread_setschedparam failed, error: \"%s\" (%d)", __func__, g_strerror (res), res);
+       }
+#endif /* HOST_WIN32 */
+}
+
+static void 
+mono_alloc_static_data (gpointer **static_data_ptr, guint32 offset, gboolean threadlocal);
+
 static gboolean
-init_root_domain_thread (MonoInternalThread *thread, MonoThread *candidate)
+mono_thread_attach_internal (MonoThread *thread, gboolean force_attach, gboolean force_domain, gsize *stack_ptr)
 {
-       MonoDomain *domain = mono_get_root_domain ();
+       MonoThreadInfo *info;
+       MonoInternalThread *internal;
+       MonoDomain *domain, *root_domain;
+
+       g_assert (thread);
+
+       info = mono_thread_info_current ();
+
+       internal = thread->internal_thread;
+       internal->handle = mono_thread_info_duplicate_handle (info);
+       internal->tid = MONO_NATIVE_THREAD_ID_TO_UINT (mono_native_thread_id_get ());
+       internal->thread_info = info;
+       internal->small_id = info->small_id;
+       internal->stack_ptr = stack_ptr;
+
+       THREAD_DEBUG (g_message ("%s: (%"G_GSIZE_FORMAT") Setting current_object_key to %p", __func__, mono_native_thread_id_get (), internal));
+
+       SET_CURRENT_OBJECT (internal);
+
+       domain = mono_object_domain (thread);
 
-       if (!candidate || candidate->obj.vtable->domain != domain) {
-               candidate = new_thread_with_internal (domain, thread);
+       mono_thread_push_appdomain_ref (domain);
+       if (!mono_domain_set (domain, force_domain)) {
+               mono_thread_pop_appdomain_ref ();
+               return FALSE;
+       }
+
+       mono_threads_lock ();
+
+       if (threads_starting_up)
+               mono_g_hash_table_remove (threads_starting_up, thread);
+
+       if (shutting_down && !force_attach) {
+               mono_threads_unlock ();
+               return FALSE;
+       }
+
+       if (!threads) {
+               MONO_GC_REGISTER_ROOT_FIXED (threads, MONO_ROOT_SOURCE_THREADING, "threads table");
+               threads = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_THREADING, "threads table");
+       }
+
+       /* We don't need to duplicate thread->handle, because it is
+        * only closed when the thread object is finalized by the GC. */
+       mono_g_hash_table_insert (threads, (gpointer)(gsize)(internal->tid), internal);
+
+       /* We have to do this here because mono_thread_start_cb
+        * requires that root_domain_thread is set up. */
+       if (thread_static_info.offset || thread_static_info.idx > 0) {
+               /* get the current allocated size */
+               guint32 offset = MAKE_SPECIAL_STATIC_OFFSET (thread_static_info.idx, thread_static_info.offset, 0);
+               mono_alloc_static_data (&internal->static_data, offset, TRUE);
        }
-       set_current_thread_for_domain (domain, thread, candidate);
-       g_assert (!thread->root_domain_thread);
-       MONO_OBJECT_SETREF (thread, root_domain_thread, candidate);
+
+       mono_threads_unlock ();
+
+       root_domain = mono_get_root_domain ();
+
+       g_assert (!internal->root_domain_thread);
+       if (domain != root_domain)
+               MONO_OBJECT_SETREF (internal, root_domain_thread, new_thread_with_internal (root_domain, internal));
+       else
+               MONO_OBJECT_SETREF (internal, root_domain_thread, thread);
+
+       if (domain != root_domain)
+               set_current_thread_for_domain (root_domain, internal, internal->root_domain_thread);
+
+       set_current_thread_for_domain (domain, internal, thread);
+
+       THREAD_DEBUG (g_message ("%s: Attached thread ID %"G_GSIZE_FORMAT" (handle %p)", __func__, internal->tid, internal->handle));
+
        return TRUE;
 }
 
-static guint32 WINAPI start_wrapper_internal(void *data)
+typedef struct {
+       gint32 ref;
+       MonoThread *thread;
+       MonoObject *start_delegate;
+       MonoObject *start_delegate_arg;
+       MonoThreadStart start_func;
+       gpointer start_func_arg;
+       gboolean failed;
+       MonoCoopSem registered;
+} StartInfo;
+
+static guint32 WINAPI start_wrapper_internal(StartInfo *start_info, gsize *stack_ptr)
 {
        MonoError error;
-       MonoThreadInfo *info;
-       StartInfo *start_info = (StartInfo *)data;
-       guint32 (*start_func)(void *);
-       void *start_arg;
+       MonoThreadStart start_func;
+       void *start_func_arg;
        gsize tid;
        /* 
-        * We don't create a local to hold start_info->obj, so hopefully it won't get pinned during a
+        * We don't create a local to hold start_info->thread, so hopefully it won't get pinned during a
         * GC stack walk.
         */
-       MonoInternalThread *internal = start_info->obj->internal_thread;
-       MonoObject *start_delegate = start_info->delegate;
-       MonoDomain *domain = start_info->obj->obj.vtable->domain;
+       MonoThread *thread;
+       MonoInternalThread *internal;
+       MonoObject *start_delegate;
+       MonoObject *start_delegate_arg;
+       MonoDomain *domain;
+
+       thread = start_info->thread;
+       internal = thread->internal_thread;
+       domain = mono_object_domain (start_info->thread);
 
        THREAD_DEBUG (g_message ("%s: (%"G_GSIZE_FORMAT") Start wrapper", __func__, mono_native_thread_id_get ()));
 
-       /* We can be sure start_info->obj->tid and
-        * start_info->obj->handle have been set, because the thread
-        * was created suspended, and these values were set before the
-        * thread resumed
-        */
+       if (!mono_thread_attach_internal (thread, FALSE, FALSE, stack_ptr)) {
+               start_info->failed = TRUE;
 
-       info = mono_thread_info_current ();
-       g_assert (info);
-       internal->thread_info = info;
-       internal->small_id = info->small_id;
-
-       tid = internal->tid;
+               mono_coop_sem_post (&start_info->registered);
 
-       SET_CURRENT_OBJECT (internal);
+               if (InterlockedDecrement (&start_info->ref) == 0) {
+                       mono_coop_sem_destroy (&start_info->registered);
+                       g_free (start_info);
+               }
 
-       /* Every thread references the appdomain which created it */
-       mono_thread_push_appdomain_ref (domain);
-       
-       if (!mono_domain_set (domain, FALSE)) {
-               /* No point in raising an appdomain_unloaded exception here */
-               /* FIXME: Cleanup here */
-               mono_thread_pop_appdomain_ref ();
                return 0;
        }
 
-       start_func = start_info->func;
-       start_arg = start_info->obj->start_obj;
-       if (!start_arg)
-               start_arg = start_info->start_arg;
+       mono_thread_internal_set_priority (internal, internal->priority);
 
-       /* We have to do this here because mono_thread_new_init()
-          requires that root_domain_thread is set up. */
-       thread_adjust_static_data (internal);
-       init_root_domain_thread (internal, start_info->obj);
+       tid = internal->tid;
+
+       start_delegate = start_info->start_delegate;
+       start_delegate_arg = start_info->start_delegate_arg;
+       start_func = start_info->start_func;
+       start_func_arg = start_info->start_func_arg;
 
        /* This MUST be called before any managed code can be
         * executed, as it calls the callback function that (for the
         * jit) sets the lmf marker.
         */
-       mono_thread_new_init (tid, &tid, start_func);
-       internal->stack_ptr = &tid;
-       if (domain != mono_get_root_domain ())
-               set_current_thread_for_domain (domain, internal, start_info->obj);
-
-       LIBGC_DEBUG (g_message ("%s: (%"G_GSIZE_FORMAT",%d) Setting thread stack to %p", __func__, mono_native_thread_id_get (), getpid (), thread->stack_ptr));
 
-       THREAD_DEBUG (g_message ("%s: (%"G_GSIZE_FORMAT") Setting current_object_key to %p", __func__, mono_native_thread_id_get (), internal));
+       if (mono_thread_start_cb)
+               mono_thread_start_cb (tid, stack_ptr, start_func);
 
        /* On 2.0 profile (and higher), set explicitly since state might have been
           Unknown */
@@ -723,21 +806,16 @@ static guint32 WINAPI start_wrapper_internal(void *data)
 
        mono_thread_init_apartment_state ();
 
-       if (internal->start_notify)
-               /* Let the thread that called Start() know we're
-                * ready
-                */
-               mono_coop_sem_post (internal->start_notify);
+       /* Let the thread that called Start() know we're ready */
+       mono_coop_sem_post (&start_info->registered);
 
-       if (InterlockedDecrement ((gint32*)&internal->start_notify_refcount) == 0) {
-               mono_coop_sem_destroy (internal->start_notify);
-               g_free (internal->start_notify);
-               internal->start_notify = NULL;
+       if (InterlockedDecrement (&start_info->ref) == 0) {
+               mono_coop_sem_destroy (&start_info->registered);
+               g_free (start_info);
        }
 
-       g_free (start_info);
-       THREAD_DEBUG (g_message ("%s: start_wrapper for %"G_GSIZE_FORMAT, __func__,
-                                                        internal->tid));
+       /* start_info is not valid anymore */
+       start_info = NULL;
 
        /* 
         * Call this after calling start_notify, since the profiler callback might want
@@ -756,12 +834,14 @@ static guint32 WINAPI start_wrapper_internal(void *data)
 
        /* start_func is set only for unmanaged start functions */
        if (start_func) {
-               start_func (start_arg);
+               start_func (start_func_arg);
        } else {
                void *args [1];
+
                g_assert (start_delegate != NULL);
-               args [0] = start_arg;
+
                /* we may want to handle the exception here. See comment below on unhandled exceptions */
+               args [0] = (gpointer) start_delegate_arg;
                mono_runtime_delegate_invoke_checked (start_delegate, args, &error);
 
                if (!mono_error_ok (&error)) {
@@ -813,12 +893,12 @@ static guint32 WINAPI start_wrapper_internal(void *data)
 
 static gsize WINAPI start_wrapper(void *data)
 {
-       volatile int dummy;
+       volatile gsize dummy;
 
        /* Avoid scanning the frames above this frame during a GC */
        mono_gc_set_stack_end ((void*)&dummy);
 
-       return start_wrapper_internal (data);
+       return start_wrapper_internal ((StartInfo*) data, (gsize*) &dummy);
 }
 
 /*
@@ -828,12 +908,18 @@ static gsize WINAPI start_wrapper(void *data)
  * LOCKING: Acquires the threads lock.
  */
 static gboolean
-create_thread (MonoThread *thread, MonoInternalThread *internal, StartInfo *start_info, gboolean threadpool_thread, guint32 stack_size,
-                          MonoError *error)
+create_thread (MonoThread *thread, MonoInternalThread *internal, MonoObject *start_delegate, MonoThreadStart start_func, gpointer start_func_arg,
+       gboolean threadpool_thread, guint32 stack_size, MonoError *error)
 {
+       StartInfo *start_info = NULL;
        HANDLE thread_handle;
        MonoNativeThreadId tid;
-       MonoThreadParm tp;
+       gboolean ret;
+
+       if (start_delegate)
+               g_assert (!start_func && !start_func_arg);
+       if (start_func)
+               g_assert (!start_delegate);
 
        /*
         * Join joinable threads to prevent running out of threads since the finalizer
@@ -845,7 +931,6 @@ create_thread (MonoThread *thread, MonoInternalThread *internal, StartInfo *star
 
        mono_threads_lock ();
        if (shutting_down) {
-               g_free (start_info);
                mono_threads_unlock ();
                return FALSE;
        }
@@ -856,69 +941,61 @@ create_thread (MonoThread *thread, MonoInternalThread *internal, StartInfo *star
        mono_g_hash_table_insert (threads_starting_up, thread, thread);
        mono_threads_unlock ();
 
-       internal->start_notify = g_new0 (MonoCoopSem, 1);
-       mono_coop_sem_init (internal->start_notify, 0);
-       internal->start_notify_refcount = 2;
+       internal->threadpool_thread = threadpool_thread;
+       if (threadpool_thread)
+               mono_thread_set_state (internal, ThreadState_Background);
+
+       start_info = g_new0 (StartInfo, 1);
+       start_info->ref = 2;
+       start_info->thread = thread;
+       start_info->start_delegate = start_delegate;
+       start_info->start_delegate_arg = thread->start_obj;
+       start_info->start_func = start_func;
+       start_info->start_func_arg = start_func_arg;
+       start_info->failed = FALSE;
+       mono_coop_sem_init (&start_info->registered, 0);
 
        if (stack_size == 0)
                stack_size = default_stacksize_for_thread (internal);
 
-       /* Create suspended, so we can do some housekeeping before the thread
-        * starts
-        */
-       tp.priority = thread->priority;
-       tp.stack_size = stack_size;
-       tp.creation_flags = CREATE_SUSPENDED;
-
-       thread_handle = mono_threads_create_thread (start_wrapper, start_info, &tp, &tid);
+       thread_handle = mono_threads_create_thread (start_wrapper, start_info, stack_size, &tid);
 
        if (thread_handle == NULL) {
                /* The thread couldn't be created, so set an exception */
                mono_threads_lock ();
                mono_g_hash_table_remove (threads_starting_up, thread);
                mono_threads_unlock ();
-               g_free (start_info);
                mono_error_set_execution_engine (error, "Couldn't create thread. Error 0x%x", GetLastError());
-               return FALSE;
+               /* ref is not going to be decremented in start_wrapper_internal */
+               InterlockedDecrement (&start_info->ref);
+               ret = FALSE;
+               goto done;
        }
-       THREAD_DEBUG (g_message ("%s: Started thread ID %"G_GSIZE_FORMAT" (handle %p)", __func__, tid, thread_handle));
-
-       internal->handle = thread_handle;
-       internal->tid = MONO_NATIVE_THREAD_ID_TO_UINT (tid);
-
-       internal->threadpool_thread = threadpool_thread;
-       if (threadpool_thread)
-               mono_thread_set_state (internal, ThreadState_Background);
 
        THREAD_DEBUG (g_message ("%s: (%"G_GSIZE_FORMAT") Launching thread %p (%"G_GSIZE_FORMAT")", __func__, mono_native_thread_id_get (), internal, (gsize)internal->tid));
 
-       /* Only store the handle when the thread is about to be
-        * launched, to avoid the main thread deadlocking while trying
-        * to clean up a thread that will never be signalled.
-        */
-       if (!handle_store (thread, FALSE))
-               return FALSE;
-
-       mono_thread_info_resume (tid);
-
        /*
         * Wait for the thread to set up its TLS data etc, so
         * theres no potential race condition if someone tries
         * to look up the data believing the thread has
         * started
         */
-       THREAD_DEBUG (g_message ("%s: (%"G_GSIZE_FORMAT") waiting for thread %p (%"G_GSIZE_FORMAT") to start", __func__, mono_native_thread_id_get (), internal, (gsize)internal->tid));
 
-       mono_coop_sem_wait (internal->start_notify, MONO_SEM_FLAGS_NONE);
-       if (InterlockedDecrement ((gint32*)&internal->start_notify_refcount) == 0) {
-               mono_coop_sem_destroy (internal->start_notify);
-               g_free (internal->start_notify);
-               internal->start_notify = NULL;
-       }
+       mono_coop_sem_wait (&start_info->registered, MONO_SEM_FLAGS_NONE);
+
+       mono_threads_close_thread_handle (thread_handle);
 
        THREAD_DEBUG (g_message ("%s: (%"G_GSIZE_FORMAT") Done launching thread %p (%"G_GSIZE_FORMAT")", __func__, mono_native_thread_id_get (), internal, (gsize)internal->tid));
 
-       return TRUE;
+       ret = !start_info->failed;
+
+done:
+       if (InterlockedDecrement (&start_info->ref) == 0) {
+               mono_coop_sem_destroy (&start_info->registered);
+               g_free (start_info);
+       }
+
+       return ret;
 }
 
 void mono_thread_new_init (intptr_t tid, gpointer stack_start, gpointer func)
@@ -948,31 +1025,22 @@ mono_thread_create_internal (MonoDomain *domain, gpointer func, gpointer arg, gb
 {
        MonoThread *thread;
        MonoInternalThread *internal;
-       StartInfo *start_info;
        gboolean res;
 
        mono_error_init (error);
 
        thread = create_thread_object (domain);
-       thread->priority = MONO_THREAD_PRIORITY_NORMAL;
 
        internal = create_internal_thread ();
 
        MONO_OBJECT_SETREF (thread, internal_thread, internal);
 
-       start_info = g_new0 (StartInfo, 1);
-       start_info->func = (guint32 (*)(void *))func;
-       start_info->obj = thread;
-       start_info->start_arg = arg;
+       LOCK_THREAD (internal);
 
-       res = create_thread (thread, internal, start_info, threadpool_thread, stack_size, error);
+       res = create_thread (thread, internal, NULL, (MonoThreadStart) func, arg, threadpool_thread, stack_size, error);
        return_val_if_nok (error, NULL);
 
-       /* Check that the managed and unmanaged layout of MonoInternalThread matches */
-#ifndef MONO_CROSS_COMPILE
-       if (mono_check_corlib_version () == NULL)
-               g_assert (((char*)&internal->abort_protected_block_count - (char*)internal) == mono_defaults.internal_thread_class->fields [mono_defaults.internal_thread_class->field.count - 1].offset);
-#endif
+       UNLOCK_THREAD (internal);
 
        return internal;
 }
@@ -1002,12 +1070,12 @@ mono_thread_attach (MonoDomain *domain)
 MonoThread *
 mono_thread_attach_full (MonoDomain *domain, gboolean force_attach)
 {
-       MonoThreadInfo *info;
-       MonoInternalThread *thread;
-       MonoThread *current_thread;
+       MonoInternalThread *internal;
+       MonoThread *thread;
        MonoNativeThreadId tid;
+       gsize stack_ptr;
 
-       if ((thread = mono_thread_internal_current ())) {
+       if ((internal = mono_thread_internal_current ())) {
                if (domain != mono_domain_get ())
                        mono_domain_set (domain, TRUE);
                /* Already attached */
@@ -1018,40 +1086,19 @@ mono_thread_attach_full (MonoDomain *domain, gboolean force_attach)
                g_error ("Thread %"G_GSIZE_FORMAT" calling into managed code is not registered with the GC. On UNIX, this can be fixed by #include-ing <gc.h> before <pthread.h> in the file containing the thread creation code.", mono_native_thread_id_get ());
        }
 
-       info = mono_thread_info_current ();
-
        tid=mono_native_thread_id_get ();
 
-       thread = create_internal_thread ();
-       thread->handle = mono_thread_info_get_handle (info);
-       thread->tid = MONO_NATIVE_THREAD_ID_TO_UINT (tid);
-       thread->stack_ptr = &tid;
-
-       THREAD_DEBUG (g_message ("%s: Attached thread ID %"G_GSIZE_FORMAT" (handle %p)", __func__, tid, thread->handle));
-
-       thread->thread_info = info;
-       thread->small_id = info->small_id;
+       internal = create_internal_thread ();
 
-       current_thread = new_thread_with_internal (domain, thread);
+       thread = new_thread_with_internal (domain, internal);
 
-       if (!handle_store (current_thread, force_attach)) {
+       if (!mono_thread_attach_internal (thread, force_attach, TRUE, &stack_ptr)) {
                /* Mono is shutting down, so just wait for the end */
                for (;;)
                        mono_thread_info_sleep (10000, NULL);
        }
 
-       THREAD_DEBUG (g_message ("%s: (%"G_GSIZE_FORMAT") Setting current_object_key to %p", __func__, mono_native_thread_id_get (), thread));
-
-       SET_CURRENT_OBJECT (thread);
-       mono_domain_set (domain, TRUE);
-
-       thread_adjust_static_data (thread);
-
-       init_root_domain_thread (thread, current_thread);
-
-       if (domain != mono_get_root_domain ())
-               set_current_thread_for_domain (domain, thread, current_thread);
-
+       THREAD_DEBUG (g_message ("%s: Attached thread ID %"G_GSIZE_FORMAT" (handle %p)", __func__, tid, internal->handle));
 
        if (mono_thread_attach_cb) {
                guint8 *staddr;
@@ -1060,17 +1107,17 @@ mono_thread_attach_full (MonoDomain *domain, gboolean force_attach)
                mono_thread_info_get_stack_bounds (&staddr, &stsize);
 
                if (staddr == NULL)
-                       mono_thread_attach_cb (MONO_NATIVE_THREAD_ID_TO_UINT (tid), &tid);
+                       mono_thread_attach_cb (MONO_NATIVE_THREAD_ID_TO_UINT (tid), &stack_ptr);
                else
                        mono_thread_attach_cb (MONO_NATIVE_THREAD_ID_TO_UINT (tid), staddr + stsize);
        }
 
        /* Can happen when we attach the profiler helper thread in order to heapshot. */
-       if (!info->tools_thread)
+       if (!mono_thread_info_current ()->tools_thread)
                // FIXME: Need a separate callback
                mono_profiler_thread_start (MONO_NATIVE_THREAD_ID_TO_UINT (tid));
 
-       return current_thread;
+       return thread;
 }
 
 void
@@ -1155,7 +1202,6 @@ ves_icall_System_Threading_Thread_Thread_internal (MonoThread *this_obj,
                                                                                                   MonoObject *start)
 {
        MonoError error;
-       StartInfo *start_info;
        MonoInternalThread *internal;
        gboolean res;
 
@@ -1177,15 +1223,8 @@ ves_icall_System_Threading_Thread_Thread_internal (MonoThread *this_obj,
                UNLOCK_THREAD (internal);
                return this_obj;
        }
-       /* This is freed in start_wrapper */
-       start_info = g_new0 (StartInfo, 1);
-       start_info->func = NULL;
-       start_info->start_arg = NULL;
-       start_info->delegate = start;
-       start_info->obj = this_obj;
-       g_assert (this_obj->obj.vtable->domain == mono_domain_get ());
 
-       res = create_thread (this_obj, internal, start_info, FALSE, 0, &error);
+       res = create_thread (this_obj, internal, start, NULL, NULL, FALSE, 0, &error);
        if (!res) {
                mono_error_cleanup (&error);
                UNLOCK_THREAD (internal);
@@ -1441,11 +1480,9 @@ ves_icall_System_Threading_Thread_GetPriority (MonoThread *this_obj)
        MonoInternalThread *internal = this_obj->internal_thread;
 
        LOCK_THREAD (internal);
-       if (internal->handle != NULL)
-               priority = mono_thread_info_get_priority ((MonoThreadInfo*) internal->thread_info);
-       else
-               priority = this_obj->priority;
+       priority = internal->priority;
        UNLOCK_THREAD (internal);
+
        return priority;
 }
 
@@ -1462,9 +1499,9 @@ ves_icall_System_Threading_Thread_SetPriority (MonoThread *this_obj, int priorit
        MonoInternalThread *internal = this_obj->internal_thread;
 
        LOCK_THREAD (internal);
-       this_obj->priority = priority;
+       internal->priority = priority;
        if (internal->handle != NULL)
-               mono_thread_info_set_priority ((MonoThreadInfo*) internal->thread_info, this_obj->priority);
+               mono_thread_internal_set_priority (internal, priority);
        UNLOCK_THREAD (internal);
 }
 
@@ -1786,123 +1823,6 @@ ves_icall_System_Threading_WaitHandle_SignalAndWait_Internal (HANDLE toSignal, H
        return map_native_wait_result_to_managed (ret);
 }
 
-HANDLE ves_icall_System_Threading_Mutex_CreateMutex_internal (MonoBoolean owned, MonoString *name, MonoBoolean *created)
-{ 
-       HANDLE mutex;
-       
-       *created = TRUE;
-       
-       if (name == NULL) {
-               mutex = CreateMutex (NULL, owned, NULL);
-       } else {
-               mutex = CreateMutex (NULL, owned, mono_string_chars (name));
-               
-               if (GetLastError () == ERROR_ALREADY_EXISTS) {
-                       *created = FALSE;
-               }
-       }
-
-       return(mutex);
-}                                                                   
-
-MonoBoolean ves_icall_System_Threading_Mutex_ReleaseMutex_internal (HANDLE handle ) { 
-       return(ReleaseMutex (handle));
-}
-
-HANDLE ves_icall_System_Threading_Mutex_OpenMutex_internal (MonoString *name,
-                                                           gint32 rights,
-                                                           gint32 *error)
-{
-       HANDLE ret;
-       
-       *error = ERROR_SUCCESS;
-       
-       ret = OpenMutex (rights, FALSE, mono_string_chars (name));
-       if (ret == NULL) {
-               *error = GetLastError ();
-       }
-       
-       return(ret);
-}
-
-
-HANDLE ves_icall_System_Threading_Semaphore_CreateSemaphore_internal (gint32 initialCount, gint32 maximumCount, MonoString *name, gint32 *error)
-{ 
-       HANDLE sem;
-       
-       if (name == NULL) {
-               sem = CreateSemaphore (NULL, initialCount, maximumCount, NULL);
-       } else {
-               sem = CreateSemaphore (NULL, initialCount, maximumCount,
-                                      mono_string_chars (name));
-       }
-
-       *error = GetLastError ();
-
-       return(sem);
-}                                                                   
-
-MonoBoolean ves_icall_System_Threading_Semaphore_ReleaseSemaphore_internal (HANDLE handle, gint32 releaseCount, gint32 *prevcount)
-{ 
-       return ReleaseSemaphore (handle, releaseCount, prevcount);
-}
-
-HANDLE ves_icall_System_Threading_Semaphore_OpenSemaphore_internal (MonoString *name, gint32 rights, gint32 *error)
-{
-       HANDLE sem;
-
-       sem = OpenSemaphore (rights, FALSE, mono_string_chars (name));
-
-       *error = GetLastError ();
-
-       return(sem);
-}
-
-HANDLE ves_icall_System_Threading_Events_CreateEvent_internal (MonoBoolean manual, MonoBoolean initial, MonoString *name, gint32 *error)
-{
-       HANDLE event;
-
-       if (name == NULL) {
-               event = CreateEvent (NULL, manual, initial, NULL);
-       } else {
-               event = CreateEvent (NULL, manual, initial,
-                                    mono_string_chars (name));
-       }
-
-       *error = GetLastError ();
-
-       return(event);
-}
-
-gboolean ves_icall_System_Threading_Events_SetEvent_internal (HANDLE handle) {
-       return (SetEvent(handle));
-}
-
-gboolean ves_icall_System_Threading_Events_ResetEvent_internal (HANDLE handle) {
-       return (ResetEvent(handle));
-}
-
-void
-ves_icall_System_Threading_Events_CloseEvent_internal (HANDLE handle) {
-       CloseHandle (handle);
-}
-
-HANDLE ves_icall_System_Threading_Events_OpenEvent_internal (MonoString *name,
-                                                            gint32 rights,
-                                                            gint32 *error)
-{
-       HANDLE ret;
-       
-       ret = OpenEvent (rights, FALSE, mono_string_chars (name));
-       if (ret == NULL) {
-               *error = GetLastError ();
-       } else {
-               *error = ERROR_SUCCESS;
-       }
-
-       return(ret);
-}
-
 gint32 ves_icall_System_Threading_Interlocked_Increment_Int (gint32 *location)
 {
        return InterlockedIncrement (location);
@@ -2147,7 +2067,7 @@ ves_icall_System_Threading_Thread_ClrState (MonoInternalThread* this_obj, guint3
                 * be notified, since it has to rebuild the list of threads to
                 * wait for.
                 */
-               SetEvent (background_change_event);
+               mono_w32event_set (background_change_event);
        }
 }
 
@@ -2161,7 +2081,7 @@ ves_icall_System_Threading_Thread_SetState (MonoInternalThread* this_obj, guint3
                 * be notified, since it has to rebuild the list of threads to
                 * wait for.
                 */
-               SetEvent (background_change_event);
+               mono_w32event_set (background_change_event);
        }
 }
 
@@ -2912,7 +2832,7 @@ void mono_thread_init (MonoThreadStartCB start_cb,
        mono_os_mutex_init_recursive(&interlocked_mutex);
        mono_os_mutex_init_recursive(&joinable_threads_mutex);
        
-       background_change_event = CreateEvent (NULL, TRUE, FALSE, NULL);
+       background_change_event = mono_w32event_create (TRUE, FALSE);
        g_assert(background_change_event != NULL);
        
        mono_init_static_data_info (&thread_static_info);
@@ -2929,6 +2849,9 @@ void mono_thread_init (MonoThreadStartCB start_cb,
         * anything up.
         */
        GetCurrentProcess ();
+
+       /* Check that the managed and unmanaged layout of MonoInternalThread matches */
+       g_assert (MONO_STRUCT_OFFSET (MonoInternalThread, last) == mono_field_get_offset (mono_class_get_field_from_name (mono_defaults.internal_thread_class, "last")));
 }
 
 void mono_thread_cleanup (void)
@@ -3224,7 +3147,7 @@ mono_threads_set_shutting_down (void)
                 * interrupt the main thread if it is waiting for all
                 * the other threads.
                 */
-               SetEvent (background_change_event);
+               mono_w32event_set (background_change_event);
                
                mono_threads_unlock ();
        }
@@ -3257,7 +3180,7 @@ void mono_thread_manage (void)
                THREAD_DEBUG (g_message ("%s: There are %d threads to join", __func__, mono_g_hash_table_size (threads));
                        mono_g_hash_table_foreach (threads, print_tids, NULL));
        
-               ResetEvent (background_change_event);
+               mono_w32event_reset (background_change_event);
                wait->num=0;
                /*We must zero all InternalThread pointers to avoid making the GC unhappy.*/
                memset (wait->threads, 0, MONO_W32HANDLE_MAXIMUM_WAIT_OBJECTS * SIZEOF_VOID_P);
@@ -4134,22 +4057,6 @@ mono_alloc_static_data_slot (StaticDataInfo *static_data, guint32 size, guint32
        return offset;
 }
 
-/* 
- * ensure thread static fields already allocated are valid for thread
- * This function is called when a thread is created or on thread attach.
- */
-static void
-thread_adjust_static_data (MonoInternalThread *thread)
-{
-       mono_threads_lock ();
-       if (thread_static_info.offset || thread_static_info.idx > 0) {
-               /* get the current allocated size */
-               guint32 offset = MAKE_SPECIAL_STATIC_OFFSET (thread_static_info.idx, thread_static_info.offset, 0);
-               mono_alloc_static_data (&thread->static_data, offset, TRUE);
-       }
-       mono_threads_unlock ();
-}
-
 /*
  * LOCKING: requires that threads_mutex is held
  */
@@ -4692,6 +4599,29 @@ mono_thread_set_state (MonoInternalThread *thread, MonoThreadState state)
        UNLOCK_THREAD (thread);
 }
 
+/**
+ * mono_thread_test_and_set_state:
+ *
+ * Test if current state of @thread include @test. If it does not, OR @set into the state.
+ *
+ * Returns TRUE is @set was OR'd in.
+ */
+gboolean
+mono_thread_test_and_set_state (MonoInternalThread *thread, MonoThreadState test, MonoThreadState set)
+{
+       LOCK_THREAD (thread);
+
+       if ((thread->state & test) != 0) {
+               UNLOCK_THREAD (thread);
+               return FALSE;
+       }
+
+       thread->state |= set;
+       UNLOCK_THREAD (thread);
+
+       return TRUE;
+}
+
 void
 mono_thread_clr_state (MonoInternalThread *thread, MonoThreadState state)
 {
@@ -5217,4 +5147,26 @@ mono_thread_try_resume_interruption (void)
                return NULL;
 
        return mono_thread_resume_interruption ();
+}
+
+/* Returns TRUE if the current thread is ready to be interrupted. */
+gboolean
+mono_threads_is_ready_to_be_interrupted (void)
+{
+       MonoInternalThread *thread;
+
+       thread = mono_thread_internal_current ();
+       LOCK_THREAD (thread);
+       if (thread->state & (MonoThreadState)(ThreadState_StopRequested | ThreadState_SuspendRequested | ThreadState_AbortRequested)) {
+               UNLOCK_THREAD (thread);
+               return FALSE;
+       }
+
+       if (thread->abort_protected_block_count || mono_get_eh_callbacks ()->mono_current_thread_has_handle_block_guard ()) {
+               UNLOCK_THREAD (thread);
+               return FALSE;
+       }
+
+       UNLOCK_THREAD (thread);
+       return TRUE;
 }
\ No newline at end of file
diff --git a/mono/metadata/w32event-unix.c b/mono/metadata/w32event-unix.c
new file mode 100644 (file)
index 0000000..de99585
--- /dev/null
@@ -0,0 +1,411 @@
+/*
+ * w32event-unix.c: Runtime support for managed Event on Unix
+ *
+ * Author:
+ *     Ludovic Henry (luhenry@microsoft.com)
+ *
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
+ */
+
+#include "w32event.h"
+
+#include "w32handle-namespace.h"
+#include "mono/io-layer/io-layer.h"
+#include "mono/utils/mono-logger-internals.h"
+#include "mono/utils/w32handle.h"
+
+typedef struct {
+       gboolean manual;
+       guint32 set_count;
+} MonoW32HandleEvent;
+
+struct MonoW32HandleNamedEvent {
+       MonoW32HandleEvent e;
+       MonoW32HandleNamespace sharedns;
+};
+
+static gboolean event_handle_own (gpointer handle, MonoW32HandleType type)
+{
+       MonoW32HandleEvent *event_handle;
+       gboolean ok;
+
+       ok = mono_w32handle_lookup (handle, type, (gpointer *)&event_handle);
+       if (!ok) {
+               g_warning ("%s: error looking up %s handle %p",
+                       __func__, mono_w32handle_ops_typename (type), handle);
+               return FALSE;
+       }
+
+       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: owning %s handle %p",
+               __func__, mono_w32handle_ops_typename (type), handle);
+
+       if (!event_handle->manual) {
+               g_assert (event_handle->set_count > 0);
+               event_handle->set_count --;
+
+               if (event_handle->set_count == 0)
+                       mono_w32handle_set_signal_state (handle, FALSE, FALSE);
+       }
+
+       return TRUE;
+}
+
+static void event_signal(gpointer handle)
+{
+       ves_icall_System_Threading_Events_SetEvent_internal (handle);
+}
+
+static gboolean event_own (gpointer handle)
+{
+       return event_handle_own (handle, MONO_W32HANDLE_EVENT);
+}
+
+static void namedevent_signal (gpointer handle)
+{
+       ves_icall_System_Threading_Events_SetEvent_internal (handle);
+}
+
+/* NB, always called with the shared handle lock held */
+static gboolean namedevent_own (gpointer handle)
+{
+       return event_handle_own (handle, MONO_W32HANDLE_NAMEDEVENT);
+}
+
+static void event_details (gpointer data)
+{
+       MonoW32HandleEvent *event = (MonoW32HandleEvent *)data;
+       g_print ("manual: %s, set_count: %d",
+               event->manual ? "TRUE" : "FALSE", event->set_count);
+}
+
+static void namedevent_details (gpointer data)
+{
+       MonoW32HandleNamedEvent *namedevent = (MonoW32HandleNamedEvent *)data;
+       g_print ("manual: %s, set_count: %d, name: \"%s\"",
+               namedevent->e.manual ? "TRUE" : "FALSE", namedevent->e.set_count, namedevent->sharedns.name);
+}
+
+static const gchar* event_typename (void)
+{
+       return "Event";
+}
+
+static gsize event_typesize (void)
+{
+       return sizeof (MonoW32HandleEvent);
+}
+
+static const gchar* namedevent_typename (void)
+{
+       return "N.Event";
+}
+
+static gsize namedevent_typesize (void)
+{
+       return sizeof (MonoW32HandleNamedEvent);
+}
+
+void
+mono_w32event_init (void)
+{
+       static MonoW32HandleOps event_ops = {
+               NULL,                   /* close */
+               event_signal,           /* signal */
+               event_own,              /* own */
+               NULL,                   /* is_owned */
+               NULL,                   /* special_wait */
+               NULL,                   /* prewait */
+               event_details,  /* details */
+               event_typename, /* typename */
+               event_typesize, /* typesize */
+       };
+
+       static MonoW32HandleOps namedevent_ops = {
+               NULL,                   /* close */
+               namedevent_signal,      /* signal */
+               namedevent_own,         /* own */
+               NULL,                   /* is_owned */
+               NULL,                   /* special_wait */
+               NULL,                   /* prewait */
+               namedevent_details,     /* details */
+               namedevent_typename, /* typename */
+               namedevent_typesize, /* typesize */
+       };
+
+       mono_w32handle_register_ops (MONO_W32HANDLE_EVENT,      &event_ops);
+       mono_w32handle_register_ops (MONO_W32HANDLE_NAMEDEVENT, &namedevent_ops);
+
+       mono_w32handle_register_capabilities (MONO_W32HANDLE_EVENT,
+               (MonoW32HandleCapability)(MONO_W32HANDLE_CAP_WAIT | MONO_W32HANDLE_CAP_SIGNAL));
+       mono_w32handle_register_capabilities (MONO_W32HANDLE_NAMEDEVENT,
+               (MonoW32HandleCapability)(MONO_W32HANDLE_CAP_WAIT | MONO_W32HANDLE_CAP_SIGNAL));
+}
+
+gpointer
+mono_w32event_create (gboolean manual, gboolean initial)
+{
+       gpointer handle;
+       gint32 error;
+
+       handle = ves_icall_System_Threading_Events_CreateEvent_internal (manual, initial, NULL, &error);
+       if (error != ERROR_SUCCESS)
+               g_assert (!handle);
+
+       return handle;
+}
+
+void
+mono_w32event_set (gpointer handle)
+{
+       ves_icall_System_Threading_Events_SetEvent_internal (handle);
+}
+
+void
+mono_w32event_reset (gpointer handle)
+{
+       ves_icall_System_Threading_Events_ResetEvent_internal (handle);
+}
+
+static gpointer event_handle_create (MonoW32HandleEvent *event_handle, MonoW32HandleType type, gboolean manual, gboolean initial)
+{
+       gpointer handle;
+       int thr_ret;
+
+       event_handle->manual = manual;
+       event_handle->set_count = (initial && !manual) ? 1 : 0;
+
+       handle = mono_w32handle_new (type, event_handle);
+       if (handle == INVALID_HANDLE_VALUE) {
+               g_warning ("%s: error creating %s handle",
+                       __func__, mono_w32handle_ops_typename (type));
+               SetLastError (ERROR_GEN_FAILURE);
+               return NULL;
+       }
+
+       thr_ret = mono_w32handle_lock_handle (handle);
+       g_assert (thr_ret == 0);
+
+       if (initial)
+               mono_w32handle_set_signal_state (handle, TRUE, FALSE);
+
+       thr_ret = mono_w32handle_unlock_handle (handle);
+       g_assert (thr_ret == 0);
+
+       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: created %s handle %p",
+               __func__, mono_w32handle_ops_typename (type), handle);
+
+       return handle;
+}
+
+static gpointer event_create (gboolean manual, gboolean initial)
+{
+       MonoW32HandleEvent event_handle;
+       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: creating %s handle",
+               __func__, mono_w32handle_ops_typename (MONO_W32HANDLE_EVENT));
+       return event_handle_create (&event_handle, MONO_W32HANDLE_EVENT, manual, initial);
+}
+
+static gpointer namedevent_create (gboolean manual, gboolean initial, const gunichar2 *name G_GNUC_UNUSED)
+{
+       gpointer handle;
+       gchar *utf8_name;
+
+       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: creating %s handle",
+               __func__, mono_w32handle_ops_typename (MONO_W32HANDLE_NAMEDEVENT));
+
+       /* w32 seems to guarantee that opening named objects can't race each other */
+       mono_w32handle_namespace_lock ();
+
+       utf8_name = g_utf16_to_utf8 (name, -1, NULL, NULL, NULL);
+
+       handle = mono_w32handle_namespace_search_handle (MONO_W32HANDLE_NAMEDEVENT, utf8_name);
+       if (handle == INVALID_HANDLE_VALUE) {
+               /* The name has already been used for a different object. */
+               handle = NULL;
+               SetLastError (ERROR_INVALID_HANDLE);
+       } else if (handle) {
+               /* Not an error, but this is how the caller is informed that the event wasn't freshly created */
+               SetLastError (ERROR_ALREADY_EXISTS);
+
+               /* this is used as creating a new handle */
+               mono_w32handle_ref (handle);
+       } else {
+               /* A new named event */
+               MonoW32HandleNamedEvent namedevent_handle;
+
+               strncpy (&namedevent_handle.sharedns.name [0], utf8_name, MAX_PATH);
+               namedevent_handle.sharedns.name [MAX_PATH] = '\0';
+
+               handle = event_handle_create ((MonoW32HandleEvent*) &namedevent_handle, MONO_W32HANDLE_NAMEDEVENT, manual, initial);
+       }
+
+       g_free (utf8_name);
+
+       mono_w32handle_namespace_unlock ();
+
+       return handle;
+}
+
+gpointer
+ves_icall_System_Threading_Events_CreateEvent_internal (MonoBoolean manual, MonoBoolean initial, MonoString *name, gint32 *error)
+{
+       gpointer event;
+
+       /* Need to blow away any old errors here, because code tests
+        * for ERROR_ALREADY_EXISTS on success (!) to see if an event
+        * was freshly created */
+       SetLastError (ERROR_SUCCESS);
+
+       event = name ? namedevent_create (manual, initial, mono_string_chars (name)) : event_create (manual, initial);
+
+       *error = GetLastError ();
+
+       return event;
+}
+
+gboolean
+ves_icall_System_Threading_Events_SetEvent_internal (gpointer handle)
+{
+       MonoW32HandleType type;
+       MonoW32HandleEvent *event_handle;
+       int thr_ret;
+
+       if (handle == NULL) {
+               SetLastError (ERROR_INVALID_HANDLE);
+               return(FALSE);
+       }
+
+       switch (type = mono_w32handle_get_type (handle)) {
+       case MONO_W32HANDLE_EVENT:
+       case MONO_W32HANDLE_NAMEDEVENT:
+               break;
+       default:
+               SetLastError (ERROR_INVALID_HANDLE);
+               return FALSE;
+       }
+
+       if (!mono_w32handle_lookup (handle, type, (gpointer *)&event_handle)) {
+               g_warning ("%s: error looking up %s handle %p",
+                       __func__, mono_w32handle_ops_typename (type), handle);
+               return FALSE;
+       }
+
+       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: setting %s handle %p",
+               __func__, mono_w32handle_ops_typename (type), handle);
+
+       thr_ret = mono_w32handle_lock_handle (handle);
+       g_assert (thr_ret == 0);
+
+       if (!event_handle->manual) {
+               event_handle->set_count = 1;
+               mono_w32handle_set_signal_state (handle, TRUE, FALSE);
+       } else {
+               mono_w32handle_set_signal_state (handle, TRUE, TRUE);
+       }
+
+       thr_ret = mono_w32handle_unlock_handle (handle);
+       g_assert (thr_ret == 0);
+
+       return TRUE;
+}
+
+gboolean
+ves_icall_System_Threading_Events_ResetEvent_internal (gpointer handle)
+{
+       MonoW32HandleType type;
+       MonoW32HandleEvent *event_handle;
+       int thr_ret;
+
+       SetLastError (ERROR_SUCCESS);
+
+       if (handle == NULL) {
+               SetLastError (ERROR_INVALID_HANDLE);
+               return(FALSE);
+       }
+
+       switch (type = mono_w32handle_get_type (handle)) {
+       case MONO_W32HANDLE_EVENT:
+       case MONO_W32HANDLE_NAMEDEVENT:
+               break;
+       default:
+               SetLastError (ERROR_INVALID_HANDLE);
+               return FALSE;
+       }
+
+       if (!mono_w32handle_lookup (handle, type, (gpointer *)&event_handle)) {
+               g_warning ("%s: error looking up %s handle %p",
+                       __func__, mono_w32handle_ops_typename (type), handle);
+               return FALSE;
+       }
+
+       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: resetting %s handle %p",
+               __func__, mono_w32handle_ops_typename (type), handle);
+
+       thr_ret = mono_w32handle_lock_handle (handle);
+       g_assert (thr_ret == 0);
+
+       if (!mono_w32handle_issignalled (handle)) {
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: no need to reset %s handle %p",
+                       __func__, mono_w32handle_ops_typename (type), handle);
+       } else {
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: obtained write lock on %s handle %p",
+                       __func__, mono_w32handle_ops_typename (type), handle);
+
+               mono_w32handle_set_signal_state (handle, FALSE, FALSE);
+       }
+
+       event_handle->set_count = 0;
+
+       thr_ret = mono_w32handle_unlock_handle (handle);
+       g_assert (thr_ret == 0);
+
+       return TRUE;
+}
+
+void
+ves_icall_System_Threading_Events_CloseEvent_internal (gpointer handle)
+{
+       CloseHandle (handle);
+}
+
+gpointer
+ves_icall_System_Threading_Events_OpenEvent_internal (MonoString *name, gint32 rights G_GNUC_UNUSED, gint32 *error)
+{
+       gpointer handle;
+       gchar *utf8_name;
+
+       *error = ERROR_SUCCESS;
+
+       /* w32 seems to guarantee that opening named objects can't race each other */
+       mono_w32handle_namespace_lock ();
+
+       utf8_name = g_utf16_to_utf8 (mono_string_chars (name), -1, NULL, NULL, NULL);
+
+       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Opening named event [%s]", __func__, utf8_name);
+
+       handle = mono_w32handle_namespace_search_handle (MONO_W32HANDLE_NAMEDEVENT, utf8_name);
+       if (handle == INVALID_HANDLE_VALUE) {
+               /* The name has already been used for a different object. */
+               *error = ERROR_INVALID_HANDLE;
+               goto cleanup;
+       } else if (!handle) {
+               /* This name doesn't exist */
+               *error = ERROR_FILE_NOT_FOUND;
+               goto cleanup;
+       }
+
+       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: returning named event handle %p", __func__, handle);
+
+cleanup:
+       g_free (utf8_name);
+
+       mono_w32handle_namespace_unlock ();
+
+       return handle;
+}
+
+MonoW32HandleNamespace*
+mono_w32event_get_namespace (MonoW32HandleNamedEvent *event)
+{
+       return &event->sharedns;
+}
diff --git a/mono/metadata/w32event-win32.c b/mono/metadata/w32event-win32.c
new file mode 100644 (file)
index 0000000..8659021
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * w32event-win32.c: Runtime support for managed Event on Win32
+ *
+ * Author:
+ *     Ludovic Henry (luhenry@microsoft.com)
+ *
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
+ */
+
+#include "w32event.h"
+
+#include <windows.h>
+#include <winbase.h>
+
+void
+mono_w32event_init (void)
+{
+}
+
+gpointer
+mono_w32event_create (gboolean manual, gboolean initial)
+{
+       return CreateEvent (NULL, manual, initial, NULL);
+}
+
+void
+mono_w32event_set (gpointer handle)
+{
+       SetEvent (handle);
+}
+
+void
+mono_w32event_reset (gpointer handle)
+{
+       ResetEvent (handle);
+}
+
+gpointer
+ves_icall_System_Threading_Events_CreateEvent_internal (MonoBoolean manual, MonoBoolean initial, MonoString *name, gint32 *error)
+{
+       gpointer event;
+
+       event = CreateEvent (NULL, manual, initial, name ? mono_string_chars (name) : NULL);
+
+       *error = GetLastError ();
+
+       return event;
+}
+
+gboolean
+ves_icall_System_Threading_Events_SetEvent_internal (gpointer handle)
+{
+       return SetEvent (handle);
+}
+
+gboolean
+ves_icall_System_Threading_Events_ResetEvent_internal (gpointer handle)
+{
+       return ResetEvent (handle);
+}
+
+void
+ves_icall_System_Threading_Events_CloseEvent_internal (gpointer handle)
+{
+       CloseHandle (handle);
+}
+
+gpointer
+ves_icall_System_Threading_Events_OpenEvent_internal (MonoString *name, gint32 rights, gint32 *error)
+{
+       gpointer handle;
+
+       *error = ERROR_SUCCESS;
+
+       handle = OpenEvent (rights, FALSE, mono_string_chars (name));
+       if (!handle)
+               *error = GetLastError ();
+
+       return handle;
+}
diff --git a/mono/metadata/w32event.h b/mono/metadata/w32event.h
new file mode 100644 (file)
index 0000000..1f41b1a
--- /dev/null
@@ -0,0 +1,43 @@
+
+#ifndef _MONO_METADATA_W32EVENT_H_
+#define _MONO_METADATA_W32EVENT_H_
+
+#include <config.h>
+#include <glib.h>
+
+#include "object.h"
+#include "w32handle-namespace.h"
+
+void
+mono_w32event_init (void);
+
+gpointer
+mono_w32event_create (gboolean manual, gboolean initial);
+
+void
+mono_w32event_set (gpointer handle);
+
+void
+mono_w32event_reset (gpointer handle);
+
+gpointer
+ves_icall_System_Threading_Events_CreateEvent_internal (MonoBoolean manual, MonoBoolean initial, MonoString *name, gint32 *error);
+
+gboolean
+ves_icall_System_Threading_Events_SetEvent_internal (gpointer handle);
+
+gboolean
+ves_icall_System_Threading_Events_ResetEvent_internal (gpointer handle);
+
+void
+ves_icall_System_Threading_Events_CloseEvent_internal (gpointer handle);
+
+gpointer
+ves_icall_System_Threading_Events_OpenEvent_internal (MonoString *name, gint32 rights, gint32 *error);
+
+typedef struct MonoW32HandleNamedEvent MonoW32HandleNamedEvent;
+
+MonoW32HandleNamespace*
+mono_w32event_get_namespace (MonoW32HandleNamedEvent *event);
+
+#endif /* _MONO_METADATA_W32EVENT_H_ */
diff --git a/mono/metadata/w32handle-namespace.c b/mono/metadata/w32handle-namespace.c
new file mode 100644 (file)
index 0000000..23a936b
--- /dev/null
@@ -0,0 +1,119 @@
+/*
+ * w32handle-namespace.c: namespace for w32handles
+ *
+ * Author:
+ *     Ludovic Henry (luhenry@microsoft.com)
+ *
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
+ */
+
+#include <config.h>
+
+#ifndef HOST_WIN32
+
+#include "w32handle-namespace.h"
+
+#include "w32mutex.h"
+#include "w32semaphore.h"
+#include "w32event.h"
+#include "mono/io-layer/io-layer.h"
+#include "mono/utils/mono-logger-internals.h"
+#include "mono/utils/mono-coop-mutex.h"
+
+static MonoCoopMutex lock;
+
+void
+mono_w32handle_namespace_init (void)
+{
+       mono_coop_mutex_init (&lock);
+}
+
+void
+mono_w32handle_namespace_lock (void)
+{
+       mono_coop_mutex_lock (&lock);
+}
+
+void
+mono_w32handle_namespace_unlock (void)
+{
+       mono_coop_mutex_unlock (&lock);
+}
+
+static gboolean
+has_namespace (MonoW32HandleType type)
+{
+       switch (type) {
+       case MONO_W32HANDLE_NAMEDMUTEX:
+       case MONO_W32HANDLE_NAMEDSEM:
+       case MONO_W32HANDLE_NAMEDEVENT:
+               return TRUE;
+       default:
+               return FALSE;
+       }
+}
+
+typedef struct {
+       gpointer ret;
+       MonoW32HandleType type;
+       gchar *name;
+} NamespaceSearchHandleData;
+
+static gboolean
+mono_w32handle_namespace_search_handle_callback (gpointer handle, gpointer data, gpointer user_data)
+{
+       NamespaceSearchHandleData *search_data;
+       MonoW32HandleType type;
+       MonoW32HandleNamespace *sharedns;
+
+       type = mono_w32handle_get_type (handle);
+       if (!has_namespace (type))
+               return FALSE;
+
+       search_data = (NamespaceSearchHandleData*) user_data;
+
+       switch (type) {
+       case MONO_W32HANDLE_NAMEDMUTEX: sharedns = mono_w32mutex_get_namespace ((MonoW32HandleNamedMutex*) data); break;
+       case MONO_W32HANDLE_NAMEDSEM:   sharedns = mono_w32semaphore_get_namespace ((MonoW32HandleNamedSemaphore*) data); break;
+       case MONO_W32HANDLE_NAMEDEVENT: sharedns = mono_w32event_get_namespace ((MonoW32HandleNamedEvent*) data); break;
+       default:
+               g_assert_not_reached ();
+       }
+
+       if (strcmp (sharedns->name, search_data->name) == 0) {
+               if (type != search_data->type) {
+                       /* Its the wrong type, so fail now */
+                       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p matches name but is wrong type: %s",
+                               __func__, handle, mono_w32handle_ops_typename (type));
+                       search_data->ret = INVALID_HANDLE_VALUE;
+               } else {
+                       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p matches name and type",
+                               __func__, handle);
+                       search_data->ret = handle;
+               }
+
+               return TRUE;
+       }
+
+       return FALSE;
+}
+
+gpointer
+mono_w32handle_namespace_search_handle (MonoW32HandleType type, gchar *name)
+{
+       NamespaceSearchHandleData search_data;
+
+       if (!has_namespace (type))
+               g_error ("%s: type %s does not have a namespace", __func__, type);
+
+       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Lookup for handle named [%s] type %s",
+               __func__, name, mono_w32handle_ops_typename (type));
+
+       search_data.ret = NULL;
+       search_data.type = type;
+       search_data.name = name;
+       mono_w32handle_foreach (mono_w32handle_namespace_search_handle_callback, &search_data);
+       return search_data.ret;
+}
+
+#endif
diff --git a/mono/metadata/w32handle-namespace.h b/mono/metadata/w32handle-namespace.h
new file mode 100644 (file)
index 0000000..5a25477
--- /dev/null
@@ -0,0 +1,28 @@
+
+#ifndef _MONO_METADATA_W32HANDLE_NAMESPACE_H_
+#define _MONO_METADATA_W32HANDLE_NAMESPACE_H_
+
+#include <config.h>
+#include <glib.h>
+
+#include "mono/utils/w32handle.h"
+
+#define MONO_W32HANDLE_NAMESPACE_MAX_PATH 260
+
+typedef struct {
+       gchar name [MONO_W32HANDLE_NAMESPACE_MAX_PATH + 1];
+} MonoW32HandleNamespace;
+
+void
+mono_w32handle_namespace_init (void);
+
+void
+mono_w32handle_namespace_lock (void);
+
+void
+mono_w32handle_namespace_unlock (void);
+
+gpointer
+mono_w32handle_namespace_search_handle (MonoW32HandleType type, gchar *name);
+
+#endif /* _MONO_METADATA_W32HANDLE_NAMESPACE_H_ */
\ No newline at end of file
diff --git a/mono/metadata/w32mutex-unix.c b/mono/metadata/w32mutex-unix.c
new file mode 100644 (file)
index 0000000..d7a3c03
--- /dev/null
@@ -0,0 +1,476 @@
+/*
+ * w32mutex-unix.c: Runtime support for managed Mutex on Unix
+ *
+ * Author:
+ *     Ludovic Henry (luhenry@microsoft.com)
+ *
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
+ */
+
+#include "w32mutex.h"
+#include "w32mutex-utils.h"
+
+#include <pthread.h>
+
+#include "w32handle-namespace.h"
+#include "mono/io-layer/io-layer.h"
+#include "mono/utils/mono-logger-internals.h"
+#include "mono/utils/mono-threads.h"
+#include "mono/utils/w32handle.h"
+
+typedef struct {
+       MonoNativeThreadId tid;
+       guint32 recursion;
+} MonoW32HandleMutex;
+
+struct MonoW32HandleNamedMutex {
+       MonoW32HandleMutex m;
+       MonoW32HandleNamespace sharedns;
+};
+
+static gboolean
+mutex_handle_own (gpointer handle, MonoW32HandleType type)
+{
+       MonoW32HandleMutex *mutex_handle;
+
+       if (!mono_w32handle_lookup (handle, type, (gpointer *)&mutex_handle)) {
+               g_warning ("%s: error looking up %s handle %p", __func__, mono_w32handle_ops_typename (type), handle);
+               return FALSE;
+       }
+
+       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: owning %s handle %p, tid %p, recursion %u",
+               __func__, mono_w32handle_ops_typename (type), handle, (gpointer) mutex_handle->tid, mutex_handle->recursion);
+
+       mono_thread_info_own_mutex (mono_thread_info_current (), handle);
+
+       mutex_handle->tid = pthread_self ();
+       mutex_handle->recursion++;
+
+       mono_w32handle_set_signal_state (handle, FALSE, FALSE);
+
+       return TRUE;
+}
+
+static gboolean
+mutex_handle_is_owned (gpointer handle, MonoW32HandleType type)
+{
+       MonoW32HandleMutex *mutex_handle;
+
+       if (!mono_w32handle_lookup (handle, type, (gpointer *)&mutex_handle)) {
+               g_warning ("%s: error looking up %s handle %p", __func__, mono_w32handle_ops_typename (type), handle);
+               return FALSE;
+       }
+
+       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: testing ownership %s handle %p",
+               __func__, mono_w32handle_ops_typename (type), handle);
+
+       if (mutex_handle->recursion > 0 && pthread_equal (mutex_handle->tid, pthread_self ())) {
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: %s handle %p owned by %p",
+                       __func__, mono_w32handle_ops_typename (type), handle, (gpointer) pthread_self ());
+               return TRUE;
+       } else {
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: %s handle %p not owned by %p, but locked %d times by %p",
+                       __func__, mono_w32handle_ops_typename (type), handle, (gpointer) pthread_self (), mutex_handle->recursion, (gpointer) mutex_handle->tid);
+               return FALSE;
+       }
+}
+
+static void mutex_signal(gpointer handle)
+{
+       ves_icall_System_Threading_Mutex_ReleaseMutex_internal (handle);
+}
+
+static gboolean mutex_own (gpointer handle)
+{
+       return mutex_handle_own (handle, MONO_W32HANDLE_MUTEX);
+}
+
+static gboolean mutex_is_owned (gpointer handle)
+{
+       
+       return mutex_handle_is_owned (handle, MONO_W32HANDLE_MUTEX);
+}
+
+static void namedmutex_signal (gpointer handle)
+{
+       ves_icall_System_Threading_Mutex_ReleaseMutex_internal (handle);
+}
+
+/* NB, always called with the shared handle lock held */
+static gboolean namedmutex_own (gpointer handle)
+{
+       return mutex_handle_own (handle, MONO_W32HANDLE_NAMEDMUTEX);
+}
+
+static gboolean namedmutex_is_owned (gpointer handle)
+{
+       return mutex_handle_is_owned (handle, MONO_W32HANDLE_NAMEDMUTEX);
+}
+
+static void mutex_handle_prewait (gpointer handle, MonoW32HandleType type)
+{
+       /* If the mutex is not currently owned, do nothing and let the
+        * usual wait carry on.  If it is owned, check that the owner
+        * is still alive; if it isn't we override the previous owner
+        * and assume that process exited abnormally and failed to
+        * clean up.
+        */
+       MonoW32HandleMutex *mutex_handle;
+
+       if (!mono_w32handle_lookup (handle, type, (gpointer *)&mutex_handle)) {
+               g_warning ("%s: error looking up %s handle %p",
+                       __func__, mono_w32handle_ops_typename (type), handle);
+               return;
+       }
+
+       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: pre-waiting %s handle %p, owned? %s",
+               __func__, mono_w32handle_ops_typename (type), handle, mutex_handle->recursion != 0 ? "true" : "false");
+}
+
+/* The shared state is not locked when prewait methods are called */
+static void mutex_prewait (gpointer handle)
+{
+       mutex_handle_prewait (handle, MONO_W32HANDLE_MUTEX);
+}
+
+/* The shared state is not locked when prewait methods are called */
+static void namedmutex_prewait (gpointer handle)
+{
+       mutex_handle_prewait (handle, MONO_W32HANDLE_NAMEDMUTEX);
+}
+
+static void mutex_details (gpointer data)
+{
+       MonoW32HandleMutex *mut = (MonoW32HandleMutex *)data;
+       
+#ifdef PTHREAD_POINTER_ID
+       g_print ("own: %5p, count: %5u", mut->tid, mut->recursion);
+#else
+       g_print ("own: %5ld, count: %5u", mut->tid, mut->recursion);
+#endif
+}
+
+static void namedmutex_details (gpointer data)
+{
+       MonoW32HandleNamedMutex *namedmut = (MonoW32HandleNamedMutex *)data;
+       
+#ifdef PTHREAD_POINTER_ID
+       g_print ("own: %5p, count: %5u, name: \"%s\"",
+               namedmut->m.tid, namedmut->m.recursion, namedmut->sharedns.name);
+#else
+       g_print ("own: %5ld, count: %5u, name: \"%s\"",
+               namedmut->m.tid, namedmut->m.recursion, namedmut->sharedns.name);
+#endif
+}
+
+static const gchar* mutex_typename (void)
+{
+       return "Mutex";
+}
+
+static gsize mutex_typesize (void)
+{
+       return sizeof (MonoW32HandleMutex);
+}
+
+static const gchar* namedmutex_typename (void)
+{
+       return "N.Mutex";
+}
+
+static gsize namedmutex_typesize (void)
+{
+       return sizeof (MonoW32HandleNamedMutex);
+}
+
+void
+mono_w32mutex_init (void)
+{
+       static MonoW32HandleOps mutex_ops = {
+               NULL,                   /* close */
+               mutex_signal,           /* signal */
+               mutex_own,              /* own */
+               mutex_is_owned,         /* is_owned */
+               NULL,                   /* special_wait */
+               mutex_prewait,                  /* prewait */
+               mutex_details,  /* details */
+               mutex_typename, /* typename */
+               mutex_typesize, /* typesize */
+       };
+
+       static MonoW32HandleOps namedmutex_ops = {
+               NULL,                   /* close */
+               namedmutex_signal,      /* signal */
+               namedmutex_own,         /* own */
+               namedmutex_is_owned,    /* is_owned */
+               NULL,                   /* special_wait */
+               namedmutex_prewait,     /* prewait */
+               namedmutex_details,     /* details */
+               namedmutex_typename,    /* typename */
+               namedmutex_typesize,    /* typesize */
+       };
+
+       mono_w32handle_register_ops (MONO_W32HANDLE_MUTEX,      &mutex_ops);
+       mono_w32handle_register_ops (MONO_W32HANDLE_NAMEDMUTEX, &namedmutex_ops);
+
+       mono_w32handle_register_capabilities (MONO_W32HANDLE_MUTEX,
+               (MonoW32HandleCapability)(MONO_W32HANDLE_CAP_WAIT | MONO_W32HANDLE_CAP_SIGNAL | MONO_W32HANDLE_CAP_OWN));
+       mono_w32handle_register_capabilities (MONO_W32HANDLE_NAMEDMUTEX,
+               (MonoW32HandleCapability)(MONO_W32HANDLE_CAP_WAIT | MONO_W32HANDLE_CAP_SIGNAL | MONO_W32HANDLE_CAP_OWN));
+}
+
+static gpointer mutex_handle_create (MonoW32HandleMutex *mutex_handle, MonoW32HandleType type, gboolean owned)
+{
+       gpointer handle;
+       int thr_ret;
+
+       mutex_handle->tid = 0;
+       mutex_handle->recursion = 0;
+
+       handle = mono_w32handle_new (type, mutex_handle);
+       if (handle == INVALID_HANDLE_VALUE) {
+               g_warning ("%s: error creating %s handle",
+                       __func__, mono_w32handle_ops_typename (type));
+               SetLastError (ERROR_GEN_FAILURE);
+               return NULL;
+       }
+
+       thr_ret = mono_w32handle_lock_handle (handle);
+       g_assert (thr_ret == 0);
+
+       if (owned)
+               mutex_handle_own (handle, type);
+       else
+               mono_w32handle_set_signal_state (handle, TRUE, FALSE);
+
+       thr_ret = mono_w32handle_unlock_handle (handle);
+       g_assert (thr_ret == 0);
+
+       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: created %s handle %p",
+               __func__, mono_w32handle_ops_typename (type), handle);
+
+       return handle;
+}
+
+static gpointer mutex_create (gboolean owned)
+{
+       MonoW32HandleMutex mutex_handle;
+       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: creating %s handle",
+               __func__, mono_w32handle_ops_typename (MONO_W32HANDLE_MUTEX));
+       return mutex_handle_create (&mutex_handle, MONO_W32HANDLE_MUTEX, owned);
+}
+
+static gpointer namedmutex_create (gboolean owned, const gunichar2 *name)
+{
+       gpointer handle;
+       gchar *utf8_name;
+
+       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: creating %s handle",
+               __func__, mono_w32handle_ops_typename (MONO_W32HANDLE_NAMEDMUTEX));
+
+       /* w32 seems to guarantee that opening named objects can't race each other */
+       mono_w32handle_namespace_lock ();
+
+       utf8_name = g_utf16_to_utf8 (name, -1, NULL, NULL, NULL);
+
+       handle = mono_w32handle_namespace_search_handle (MONO_W32HANDLE_NAMEDMUTEX, utf8_name);
+       if (handle == INVALID_HANDLE_VALUE) {
+               /* The name has already been used for a different object. */
+               handle = NULL;
+               SetLastError (ERROR_INVALID_HANDLE);
+       } else if (handle) {
+               /* Not an error, but this is how the caller is informed that the mutex wasn't freshly created */
+               SetLastError (ERROR_ALREADY_EXISTS);
+
+               /* this is used as creating a new handle */
+               mono_w32handle_ref (handle);
+       } else {
+               /* A new named mutex */
+               MonoW32HandleNamedMutex namedmutex_handle;
+
+               strncpy (&namedmutex_handle.sharedns.name [0], utf8_name, MAX_PATH);
+               namedmutex_handle.sharedns.name [MAX_PATH] = '\0';
+
+               handle = mutex_handle_create ((MonoW32HandleMutex*) &namedmutex_handle, MONO_W32HANDLE_NAMEDMUTEX, owned);
+       }
+
+       g_free (utf8_name);
+
+       mono_w32handle_namespace_unlock ();
+
+       return handle;
+}
+
+gpointer
+ves_icall_System_Threading_Mutex_CreateMutex_internal (MonoBoolean owned, MonoString *name, MonoBoolean *created)
+{
+       gpointer mutex;
+
+       *created = TRUE;
+
+       /* Need to blow away any old errors here, because code tests
+        * for ERROR_ALREADY_EXISTS on success (!) to see if a mutex
+        * was freshly created */
+       SetLastError (ERROR_SUCCESS);
+
+       if (!name) {
+               mutex = mutex_create (owned);
+       } else {
+               mutex = namedmutex_create (owned, mono_string_chars (name));
+
+               if (GetLastError () == ERROR_ALREADY_EXISTS)
+                       *created = FALSE;
+       }
+
+       return mutex;
+}
+
+MonoBoolean
+ves_icall_System_Threading_Mutex_ReleaseMutex_internal (gpointer handle)
+{
+       MonoW32HandleType type;
+       MonoW32HandleMutex *mutex_handle;
+       pthread_t tid;
+       int thr_ret;
+       gboolean ret;
+
+       if (handle == NULL) {
+               SetLastError (ERROR_INVALID_HANDLE);
+               return FALSE;
+       }
+
+       switch (type = mono_w32handle_get_type (handle)) {
+       case MONO_W32HANDLE_MUTEX:
+       case MONO_W32HANDLE_NAMEDMUTEX:
+               break;
+       default:
+               SetLastError (ERROR_INVALID_HANDLE);
+               return FALSE;
+       }
+
+       if (!mono_w32handle_lookup (handle, type, (gpointer *)&mutex_handle)) {
+               g_warning ("%s: error looking up %s handle %p",
+                       __func__, mono_w32handle_ops_typename (type), handle);
+               return FALSE;
+       }
+
+       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: releasing %s handle %p",
+               __func__, mono_w32handle_ops_typename (type), handle);
+
+       thr_ret = mono_w32handle_lock_handle (handle);
+       g_assert (thr_ret == 0);
+
+       tid = pthread_self ();
+
+       if (!pthread_equal (mutex_handle->tid, tid)) {
+               ret = FALSE;
+
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: we don't own %s handle %p (owned by %ld, me %ld)",
+                       __func__, mono_w32handle_ops_typename (type), handle, mutex_handle->tid, tid);
+       } else {
+               ret = TRUE;
+
+               /* OK, we own this mutex */
+               mutex_handle->recursion--;
+
+               if (mutex_handle->recursion == 0) {
+                       mono_thread_info_disown_mutex (mono_thread_info_current (), handle);
+
+                       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: unlocking %s handle %p",
+                               __func__, mono_w32handle_ops_typename (type), handle);
+
+                       mutex_handle->tid = 0;
+                       mono_w32handle_set_signal_state (handle, TRUE, FALSE);
+               }
+       }
+
+       thr_ret = mono_w32handle_unlock_handle (handle);
+       g_assert (thr_ret == 0);
+
+       return ret;
+}
+
+gpointer
+ves_icall_System_Threading_Mutex_OpenMutex_internal (MonoString *name, gint32 rights G_GNUC_UNUSED, gint32 *error)
+{
+       gpointer handle;
+       gchar *utf8_name;
+
+       *error = ERROR_SUCCESS;
+
+       /* w32 seems to guarantee that opening named objects can't race each other */
+       mono_w32handle_namespace_lock ();
+
+       utf8_name = g_utf16_to_utf8 (mono_string_chars (name), -1, NULL, NULL, NULL);
+
+       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Opening named mutex [%s]",
+               __func__, utf8_name);
+
+       handle = mono_w32handle_namespace_search_handle (MONO_W32HANDLE_NAMEDMUTEX, utf8_name);
+       if (handle == INVALID_HANDLE_VALUE) {
+               /* The name has already been used for a different object. */
+               *error = ERROR_INVALID_HANDLE;
+               goto cleanup;
+       } else if (!handle) {
+               /* This name doesn't exist */
+               *error = ERROR_FILE_NOT_FOUND;
+               goto cleanup;
+       }
+
+       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: returning named mutex handle %p",
+               __func__, handle);
+
+cleanup:
+       g_free (utf8_name);
+
+       mono_w32handle_namespace_unlock ();
+
+       return handle;
+}
+
+void
+mono_w32mutex_abandon (gpointer handle, MonoNativeThreadId tid)
+{
+       MonoW32HandleType type;
+       MonoW32HandleMutex *mutex_handle;
+       int thr_ret;
+
+       switch (type = mono_w32handle_get_type (handle)) {
+       case MONO_W32HANDLE_MUTEX:
+       case MONO_W32HANDLE_NAMEDMUTEX:
+               break;
+       default:
+               g_assert_not_reached ();
+       }
+
+       if (!mono_w32handle_lookup (handle, type, (gpointer *)&mutex_handle)) {
+               g_warning ("%s: error looking up %s handle %p",
+                       __func__, mono_w32handle_ops_typename (type), handle);
+               return;
+       }
+
+       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: abandon %s handle %p",
+               __func__, mono_w32handle_ops_typename (type), handle);
+
+       thr_ret = mono_w32handle_lock_handle (handle);
+       g_assert (thr_ret == 0);
+
+       if (pthread_equal (mutex_handle->tid, tid)) {
+               mutex_handle->recursion = 0;
+               mutex_handle->tid = 0;
+
+               mono_w32handle_set_signal_state (handle, TRUE, FALSE);
+
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: abandoned %s handle %p",
+                       __func__, mono_w32handle_ops_typename (type), handle);
+       }
+
+       thr_ret = mono_w32handle_unlock_handle (handle);
+       g_assert (thr_ret == 0);
+}
+
+MonoW32HandleNamespace*
+mono_w32mutex_get_namespace (MonoW32HandleNamedMutex *mutex)
+{
+       return &mutex->sharedns;
+}
diff --git a/mono/metadata/w32mutex-utils.h b/mono/metadata/w32mutex-utils.h
new file mode 100644 (file)
index 0000000..a7bad8c
--- /dev/null
@@ -0,0 +1,20 @@
+
+/* This is just a hack so we can call mono_w32mutex_abandon
+ * from mono/utils/mono-threads-posix.c, without importing
+ * the whole object.h
+ * In the best of all world, mutex owning + disowning + abandoning
+ * should be done in metadata/ */
+
+#ifndef _MONO_METADATA_W32MUTEX_UTILS_H_
+#define _MONO_METADATA_W32MUTEX_UTILS_H_
+
+#include <config.h>
+#include <glib.h>
+
+#include "mono/utils/mono-threads.h"
+
+void
+mono_w32mutex_abandon (gpointer handle, MonoNativeThreadId tid);
+
+#endif /* _MONO_METADATA_W32MUTEX_UTILS_H_ */
+
diff --git a/mono/metadata/w32mutex-win32.c b/mono/metadata/w32mutex-win32.c
new file mode 100644 (file)
index 0000000..6f967e8
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * w32mutex-win32.c: Runtime support for managed Mutex on Win32
+ *
+ * Author:
+ *     Ludovic Henry (luhenry@microsoft.com)
+ *
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
+ */
+
+#include "w32mutex.h"
+
+#include <windows.h>
+#include <winbase.h>
+
+void
+mono_w32mutex_init (void)
+{
+}
+
+gpointer
+ves_icall_System_Threading_Mutex_CreateMutex_internal (MonoBoolean owned, MonoString *name, MonoBoolean *created)
+{
+       HANDLE mutex;
+
+       *created = TRUE;
+
+       if (!name) {
+               mutex = CreateMutex (NULL, owned, NULL);
+       } else {
+               mutex = CreateMutex (NULL, owned, mono_string_chars (name));
+
+               if (GetLastError () == ERROR_ALREADY_EXISTS)
+                       *created = FALSE;
+       }
+
+       return mutex;
+}
+
+MonoBoolean
+ves_icall_System_Threading_Mutex_ReleaseMutex_internal (gpointer handle)
+{
+       return ReleaseMutex (handle);
+}
+
+gpointer
+ves_icall_System_Threading_Mutex_OpenMutex_internal (MonoString *name, gint32 rights, gint32 *error)
+{
+       HANDLE ret;
+
+       *error = ERROR_SUCCESS;
+
+       ret = OpenMutex (rights, FALSE, mono_string_chars (name));
+       if (!ret)
+               *error = GetLastError ();
+
+       return ret;
+}
diff --git a/mono/metadata/w32mutex.h b/mono/metadata/w32mutex.h
new file mode 100644 (file)
index 0000000..3c63619
--- /dev/null
@@ -0,0 +1,28 @@
+
+#ifndef _MONO_METADATA_W32MUTEX_H_
+#define _MONO_METADATA_W32MUTEX_H_
+
+#include <config.h>
+#include <glib.h>
+
+#include "object.h"
+#include "w32handle-namespace.h"
+
+void
+mono_w32mutex_init (void);
+
+gpointer
+ves_icall_System_Threading_Mutex_CreateMutex_internal (MonoBoolean owned, MonoString *name, MonoBoolean *created);
+
+MonoBoolean
+ves_icall_System_Threading_Mutex_ReleaseMutex_internal (gpointer handle);
+
+gpointer
+ves_icall_System_Threading_Mutex_OpenMutex_internal (MonoString *name, gint32 rights, gint32 *error);
+
+typedef struct MonoW32HandleNamedMutex MonoW32HandleNamedMutex;
+
+MonoW32HandleNamespace*
+mono_w32mutex_get_namespace (MonoW32HandleNamedMutex *mutex);
+
+#endif /* _MONO_METADATA_W32MUTEX_H_ */
diff --git a/mono/metadata/w32semaphore-unix.c b/mono/metadata/w32semaphore-unix.c
new file mode 100644 (file)
index 0000000..d21ef97
--- /dev/null
@@ -0,0 +1,357 @@
+/*
+ * w32semaphore-unix.c: Runtime support for managed Semaphore on Unix
+ *
+ * Author:
+ *     Ludovic Henry (luhenry@microsoft.com)
+ *
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
+ */
+
+#include "w32semaphore.h"
+
+#include "w32handle-namespace.h"
+#include "mono/io-layer/io-layer.h"
+#include "mono/utils/mono-logger-internals.h"
+#include "mono/utils/w32handle.h"
+
+typedef struct {
+       guint32 val;
+       gint32 max;
+} MonoW32HandleSemaphore;
+
+struct MonoW32HandleNamedSemaphore {
+       MonoW32HandleSemaphore s;
+       MonoW32HandleNamespace sharedns;
+};
+
+static gboolean sem_handle_own (gpointer handle, MonoW32HandleType type)
+{
+       MonoW32HandleSemaphore *sem_handle;
+
+       if (!mono_w32handle_lookup (handle, type, (gpointer *)&sem_handle)) {
+               g_warning ("%s: error looking up %s handle %p",
+                       __func__, mono_w32handle_ops_typename (type), handle);
+               return FALSE;
+       }
+
+       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: owning %s handle %p",
+               __func__, mono_w32handle_ops_typename (type), handle);
+
+       sem_handle->val--;
+
+       if (sem_handle->val == 0)
+               mono_w32handle_set_signal_state (handle, FALSE, FALSE);
+
+       return TRUE;
+}
+
+static void sema_signal(gpointer handle)
+{
+       ves_icall_System_Threading_Semaphore_ReleaseSemaphore_internal(handle, 1, NULL);
+}
+
+static gboolean sema_own (gpointer handle)
+{
+       return sem_handle_own (handle, MONO_W32HANDLE_SEM);
+}
+
+static void namedsema_signal (gpointer handle)
+{
+       ves_icall_System_Threading_Semaphore_ReleaseSemaphore_internal (handle, 1, NULL);
+}
+
+/* NB, always called with the shared handle lock held */
+static gboolean namedsema_own (gpointer handle)
+{
+       return sem_handle_own (handle, MONO_W32HANDLE_NAMEDSEM);
+}
+
+static void sema_details (gpointer data)
+{
+       MonoW32HandleSemaphore *sem = (MonoW32HandleSemaphore *)data;
+       g_print ("val: %5u, max: %5d", sem->val, sem->max);
+}
+
+static void namedsema_details (gpointer data)
+{
+       MonoW32HandleNamedSemaphore *namedsem = (MonoW32HandleNamedSemaphore *)data;
+       g_print ("val: %5u, max: %5d, name: \"%s\"", namedsem->s.val, namedsem->s.max, namedsem->sharedns.name);
+}
+
+static const gchar* sema_typename (void)
+{
+       return "Semaphore";
+}
+
+static gsize sema_typesize (void)
+{
+       return sizeof (MonoW32HandleSemaphore);
+}
+
+static const gchar* namedsema_typename (void)
+{
+       return "N.Semaphore";
+}
+
+static gsize namedsema_typesize (void)
+{
+       return sizeof (MonoW32HandleNamedSemaphore);
+}
+
+void
+mono_w32semaphore_init (void)
+{
+       static MonoW32HandleOps sem_ops = {
+               NULL,                   /* close */
+               sema_signal,            /* signal */
+               sema_own,               /* own */
+               NULL,                   /* is_owned */
+               NULL,                   /* special_wait */
+               NULL,                   /* prewait */
+               sema_details,   /* details */
+               sema_typename,  /* typename */
+               sema_typesize,  /* typesize */
+       };
+
+       static MonoW32HandleOps namedsem_ops = {
+               NULL,                   /* close */
+               namedsema_signal,       /* signal */
+               namedsema_own,          /* own */
+               NULL,                   /* is_owned */
+               NULL,                   /* special_wait */
+               NULL,                   /* prewait */
+               namedsema_details,      /* details */
+               namedsema_typename,     /* typename */
+               namedsema_typesize,     /* typesize */
+       };
+
+       mono_w32handle_register_ops (MONO_W32HANDLE_SEM,      &sem_ops);
+       mono_w32handle_register_ops (MONO_W32HANDLE_NAMEDSEM, &namedsem_ops);
+
+       mono_w32handle_register_capabilities (MONO_W32HANDLE_SEM,
+               (MonoW32HandleCapability)(MONO_W32HANDLE_CAP_WAIT | MONO_W32HANDLE_CAP_SIGNAL));
+       mono_w32handle_register_capabilities (MONO_W32HANDLE_NAMEDSEM,
+               (MonoW32HandleCapability)(MONO_W32HANDLE_CAP_WAIT | MONO_W32HANDLE_CAP_SIGNAL));
+}
+
+static gpointer
+sem_handle_create (MonoW32HandleSemaphore *sem_handle, MonoW32HandleType type, gint32 initial, gint32 max)
+{
+       gpointer handle;
+       int thr_ret;
+
+       sem_handle->val = initial;
+       sem_handle->max = max;
+
+       handle = mono_w32handle_new (type, sem_handle);
+       if (handle == INVALID_HANDLE_VALUE) {
+               g_warning ("%s: error creating %s handle",
+                       __func__, mono_w32handle_ops_typename (type));
+               SetLastError (ERROR_GEN_FAILURE);
+               return NULL;
+       }
+
+       thr_ret = mono_w32handle_lock_handle (handle);
+       g_assert (thr_ret == 0);
+
+       if (initial != 0)
+               mono_w32handle_set_signal_state (handle, TRUE, FALSE);
+
+       thr_ret = mono_w32handle_unlock_handle (handle);
+       g_assert (thr_ret == 0);
+
+       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: created %s handle %p",
+               __func__, mono_w32handle_ops_typename (type), handle);
+
+       return handle;
+}
+
+static gpointer
+sem_create (gint32 initial, gint32 max)
+{
+       MonoW32HandleSemaphore sem_handle;
+       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: creating %s handle, initial %d max %d",
+               __func__, mono_w32handle_ops_typename (MONO_W32HANDLE_SEM), initial, max);
+       return sem_handle_create (&sem_handle, MONO_W32HANDLE_SEM, initial, max);
+}
+
+static gpointer
+namedsem_create (gint32 initial, gint32 max, const gunichar2 *name)
+{
+       gpointer handle;
+       gchar *utf8_name;
+
+       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: creating %s handle, initial %d max %d name \"%s\"",
+               __func__, mono_w32handle_ops_typename (MONO_W32HANDLE_NAMEDSEM), initial, max, name);
+
+       /* w32 seems to guarantee that opening named objects can't race each other */
+       mono_w32handle_namespace_lock ();
+
+       utf8_name = g_utf16_to_utf8 (name, -1, NULL, NULL, NULL);
+
+       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Creating named sem name [%s] initial %d max %d", __func__, utf8_name, initial, max);
+
+       handle = mono_w32handle_namespace_search_handle (MONO_W32HANDLE_NAMEDSEM, utf8_name);
+       if (handle == INVALID_HANDLE_VALUE) {
+               /* The name has already been used for a different object. */
+               handle = NULL;
+               SetLastError (ERROR_INVALID_HANDLE);
+       } else if (handle) {
+               /* Not an error, but this is how the caller is informed that the semaphore wasn't freshly created */
+               SetLastError (ERROR_ALREADY_EXISTS);
+
+               /* this is used as creating a new handle */
+               mono_w32handle_ref (handle);
+       } else {
+               /* A new named semaphore */
+               MonoW32HandleNamedSemaphore namedsem_handle;
+
+               strncpy (&namedsem_handle.sharedns.name [0], utf8_name, MAX_PATH);
+               namedsem_handle.sharedns.name [MAX_PATH] = '\0';
+
+               handle = sem_handle_create ((MonoW32HandleSemaphore*) &namedsem_handle, MONO_W32HANDLE_NAMEDSEM, initial, max);
+       }
+
+       g_free (utf8_name);
+
+       mono_w32handle_namespace_unlock ();
+
+       return handle;
+}
+
+gpointer
+ves_icall_System_Threading_Semaphore_CreateSemaphore_internal (gint32 initialCount, gint32 maximumCount, MonoString *name, gint32 *error)
+{ 
+       gpointer sem;
+
+       if (maximumCount <= 0) {
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: maximumCount <= 0", __func__);
+
+               *error = ERROR_INVALID_PARAMETER;
+               return NULL;
+       }
+
+       if (initialCount > maximumCount || initialCount < 0) {
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: initialCount > maximumCount or < 0", __func__);
+
+               *error = ERROR_INVALID_PARAMETER;
+               return NULL;
+       }
+
+       /* Need to blow away any old errors here, because code tests
+        * for ERROR_ALREADY_EXISTS on success (!) to see if a
+        * semaphore was freshly created
+        */
+       SetLastError (ERROR_SUCCESS);
+
+       if (!name)
+               sem = sem_create (initialCount, maximumCount);
+       else
+               sem = namedsem_create (initialCount, maximumCount, mono_string_chars (name));
+
+       *error = GetLastError ();
+
+       return sem;
+}
+
+MonoBoolean
+ves_icall_System_Threading_Semaphore_ReleaseSemaphore_internal (gpointer handle, gint32 releaseCount, gint32 *prevcount)
+{
+       MonoW32HandleType type;
+       MonoW32HandleSemaphore *sem_handle;
+       int thr_ret;
+       MonoBoolean ret;
+
+       if (!handle) {
+               SetLastError (ERROR_INVALID_HANDLE);
+               return FALSE;
+       }
+
+       switch (type = mono_w32handle_get_type (handle)) {
+       case MONO_W32HANDLE_SEM:
+       case MONO_W32HANDLE_NAMEDSEM:
+               break;
+       default:
+               SetLastError (ERROR_INVALID_HANDLE);
+               return FALSE;
+       }
+
+       if (!mono_w32handle_lookup (handle, type, (gpointer *)&sem_handle)) {
+               g_warning ("%s: error looking up sem handle %p", __func__, handle);
+               return FALSE;
+       }
+
+       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: releasing %s handle %p",
+               __func__, mono_w32handle_ops_typename (type), handle);
+
+       thr_ret = mono_w32handle_lock_handle (handle);
+       g_assert (thr_ret == 0);
+
+       /* Do this before checking for count overflow, because overflowing
+        * max is a listed technique for finding the current value */
+       if (prevcount)
+               *prevcount = sem_handle->val;
+
+       /* No idea why max is signed, but thats the spec :-( */
+       if (sem_handle->val + releaseCount > (guint32)sem_handle->max) {
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: %s handle %p val %d count %d max %d, max value would be exceeded",
+                       __func__, mono_w32handle_ops_typename (type), handle, sem_handle->val, releaseCount, sem_handle->max);
+
+               ret = FALSE;
+       } else {
+               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: %s handle %p val %d count %d max %d",
+                       __func__, mono_w32handle_ops_typename (type), handle, sem_handle->val, releaseCount, sem_handle->max);
+
+               sem_handle->val += releaseCount;
+               mono_w32handle_set_signal_state (handle, TRUE, TRUE);
+
+               ret = TRUE;
+       }
+
+       thr_ret = mono_w32handle_unlock_handle (handle);
+       g_assert (thr_ret == 0);
+
+       return ret;
+}
+
+gpointer
+ves_icall_System_Threading_Semaphore_OpenSemaphore_internal (MonoString *name, gint32 rights, gint32 *error)
+{
+       gpointer handle;
+       gchar *utf8_name;
+
+       *error = ERROR_SUCCESS;
+
+       /* w32 seems to guarantee that opening named objects can't race each other */
+       mono_w32handle_namespace_lock ();
+
+       utf8_name = g_utf16_to_utf8 (mono_string_chars (name), -1, NULL, NULL, NULL);
+
+       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Opening named sem [%s]", __func__, utf8_name);
+
+       handle = mono_w32handle_namespace_search_handle (MONO_W32HANDLE_NAMEDSEM, utf8_name);
+       if (handle == INVALID_HANDLE_VALUE) {
+               /* The name has already been used for a different object. */
+               *error = ERROR_INVALID_HANDLE;
+               goto cleanup;
+       } else if (!handle) {
+               /* This name doesn't exist */
+               *error = ERROR_FILE_NOT_FOUND;
+               goto cleanup;
+       }
+
+       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: returning named sem handle %p", __func__, handle);
+
+cleanup:
+       g_free (utf8_name);
+
+       mono_w32handle_namespace_unlock ();
+
+       return handle;
+}
+
+MonoW32HandleNamespace*
+mono_w32semaphore_get_namespace (MonoW32HandleNamedSemaphore *semaphore)
+{
+       return &semaphore->sharedns;
+}
diff --git a/mono/metadata/w32semaphore-win32.c b/mono/metadata/w32semaphore-win32.c
new file mode 100644 (file)
index 0000000..d7c6b62
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * w32semaphore-win32.c: Runtime support for managed Semaphore on Win32
+ *
+ * Author:
+ *     Ludovic Henry (luhenry@microsoft.com)
+ *
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
+ */
+
+#include "w32semaphore.h"
+
+#include <windows.h>
+#include <winbase.h>
+
+void
+mono_w32semaphore_init (void)
+{
+}
+
+gpointer
+ves_icall_System_Threading_Semaphore_CreateSemaphore_internal (gint32 initialCount, gint32 maximumCount, MonoString *name, gint32 *error)
+{ 
+       HANDLE sem;
+
+       sem = CreateSemaphore (NULL, initialCount, maximumCount, name ? mono_string_chars (name) : NULL);
+
+       *error = GetLastError ();
+
+       return sem;
+}
+
+MonoBoolean
+ves_icall_System_Threading_Semaphore_ReleaseSemaphore_internal (gpointer handle, gint32 releaseCount, gint32 *prevcount)
+{ 
+       return ReleaseSemaphore (handle, releaseCount, prevcount);
+}
+
+gpointer
+ves_icall_System_Threading_Semaphore_OpenSemaphore_internal (MonoString *name, gint32 rights, gint32 *error)
+{
+       HANDLE sem;
+
+       sem = OpenSemaphore (rights, FALSE, mono_string_chars (name));
+
+       *error = GetLastError ();
+
+       return sem;
+}
\ No newline at end of file
diff --git a/mono/metadata/w32semaphore.h b/mono/metadata/w32semaphore.h
new file mode 100644 (file)
index 0000000..789dfbe
--- /dev/null
@@ -0,0 +1,28 @@
+
+#ifndef _MONO_METADATA_W32SEMAPHORE_H_
+#define _MONO_METADATA_W32SEMAPHORE_H_
+
+#include <config.h>
+#include <glib.h>
+
+#include "object.h"
+#include "w32handle-namespace.h"
+
+void
+mono_w32semaphore_init (void);
+
+gpointer
+ves_icall_System_Threading_Semaphore_CreateSemaphore_internal (gint32 initialCount, gint32 maximumCount, MonoString *name, gint32 *error);
+
+MonoBoolean
+ves_icall_System_Threading_Semaphore_ReleaseSemaphore_internal (gpointer handle, gint32 releaseCount, gint32 *prevcount);
+
+gpointer
+ves_icall_System_Threading_Semaphore_OpenSemaphore_internal (MonoString *name, gint32 rights, gint32 *error);
+
+typedef struct MonoW32HandleNamedSemaphore MonoW32HandleNamedSemaphore;
+
+MonoW32HandleNamespace*
+mono_w32semaphore_get_namespace (MonoW32HandleNamedSemaphore *semaphore);
+
+#endif /* _MONO_METADATA_W32SEMAPHORE_H_ */
index 34614773907bd8c6818564cc7b2d2aead45f5cf3..3ad4c53b921a65b03ba65022f3af609fc8234614 100644 (file)
@@ -1145,7 +1145,7 @@ arm64_emit_specific_trampoline_pages (MonoAotCompile *acfg)
        /* Trampoline argument */
        arm_ldrx (code, ARMREG_IP1, ARMREG_IP0, 0);
 
-       /* Same as arch_emit_imt_thunk () */
+       /* Same as arch_emit_imt_trampoline () */
        labels [0] = code;
        arm_ldrx (code, ARMREG_IP0, ARMREG_IP1, 0);
        arm_cmpx (code, ARMREG_IP0, MONO_ARCH_RGCTX_REG);
@@ -1177,7 +1177,7 @@ arm64_emit_specific_trampoline_pages (MonoAotCompile *acfg)
        emit_code_bytes (acfg, buf, code - buf);
 
        common_tramp_size = code - buf;
-       acfg->tramp_page_code_offsets [MONO_AOT_TRAMP_IMT_THUNK] = common_tramp_size;
+       acfg->tramp_page_code_offsets [MONO_AOT_TRAMP_IMT] = common_tramp_size;
 
        arm64_emit_tramp_page_specific_code (acfg, pagesize, common_tramp_size, specific_tramp_size);
 }
@@ -1215,7 +1215,7 @@ arm64_emit_static_rgctx_trampoline (MonoAotCompile *acfg, int offset, int *tramp
 }
 
 static void
-arm64_emit_imt_thunk (MonoAotCompile *acfg, int offset, int *tramp_size)
+arm64_emit_imt_trampoline (MonoAotCompile *acfg, int offset, int *tramp_size)
 {
        guint8 buf [128];
        guint8 *code, *labels [16];
@@ -1758,7 +1758,7 @@ arch_emit_specific_trampoline_pages (MonoAotCompile *acfg)
 
        acfg->tramp_page_code_offsets [MONO_AOT_TRAMP_SPECIFIC] = 16;
        acfg->tramp_page_code_offsets [MONO_AOT_TRAMP_STATIC_RGCTX] = 16;
-       acfg->tramp_page_code_offsets [MONO_AOT_TRAMP_IMT_THUNK] = 72;
+       acfg->tramp_page_code_offsets [MONO_AOT_TRAMP_IMT] = 72;
        acfg->tramp_page_code_offsets [MONO_AOT_TRAMP_GSHAREDVT_ARG] = 16;
 
        /* Unwind info for specifc trampolines */
@@ -2133,9 +2133,9 @@ arch_emit_static_rgctx_trampoline (MonoAotCompile *acfg, int offset, int *tramp_
 }      
 
 /*
- * arch_emit_imt_thunk:
+ * arch_emit_imt_trampoline:
  *
- *   Emit an IMT thunk usable in full-aot mode. The thunk uses 1 got slot which
+ *   Emit an IMT trampoline usable in full-aot mode. The trampoline uses 1 got slot which
  * points to an array of pointer pairs. The pairs of the form [key, ptr], where
  * key is the IMT key, and ptr holds the address of a memory location holding
  * the address to branch to if the IMT arg matches the key. The array is 
@@ -2144,7 +2144,7 @@ arch_emit_static_rgctx_trampoline (MonoAotCompile *acfg, int offset, int *tramp_
  * TRAMP_SIZE is set to the size of the emitted trampoline.
  */
 static void
-arch_emit_imt_thunk (MonoAotCompile *acfg, int offset, int *tramp_size)
+arch_emit_imt_trampoline (MonoAotCompile *acfg, int offset, int *tramp_size)
 {
 #if defined(TARGET_AMD64)
        guint8 *buf, *code;
@@ -2333,7 +2333,7 @@ arch_emit_imt_thunk (MonoAotCompile *acfg, int offset, int *tramp_size)
 
        *tramp_size = code - buf + 4;
 #elif defined(TARGET_ARM64)
-       arm64_emit_imt_thunk (acfg, offset, tramp_size);
+       arm64_emit_imt_trampoline (acfg, offset, tramp_size);
 #elif defined(TARGET_POWERPC)
        guint8 buf [128];
        guint8 *code, *labels [16];
@@ -4327,13 +4327,19 @@ gboolean mono_aot_mode_is_full (MonoAotOptions *opts)
        return opts->mode == MONO_AOT_MODE_FULL;
 }
 
+static
+gboolean mono_aot_mode_is_hybrid (MonoAotOptions *opts)
+{
+       return opts->mode == MONO_AOT_MODE_HYBRID;
+}
+
 static void add_generic_class_with_depth (MonoAotCompile *acfg, MonoClass *klass, int depth, const char *ref);
 
 static void
 add_generic_class (MonoAotCompile *acfg, MonoClass *klass, gboolean force, const char *ref)
 {
        /* This might lead to a huge code blowup so only do it if neccesary */
-       if (!mono_aot_mode_is_full (&acfg->aot_opts) && !force)
+       if (!mono_aot_mode_is_full (&acfg->aot_opts) && !mono_aot_mode_is_hybrid (&acfg->aot_opts) && !force)
                return;
 
        add_generic_class_with_depth (acfg, klass, 0, ref);
@@ -6704,7 +6710,7 @@ emit_trampolines (MonoAotCompile *acfg)
                 * These include the following:
                 * - specific trampolines
                 * - static rgctx invoke trampolines
-                * - imt thunks
+                * - imt trampolines
                 * These trampolines have the same code, they are parameterized by GOT 
                 * slots. 
                 * They are defined in this file, in the arch_... routines instead of
@@ -6740,8 +6746,8 @@ emit_trampolines (MonoAotCompile *acfg)
                        case MONO_AOT_TRAMP_STATIC_RGCTX:
                                sprintf (symbol, "static_rgctx_trampolines");
                                break;
-                       case MONO_AOT_TRAMP_IMT_THUNK:
-                               sprintf (symbol, "imt_thunks");
+                       case MONO_AOT_TRAMP_IMT:
+                               sprintf (symbol, "imt_trampolines");
                                break;
                        case MONO_AOT_TRAMP_GSHAREDVT_ARG:
                                sprintf (symbol, "gsharedvt_arg_trampolines");
@@ -6772,8 +6778,8 @@ emit_trampolines (MonoAotCompile *acfg)
                                        arch_emit_static_rgctx_trampoline (acfg, tramp_got_offset, &tramp_size);                                
                                        tramp_got_offset += 2;
                                        break;
-                               case MONO_AOT_TRAMP_IMT_THUNK:
-                                       arch_emit_imt_thunk (acfg, tramp_got_offset, &tramp_size);
+                               case MONO_AOT_TRAMP_IMT:
+                                       arch_emit_imt_trampoline (acfg, tramp_got_offset, &tramp_size);
                                        tramp_got_offset += 1;
                                        break;
                                case MONO_AOT_TRAMP_GSHAREDVT_ARG:
@@ -8363,7 +8369,7 @@ emit_code (MonoAotCompile *acfg)
                method = cfg->orig_method;
 
                /* Emit unbox trampoline */
-               if (mono_aot_mode_is_full (&acfg->aot_opts) && cfg->orig_method->klass->valuetype && !(acfg->aot_opts.llvm_only && cfg->compile_llvm)) {
+               if (mono_aot_mode_is_full (&acfg->aot_opts) && cfg->orig_method->klass->valuetype) {
                        sprintf (symbol, "ut_%d", get_method_index (acfg, method));
 
                        emit_section_change (acfg, ".text", 0);
@@ -8445,11 +8451,7 @@ emit_code (MonoAotCompile *acfg)
                int call_size;
 
                if (acfg->cfgs [i]) {
-                       if (acfg->aot_opts.llvm_only && acfg->cfgs [i]->compile_llvm)
-                               /* Obtained by calling a generated function in the LLVM image */
-                               arch_emit_direct_call (acfg, symbol, FALSE, FALSE, NULL, &call_size);
-                       else
-                               arch_emit_direct_call (acfg, acfg->cfgs [i]->asm_symbol, FALSE, acfg->thumb_mixed && acfg->cfgs [i]->compile_llvm, NULL, &call_size);
+                       arch_emit_direct_call (acfg, acfg->cfgs [i]->asm_symbol, FALSE, acfg->thumb_mixed && acfg->cfgs [i]->compile_llvm, NULL, &call_size);
                } else {
                        arch_emit_direct_call (acfg, symbol, FALSE, FALSE, NULL, &call_size);
                }
@@ -8478,7 +8480,7 @@ emit_code (MonoAotCompile *acfg)
 
                method = cfg->orig_method;
 
-               if (mono_aot_mode_is_full (&acfg->aot_opts) && cfg->orig_method->klass->valuetype && !(acfg->aot_opts.llvm_only && cfg->compile_llvm)) {
+               if (mono_aot_mode_is_full (&acfg->aot_opts) && cfg->orig_method->klass->valuetype) {
                        index = get_method_index (acfg, method);
 
                        emit_int32 (acfg, index);
@@ -8508,7 +8510,7 @@ emit_code (MonoAotCompile *acfg)
 
                method = cfg->orig_method;
 
-               if (mono_aot_mode_is_full (&acfg->aot_opts) && cfg->orig_method->klass->valuetype && !(acfg->aot_opts.llvm_only && cfg->compile_llvm)) {
+               if (mono_aot_mode_is_full (&acfg->aot_opts) && cfg->orig_method->klass->valuetype) {
 #ifdef MONO_ARCH_AOT_SUPPORTED
                        int call_size;
 
@@ -8685,7 +8687,7 @@ mono_aot_method_hash (MonoMethod *method)
                break;
        }
        
-       free (hashes_start);
+       g_free (hashes_start);
        
        return c;
 }
@@ -9468,7 +9470,7 @@ emit_aot_file_info (MonoAotCompile *acfg, MonoAotFileInfo *info)
        if (acfg->num_trampoline_got_entries) {
                symbols [sindex ++] = "specific_trampolines";
                symbols [sindex ++] = "static_rgctx_trampolines";
-               symbols [sindex ++] = "imt_thunks";
+               symbols [sindex ++] = "imt_trampolines";
                symbols [sindex ++] = "gsharedvt_arg_trampolines";
        } else {
                symbols [sindex ++] = NULL;
@@ -9775,7 +9777,6 @@ compile_methods (MonoAotCompile *acfg)
                HANDLE handle;
                gpointer *user_data;
                MonoMethod **methods;
-               MonoThreadParm tp;
 
                methods_len = acfg->methods->len;
 
@@ -9806,16 +9807,14 @@ compile_methods (MonoAotCompile *acfg)
                        user_data [1] = acfg;
                        user_data [2] = frag;
                        
-                       tp.priority = MONO_THREAD_PRIORITY_NORMAL;
-                       tp.stack_size = 0;
-                       tp.creation_flags = 0;
-                       handle = mono_threads_create_thread (compile_thread_main, (gpointer) user_data, &tp, NULL);
+                       handle = mono_threads_create_thread (compile_thread_main, (gpointer) user_data, 0, NULL);
                        g_ptr_array_add (threads, handle);
                }
                g_free (methods);
 
                for (i = 0; i < threads->len; ++i) {
                        WaitForSingleObjectEx (g_ptr_array_index (threads, i), INFINITE, FALSE);
+                       mono_threads_close_thread_handle (g_ptr_array_index (threads, i));
                }
        } else {
                methods_len = 0;
@@ -10440,7 +10439,7 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
        }
 
 #if defined(MONO_ARCH_GSHAREDVT_SUPPORTED)
-       if (acfg->aot_opts.llvm_only || mono_aot_mode_is_full (&acfg->aot_opts)) {
+       if (acfg->aot_opts.llvm_only || mono_aot_mode_is_full (&acfg->aot_opts) || mono_aot_mode_is_hybrid (&acfg->aot_opts)) {
                acfg->opts |= MONO_OPT_GSHAREDVT;
                opts |= MONO_OPT_GSHAREDVT;
        }
@@ -10536,7 +10535,7 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options)
 #ifdef MONO_ARCH_GSHARED_SUPPORTED
        acfg->num_trampolines [MONO_AOT_TRAMP_STATIC_RGCTX] = mono_aot_mode_is_full (&acfg->aot_opts) ? acfg->aot_opts.nrgctx_trampolines : 0;
 #endif
-       acfg->num_trampolines [MONO_AOT_TRAMP_IMT_THUNK] = mono_aot_mode_is_full (&acfg->aot_opts) ? acfg->aot_opts.nimt_trampolines : 0;
+       acfg->num_trampolines [MONO_AOT_TRAMP_IMT] = mono_aot_mode_is_full (&acfg->aot_opts) ? acfg->aot_opts.nimt_trampolines : 0;
 #ifdef MONO_ARCH_GSHAREDVT_SUPPORTED
        if (acfg->opts & MONO_OPT_GSHAREDVT)
                acfg->num_trampolines [MONO_AOT_TRAMP_GSHAREDVT_ARG] = mono_aot_mode_is_full (&acfg->aot_opts) ? acfg->aot_opts.ngsharedvt_arg_trampolines : 0;
index e1849862a847f604f88fb5d933a2637796ee209c..9a4d566c754d088e31d81b3679ad2617c3fd6532 100644 (file)
@@ -2151,7 +2151,7 @@ load_aot_module (MonoAssembly *assembly, gpointer user_data)
        amodule->mono_eh_frame = (guint8 *)info->mono_eh_frame;
        amodule->trampolines [MONO_AOT_TRAMP_SPECIFIC] = (guint8 *)info->specific_trampolines;
        amodule->trampolines [MONO_AOT_TRAMP_STATIC_RGCTX] = (guint8 *)info->static_rgctx_trampolines;
-       amodule->trampolines [MONO_AOT_TRAMP_IMT_THUNK] = (guint8 *)info->imt_thunks;
+       amodule->trampolines [MONO_AOT_TRAMP_IMT] = (guint8 *)info->imt_trampolines;
        amodule->trampolines [MONO_AOT_TRAMP_GSHAREDVT_ARG] = (guint8 *)info->gsharedvt_arg_trampolines;
 
        if (!strcmp (assembly->aname.name, "mscorlib"))
@@ -5186,7 +5186,7 @@ read_page_trampoline_uwinfo (MonoTrampInfo *info, int tramp_type, gboolean is_ge
                sprintf (symbol_name, "specific_trampolines_page_%s_p", is_generic ? "gen" : "sp");
        else if (tramp_type == MONO_AOT_TRAMP_STATIC_RGCTX)
                sprintf (symbol_name, "rgctx_trampolines_page_%s_p", is_generic ? "gen" : "sp");
-       else if (tramp_type == MONO_AOT_TRAMP_IMT_THUNK)
+       else if (tramp_type == MONO_AOT_TRAMP_IMT)
                sprintf (symbol_name, "imt_trampolines_page_%s_p", is_generic ? "gen" : "sp");
        else if (tramp_type == MONO_AOT_TRAMP_GSHAREDVT_ARG)
                sprintf (symbol_name, "gsharedvt_trampolines_page_%s_p", is_generic ? "gen" : "sp");
@@ -5234,7 +5234,7 @@ get_new_trampoline_from_page (int tramp_type)
                tpage = load_function (amodule, "specific_trampolines_page");
        else if (tramp_type == MONO_AOT_TRAMP_STATIC_RGCTX)
                tpage = load_function (amodule, "rgctx_trampolines_page");
-       else if (tramp_type == MONO_AOT_TRAMP_IMT_THUNK)
+       else if (tramp_type == MONO_AOT_TRAMP_IMT)
                tpage = load_function (amodule, "imt_trampolines_page");
        else if (tramp_type == MONO_AOT_TRAMP_GSHAREDVT_ARG)
                tpage = load_function (amodule, "gsharedvt_arg_trampolines_page");
@@ -5362,7 +5362,7 @@ get_new_imt_trampoline_from_page (gpointer arg)
        void *code;
        gpointer *data;
 
-       code = get_new_trampoline_from_page (MONO_AOT_TRAMP_IMT_THUNK);
+       code = get_new_trampoline_from_page (MONO_AOT_TRAMP_IMT);
 
        data = (gpointer*)((char*)code - MONO_AOT_TRAMP_PAGE_SIZE);
        data [0] = arg;
@@ -5615,13 +5615,13 @@ mono_aot_get_lazy_fetch_trampoline (guint32 slot)
 }
 
 static void
-no_imt_thunk (void)
+no_imt_trampoline (void)
 {
-       g_assert_not_reached ();
+       g_assert_not_reached ();
 }
 
 gpointer
-mono_aot_get_imt_thunk (MonoVTable *vtable, MonoDomain *domain, MonoIMTCheckItem **imt_entries, int count, gpointer fail_tramp)
+mono_aot_get_imt_trampoline (MonoVTable *vtable, MonoDomain *domain, MonoIMTCheckItem **imt_entries, int count, gpointer fail_tramp)
 {
        guint32 got_offset;
        gpointer code;
@@ -5630,7 +5630,7 @@ mono_aot_get_imt_thunk (MonoVTable *vtable, MonoDomain *domain, MonoIMTCheckItem
        MonoAotModule *amodule;
 
        if (mono_llvm_only)
-               return no_imt_thunk;
+               return no_imt_trampoline;
 
        real_count = 0;
        for (i = 0; i < count; ++i) {
@@ -5667,7 +5667,7 @@ mono_aot_get_imt_thunk (MonoVTable *vtable, MonoDomain *domain, MonoIMTCheckItem
        if (USE_PAGE_TRAMPOLINES) {
                code = get_new_imt_trampoline_from_page (buf);
        } else {
-               code = get_numerous_trampoline (MONO_AOT_TRAMP_IMT_THUNK, 1, &amodule, &got_offset, NULL);
+               code = get_numerous_trampoline (MONO_AOT_TRAMP_IMT, 1, &amodule, &got_offset, NULL);
 
                amodule->got [got_offset] = buf;
        }
@@ -5948,7 +5948,7 @@ mono_aot_get_lazy_fetch_trampoline (guint32 slot)
 }
 
 gpointer
-mono_aot_get_imt_thunk (MonoVTable *vtable, MonoDomain *domain, MonoIMTCheckItem **imt_entries, int count, gpointer fail_tramp)
+mono_aot_get_imt_trampoline (MonoVTable *vtable, MonoDomain *domain, MonoIMTCheckItem **imt_entries, int count, gpointer fail_tramp)
 {
        g_assert_not_reached ();
        return NULL;
index 22f063c59640e9253d58be382839db3c838575e7..7aa562c591db78c8118002b5f80503112154414c 100644 (file)
@@ -271,7 +271,7 @@ typedef struct {
 #define HEADER_LENGTH 11
 
 #define MAJOR_VERSION 2
-#define MINOR_VERSION 42
+#define MINOR_VERSION 43
 
 typedef enum {
        CMD_SET_VM = 1,
@@ -1627,12 +1627,7 @@ stop_debugger_thread (void)
 static void
 start_debugger_thread (void)
 {
-       MonoThreadParm tp;
-
-       tp.priority = MONO_THREAD_PRIORITY_NORMAL;
-       tp.stack_size = 0;
-       tp.creation_flags = 0;
-       debugger_thread_handle = mono_threads_create_thread (debugger_thread, NULL, &tp, NULL);
+       debugger_thread_handle = mono_threads_create_thread (debugger_thread, NULL, 0, NULL);
        g_assert (debugger_thread_handle);
 }
 
@@ -8627,6 +8622,12 @@ method_commands_internal (int command, MonoMethod *method, MonoDomain *domain, g
 
                locals = mono_debug_lookup_locals (method);
                if (!locals) {
+                       if (CHECK_PROTOCOL_VERSION (2, 43)) {
+                               /* Scopes */
+                               buffer_add_int (buf, 1);
+                               buffer_add_int (buf, 0);
+                               buffer_add_int (buf, header->code_size);
+                       }
                        buffer_add_int (buf, header->num_locals);
                        /* Types */
                        for (i = 0; i < header->num_locals; ++i) {
@@ -8644,6 +8645,17 @@ method_commands_internal (int command, MonoMethod *method, MonoDomain *domain, g
                                buffer_add_int (buf, header->code_size);
                        }
                } else {
+                       if (CHECK_PROTOCOL_VERSION (2, 43)) {
+                               /* Scopes */
+                               buffer_add_int (buf, locals->num_blocks);
+                               int last_start = 0;
+                               for (i = 0; i < locals->num_blocks; ++i) {
+                                       buffer_add_int (buf, locals->code_blocks [i].start_offset - last_start);
+                                       buffer_add_int (buf, locals->code_blocks [i].end_offset - locals->code_blocks [i].start_offset);
+                                       last_start = locals->code_blocks [i].start_offset;
+                               }
+                       }
+
                        num_locals = locals->num_locals;
                        buffer_add_int (buf, num_locals);
 
index bd6e19fc4f50a07f60071c1ecd484b9cd3db2a60..a6d2bd117b1f75181421b9e0b65ddb23265e5fd7 100644 (file)
@@ -1748,6 +1748,7 @@ mono_main (int argc, char* argv[])
                } else if (strcmp (argv [i], "--llvmonly") == 0) {
                        mono_aot_only = TRUE;
                        mono_llvm_only = TRUE;
+               } else if (strcmp (argv [i], "--hybrid-aot") == 0) {
                } else if (strcmp (argv [i], "--print-vtable") == 0) {
                        mono_print_vtable = TRUE;
                } else if (strcmp (argv [i], "--stats") == 0) {
index f8a328375b90de9bdc0344ff7e26192e50b46dc0..bb9c73c0400956edce182fcea82cc2887e726cd9 100644 (file)
@@ -1715,7 +1715,7 @@ mono_resolve_generic_virtual_call (MonoVTable *vt, int slot, MonoMethod *generic
 
        /*
         * This wastes memory but the memory usage is bounded since
-        * mono_method_add_generic_virtual_invocation () eventually builds an imt thunk for
+        * mono_method_add_generic_virtual_invocation () eventually builds an imt trampoline for
         * this vtable slot so we are not called any more for this instantiation.
         */
        MonoFtnDesc *ftndesc = mini_create_llvmonly_ftndesc (mono_domain_get (), addr, arg);
@@ -1765,7 +1765,7 @@ mono_resolve_generic_virtual_iface_call (MonoVTable *vt, int imt_slot, MonoMetho
 
        /*
         * This wastes memory but the memory usage is bounded since
-        * mono_method_add_generic_virtual_invocation () eventually builds an imt thunk for
+        * mono_method_add_generic_virtual_invocation () eventually builds an imt trampoline for
         * this vtable slot so we are not called any more for this instantiation.
         */
        MonoFtnDesc *ftndesc = mini_create_llvmonly_ftndesc (mono_domain_get (), addr, arg);
index 6769d9c5f85fd622df4f250c8e865e678eef8fb8..72d0d5e9655049fb9eab9af9ba4966ef662616fd 100644 (file)
@@ -154,8 +154,7 @@ emit_llvmonly_virtual_call (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSig
 /* helper methods signatures */
 static MonoMethodSignature *helper_sig_domain_get;
 static MonoMethodSignature *helper_sig_rgctx_lazy_fetch_trampoline;
-static MonoMethodSignature *helper_sig_llvmonly_imt_thunk;
-
+static MonoMethodSignature *helper_sig_llvmonly_imt_trampoline;
 
 /* type loading helpers */
 static GENERATE_GET_CLASS_WITH_CACHE (runtime_helpers, System.Runtime.CompilerServices, RuntimeHelpers)
@@ -364,7 +363,7 @@ mono_create_helper_signatures (void)
 {
        helper_sig_domain_get = mono_create_icall_signature ("ptr");
        helper_sig_rgctx_lazy_fetch_trampoline = mono_create_icall_signature ("ptr ptr");
-       helper_sig_llvmonly_imt_thunk = mono_create_icall_signature ("ptr ptr ptr");
+       helper_sig_llvmonly_imt_trampoline = mono_create_icall_signature ("ptr ptr ptr");
 }
 
 static MONO_NEVER_INLINE void
@@ -7809,7 +7808,7 @@ emit_llvmonly_virtual_call (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSig
                icall_args [0] = thunk_arg_ins;
                icall_args [1] = emit_get_rgctx_method (cfg, context_used,
                                                                                                cmethod, MONO_RGCTX_INFO_METHOD);
-               ftndesc_ins = mono_emit_calli (cfg, helper_sig_llvmonly_imt_thunk, icall_args, thunk_addr_ins, NULL, NULL);
+               ftndesc_ins = mono_emit_calli (cfg, helper_sig_llvmonly_imt_trampoline, icall_args, thunk_addr_ins, NULL, NULL);
 
                return emit_llvmonly_calli (cfg, fsig, sp, ftndesc_ins);
        }
@@ -7852,7 +7851,7 @@ emit_llvmonly_virtual_call (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSig
                icall_args [0] = thunk_arg_ins;
                icall_args [1] = emit_get_rgctx_method (cfg, context_used,
                                                                                                cmethod, MONO_RGCTX_INFO_METHOD);
-               ftndesc_ins = mono_emit_calli (cfg, helper_sig_llvmonly_imt_thunk, icall_args, thunk_addr_ins, NULL, NULL);
+               ftndesc_ins = mono_emit_calli (cfg, helper_sig_llvmonly_imt_trampoline, icall_args, thunk_addr_ins, NULL, NULL);
                ftndesc_ins->dreg = ftndesc_reg;
                /*
                 * Unlike normal iface calls, these imt thunks can return NULL, i.e. when they are passed an instantiation
@@ -9629,7 +9628,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                if (cfg->gsharedvt && mini_is_gsharedvt_signature (fsig))
                                        GSHAREDVT_FAILURE (*ip);
 
-                               if (cfg->backend->have_generalized_imt_thunk && cfg->backend->gshared_supported && cmethod->wrapper_type == MONO_WRAPPER_NONE) {
+                               if (cfg->backend->have_generalized_imt_trampoline && cfg->backend->gshared_supported && cmethod->wrapper_type == MONO_WRAPPER_NONE) {
                                        g_assert (!imt_arg);
                                        if (!context_used)
                                                g_assert (cmethod->is_inflated);
index f9a0d5adc8bdfa90c778cbc613c58ecf6d0f4fc0..4723e49b117d17247b5a5c1b1c7370c18ed18068 100644 (file)
@@ -7989,7 +7989,7 @@ imt_branch_distance (MonoIMTCheckItem **imt_entries, int start, int target)
  * LOCKING: called with the domain lock held
  */
 gpointer
-mono_arch_build_imt_thunk (MonoVTable *vtable, MonoDomain *domain, MonoIMTCheckItem **imt_entries, int count,
+mono_arch_build_imt_trampoline (MonoVTable *vtable, MonoDomain *domain, MonoIMTCheckItem **imt_entries, int count,
        gpointer fail_tramp)
 {
        int i;
@@ -8043,7 +8043,7 @@ mono_arch_build_imt_thunk (MonoVTable *vtable, MonoDomain *domain, MonoIMTCheckI
                size += item->chunk_size;
        }
        if (fail_tramp)
-               code = (guint8 *)mono_method_alloc_generic_virtual_thunk (domain, size);
+               code = (guint8 *)mono_method_alloc_generic_virtual_trampoline (domain, size);
        else
                code = (guint8 *)mono_domain_code_reserve (domain, size);
        start = code;
@@ -8134,7 +8134,7 @@ mono_arch_build_imt_thunk (MonoVTable *vtable, MonoDomain *domain, MonoIMTCheckI
        }
 
        if (!fail_tramp)
-               mono_stats.imt_thunks_size += code - start;
+               mono_stats.imt_trampolines_size += code - start;
        g_assert (code - start <= size);
 
        mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_IMT_TRAMPOLINE, NULL);
index 22e7413a6f531cb207b974d0cefdfff2605a12e9..8ac16a17176d26319836dee254922c1c16dc1632 100644 (file)
@@ -386,7 +386,7 @@ typedef struct {
 #define MONO_ARCH_EXC_REG AMD64_RAX
 #define MONO_ARCH_HAVE_CMOV_OPS 1
 #define MONO_ARCH_HAVE_EXCEPTIONS_INIT 1
-#define MONO_ARCH_HAVE_GENERALIZED_IMT_THUNK 1
+#define MONO_ARCH_HAVE_GENERALIZED_IMT_TRAMPOLINE 1
 #define MONO_ARCH_HAVE_LIVERANGE_OPS 1
 #define MONO_ARCH_HAVE_SIGCTX_TO_MONOCTX 1
 #define MONO_ARCH_HAVE_GET_TRAMPOLINES 1
index 7b2e1fa7b48e2438c7e85deeb87108be375a6936..82795e5b8e87e2e46c65bcc40e55190c19b4b338 100644 (file)
@@ -836,8 +836,8 @@ mono_arch_init (void)
                if (!mono_aot_only)
                        breakpoint_tramp = mini_get_breakpoint_trampoline ();
        } else {
-               ss_trigger_page = mono_valloc (NULL, mono_pagesize (), MONO_MMAP_READ|MONO_MMAP_32BIT);
-               bp_trigger_page = mono_valloc (NULL, mono_pagesize (), MONO_MMAP_READ|MONO_MMAP_32BIT);
+               ss_trigger_page = mono_valloc (NULL, mono_pagesize (), MONO_MMAP_READ|MONO_MMAP_32BIT, MONO_MEM_ACCOUNT_OTHER);
+               bp_trigger_page = mono_valloc (NULL, mono_pagesize (), MONO_MMAP_READ|MONO_MMAP_32BIT, MONO_MEM_ACCOUNT_OTHER);
                mono_mprotect (bp_trigger_page, mono_pagesize (), 0);
        }
 
@@ -6922,7 +6922,7 @@ mini_dump_bad_imt (int input_imt, int compared_imt, int pc)
 #endif
 
 gpointer
-mono_arch_build_imt_thunk (MonoVTable *vtable, MonoDomain *domain, MonoIMTCheckItem **imt_entries, int count,
+mono_arch_build_imt_trampoline (MonoVTable *vtable, MonoDomain *domain, MonoIMTCheckItem **imt_entries, int count,
        gpointer fail_tramp)
 {
        int size, i;
@@ -6974,7 +6974,7 @@ mono_arch_build_imt_thunk (MonoVTable *vtable, MonoDomain *domain, MonoIMTCheckI
                size += 4 * count; /* The ARM_ADD_REG_IMM to pop the stack */
 
        if (fail_tramp)
-               code = mono_method_alloc_generic_virtual_thunk (domain, size);
+               code = mono_method_alloc_generic_virtual_trampoline (domain, size);
        else
                code = mono_domain_code_reserve (domain, size);
        start = code;
@@ -6982,7 +6982,7 @@ mono_arch_build_imt_thunk (MonoVTable *vtable, MonoDomain *domain, MonoIMTCheckI
        unwind_ops = mono_arch_get_cie_program ();
 
 #ifdef DEBUG_IMT
-       g_print ("Building IMT thunk for class %s %s entries %d code size %d code at %p end %p vtable %p fail_tramp %p\n", vtable->klass->name_space, vtable->klass->name, count, size, start, ((guint8*)start) + size, vtable, fail_tramp);
+       g_print ("Building IMT trampoline for class %s %s entries %d code size %d code at %p end %p vtable %p fail_tramp %p\n", vtable->klass->name_space, vtable->klass->name, count, size, start, ((guint8*)start) + size, vtable, fail_tramp);
        for (i = 0; i < count; ++i) {
                MonoIMTCheckItem *item = imt_entries [i];
                g_print ("method %d (%p) %s vtable slot %p is_equals %d chunk size %d\n", i, item->key, ((MonoMethod*)item->key)->name, &vtable->vtable [item->value.vtable_slot], item->is_equals, item->chunk_size);
@@ -7148,7 +7148,7 @@ mono_arch_build_imt_thunk (MonoVTable *vtable, MonoDomain *domain, MonoIMTCheckI
 
        mono_arch_flush_icache ((guint8*)start, size);
        mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_IMT_TRAMPOLINE, NULL);
-       mono_stats.imt_thunks_size += code - start;
+       mono_stats.imt_trampolines_size += code - start;
 
        g_assert (DISTANCE (start, code) <= size);
 
index bc23a423d29a1f576c26f969c33e26ffd9d7a180..cb31a6e8b24f64f192e21cb32e1075805fbe0a8d 100644 (file)
@@ -316,7 +316,7 @@ typedef struct MonoCompileArch {
 
 #define MONO_ARCH_NEED_DIV_CHECK 1
 
-#define MONO_ARCH_HAVE_GENERALIZED_IMT_THUNK 1
+#define MONO_ARCH_HAVE_GENERALIZED_IMT_TRAMPOLINE 1
 
 #define MONO_ARCH_HAVE_FULL_AOT_TRAMPOLINES 1
 #define MONO_ARCH_HAVE_DECOMPOSE_LONG_OPTS 1
index 688594d96602b50770485925c92a521726edeea7..bc1b5021a01789137c35ed9956bea63247af10ba 100644 (file)
@@ -839,6 +839,7 @@ emit_thunk (guint8 *code, gconstpointer target)
        arm_ldrx_lit (code, ARMREG_IP0, code + 8);
        arm_brx (code, ARMREG_IP0);
        *(guint64*)code = (guint64)target;
+       code += sizeof (guint64);
 
        mono_arch_flush_icache (p, code - p);
        return code;
@@ -1776,7 +1777,33 @@ mono_arch_flush_icache (guint8 *code, gint size)
 #if __APPLE__
        sys_icache_invalidate (code, size);
 #else
-       __clear_cache (code, code + size);
+       /* Don't rely on GCC's __clear_cache implementation, as it caches
+        * icache/dcache cache line sizes, that can vary between cores on
+        * big.LITTLE architectures. */
+       guint64 end = (guint64) (code + size);
+       guint64 addr, ctr_el0;
+       static size_t icache_line_size = 0xffff, dcache_line_size = 0xffff;
+       size_t isize, dsize;
+
+       asm volatile ("mrs %0, ctr_el0" : "=r" (ctr_el0));
+       isize = 4 << ((ctr_el0 >> 0 ) & 0xf);
+       dsize = 4 << ((ctr_el0 >> 16) & 0xf);
+
+       /* determine the global minimum cache line size */
+       icache_line_size = isize = MIN (icache_line_size, isize);
+       dcache_line_size = dsize = MIN (dcache_line_size, dsize);
+
+       addr = (guint64) code & ~(guint64) (dsize - 1);
+       for (; addr < end; addr += dsize)
+               asm volatile("dc civac, %0" : : "r" (addr) : "memory");
+       asm volatile("dsb ish" : : : "memory");
+
+       addr = (guint64) code & ~(guint64) (isize - 1);
+       for (; addr < end; addr += isize)
+               asm volatile("ic ivau, %0" : : "r" (addr) : "memory");
+
+       asm volatile ("dsb ish" : : : "memory");
+       asm volatile ("isb" : : : "memory");
 #endif
 #endif
 }
@@ -4951,14 +4978,14 @@ mono_arch_get_patch_offset (guint8 *code)
 }
 
 gpointer
-mono_arch_build_imt_thunk (MonoVTable *vtable, MonoDomain *domain, MonoIMTCheckItem **imt_entries, int count,
-                                                  gpointer fail_tramp)
+mono_arch_build_imt_trampoline (MonoVTable *vtable, MonoDomain *domain, MonoIMTCheckItem **imt_entries, int count,
+                                                               gpointer fail_tramp)
 {
        int i, buf_len, imt_reg;
        guint8 *buf, *code;
 
 #if DEBUG_IMT
-       printf ("building IMT thunk for class %s %s entries %d code size %d code at %p end %p vtable %p\n", vtable->klass->name_space, vtable->klass->name, count, size, start, ((guint8*)start) + size, vtable);
+       printf ("building IMT trampoline for class %s %s entries %d code size %d code at %p end %p vtable %p\n", vtable->klass->name_space, vtable->klass->name, count, size, start, ((guint8*)start) + size, vtable);
        for (i = 0; i < count; ++i) {
                MonoIMTCheckItem *item = imt_entries [i];
                printf ("method %d (%p) %s vtable slot %p is_equals %d chunk size %d\n", i, item->key, item->key->name, &vtable->vtable [item->value.vtable_slot], item->is_equals, item->chunk_size);
@@ -4993,7 +5020,7 @@ mono_arch_build_imt_thunk (MonoVTable *vtable, MonoDomain *domain, MonoIMTCheckI
        }
 
        if (fail_tramp)
-               buf = mono_method_alloc_generic_virtual_thunk (domain, buf_len);
+               buf = mono_method_alloc_generic_virtual_trampoline (domain, buf_len);
        else
                buf = mono_domain_code_reserve (domain, buf_len);
        code = buf;
@@ -5081,8 +5108,8 @@ mono_arch_get_trampolines (gboolean aot)
 #else /* DISABLE_JIT */
 
 gpointer
-mono_arch_build_imt_thunk (MonoVTable *vtable, MonoDomain *domain, MonoIMTCheckItem **imt_entries, int count,
-                                                  gpointer fail_tramp)
+mono_arch_build_imt_trampoline (MonoVTable *vtable, MonoDomain *domain, MonoIMTCheckItem **imt_entries, int count,
+                                                               gpointer fail_tramp)
 {
        g_assert_not_reached ();
        return NULL;
index e3e90eb6ea59bd350346001e0c5c22a065e4349e..8af5ca7f7d72bcc37f8677c28aceaab3fe4bcef2 100644 (file)
@@ -130,7 +130,7 @@ typedef struct {
 #define MONO_ARCH_EXC_REG ARMREG_R0
 #define MONO_ARCH_HAVE_XP_UNWIND 1
 #define MONO_ARCH_HAVE_CREATE_DELEGATE_TRAMPOLINE 1
-#define MONO_ARCH_HAVE_GENERALIZED_IMT_THUNK 1
+#define MONO_ARCH_HAVE_GENERALIZED_IMT_TRAMPOLINE 1
 #define MONO_ARCH_USE_SIGACTION 1
 #define MONO_ARCH_HAVE_SIGCTX_TO_MONOCTX 1
 #define MONO_ARCH_HAVE_CONTEXT_SET_INT_REG 1
index 2a437730a73b5d0e4057ec4f461a1bdefe98de4b..265be946e51a8309da60e9c35721695acc315a7e 100644 (file)
@@ -2060,13 +2060,13 @@ mono_setup_altstack (MonoJitTlsData *tls)
 
        if (mono_mprotect (tls->stack_ovf_guard_base, tls->stack_ovf_guard_size, MONO_MMAP_NONE)) {
                /* mprotect can fail for the main thread stack */
-               gpointer gaddr = mono_valloc (tls->stack_ovf_guard_base, tls->stack_ovf_guard_size, MONO_MMAP_NONE|MONO_MMAP_PRIVATE|MONO_MMAP_ANON|MONO_MMAP_FIXED);
+               gpointer gaddr = mono_valloc (tls->stack_ovf_guard_base, tls->stack_ovf_guard_size, MONO_MMAP_NONE|MONO_MMAP_PRIVATE|MONO_MMAP_ANON|MONO_MMAP_FIXED, MONO_MEM_ACCOUNT_EXCEPTIONS);
                g_assert (gaddr == tls->stack_ovf_guard_base);
                tls->stack_ovf_valloced = TRUE;
        }
 
        /* Setup an alternate signal stack */
-       tls->signal_stack = mono_valloc (0, MONO_ARCH_SIGNAL_STACK_SIZE, MONO_MMAP_READ|MONO_MMAP_WRITE|MONO_MMAP_PRIVATE|MONO_MMAP_ANON);
+       tls->signal_stack = mono_valloc (0, MONO_ARCH_SIGNAL_STACK_SIZE, MONO_MMAP_READ|MONO_MMAP_WRITE|MONO_MMAP_PRIVATE|MONO_MMAP_ANON, MONO_MEM_ACCOUNT_EXCEPTIONS);
        tls->signal_stack_size = MONO_ARCH_SIGNAL_STACK_SIZE;
 
        g_assert (tls->signal_stack);
@@ -2092,9 +2092,9 @@ mono_free_altstack (MonoJitTlsData *tls)
        g_assert (err == 0);
 
        if (tls->signal_stack)
-               mono_vfree (tls->signal_stack, MONO_ARCH_SIGNAL_STACK_SIZE);
+               mono_vfree (tls->signal_stack, MONO_ARCH_SIGNAL_STACK_SIZE, MONO_MEM_ACCOUNT_EXCEPTIONS);
        if (tls->stack_ovf_valloced)
-               mono_vfree (tls->stack_ovf_guard_base, tls->stack_ovf_guard_size);
+               mono_vfree (tls->stack_ovf_guard_base, tls->stack_ovf_guard_size, MONO_MEM_ACCOUNT_EXCEPTIONS);
        else
                mono_mprotect (tls->stack_ovf_guard_base, tls->stack_ovf_guard_size, MONO_MMAP_READ|MONO_MMAP_WRITE);
 }
@@ -2389,7 +2389,7 @@ mono_handle_native_sigsegv (int signal, void *ctx, MONO_SIG_HANDLER_INFO_TYPE *i
        for (i =0; i < size; ++i) {
                mono_runtime_printf_err ("\t%s", names [i]);
        }
-       free (names);
+       g_free (names);
 
        /* Try to get more meaningful information using gdb */
 
index 357e260799833ed8d4a1bf415c148853bf610e39..4cd9b377e3e2c933f1a7354396eef49194c34f3e 100644 (file)
@@ -4532,8 +4532,8 @@ mono_arch_free_jit_tls_data (MonoJitTlsData *tls)
  * LOCKING: called with the domain lock held
  */
 gpointer
-mono_arch_build_imt_thunk (MonoVTable *vtable, MonoDomain *domain, MonoIMTCheckItem **imt_entries, int count,
-       gpointer fail_tramp)
+mono_arch_build_imt_trampoline (MonoVTable *vtable, MonoDomain *domain, MonoIMTCheckItem **imt_entries, int count,
+                                                               gpointer fail_tramp)
 {
        int i;
        int size = 0;
@@ -4613,7 +4613,7 @@ mono_arch_build_imt_thunk (MonoVTable *vtable, MonoDomain *domain, MonoIMTCheckI
 
        size = code.buf - buf;
        if (fail_tramp) {
-               start = mono_method_alloc_generic_virtual_thunk (domain, size + 16);
+               start = mono_method_alloc_generic_virtual_trampoline (domain, size + 16);
                start = (gpointer)ALIGN_TO (start, 16);
        } else {
                start = mono_domain_code_reserve (domain, size);
index bcb30ead561a6eca9a86a91aacca174989697d5c..bfee9d5c5480a3f0b0fb876524f6952cf2a5ef79 100644 (file)
@@ -109,6 +109,6 @@ unw_dyn_region_info_t* mono_ia64_create_unwind_region (Ia64CodegenState *code);
 
 #define MONO_ARCH_HAVE_INVALIDATE_METHOD 1
 #define MONO_ARCH_HAVE_SAVE_UNWIND_INFO 1
-#define MONO_ARCH_HAVE_GENERALIZED_IMT_THUNK 1
+#define MONO_ARCH_HAVE_GENERALIZED_IMT_TRAMPOLINE 1
 
 #endif /* __MONO_MINI_IA64_H__ */  
index 3ca1bca04c16a83087b5b01bf5c6eba63f020576..2ae3051b52074b80362733162ba2fcfa9fb5dc37 100644 (file)
@@ -4154,7 +4154,8 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb)
                         * can work around that by doing a volatile load + cond branch from
                         * localloc-ed memory.
                         */
-                       //set_failure (ctx, "basic block too long");
+                       if (!cfg->llvm_only)
+                               set_failure (ctx, "basic block too long");
                        cbb = gen_bb (ctx, "CONT_LONG_BB");
                        LLVMBuildBr (ctx->builder, cbb);
                        ctx->builder = builder = create_builder (ctx);
@@ -8610,7 +8611,7 @@ emit_aot_file_info (MonoLLVMModule *module)
        if (info->trampoline_size [0]) {
                fields [tindex ++] = AddJitGlobal (module, eltype, "specific_trampolines");
                fields [tindex ++] = AddJitGlobal (module, eltype, "static_rgctx_trampolines");
-               fields [tindex ++] = AddJitGlobal (module, eltype, "imt_thunks");
+               fields [tindex ++] = AddJitGlobal (module, eltype, "imt_trampolines");
                fields [tindex ++] = AddJitGlobal (module, eltype, "gsharedvt_arg_trampolines");
        } else {
                fields [tindex ++] = LLVMConstNull (eltype);
index 783896f15681743acb6001dad302705db271bee9..8af84338759ecf8629b8b541dfb679058df08b2e 100644 (file)
@@ -714,8 +714,8 @@ mono_arch_init (void)
 {
        mono_os_mutex_init_recursive (&mini_arch_mutex);
 
-       ss_trigger_page = mono_valloc (NULL, mono_pagesize (), MONO_MMAP_READ|MONO_MMAP_32BIT);
-       bp_trigger_page = mono_valloc (NULL, mono_pagesize (), MONO_MMAP_READ|MONO_MMAP_32BIT);
+       ss_trigger_page = mono_valloc (NULL, mono_pagesize (), MONO_MMAP_READ|MONO_MMAP_32BIT, MONO_MEM_ACCOUNT_OTHER);
+       bp_trigger_page = mono_valloc (NULL, mono_pagesize (), MONO_MMAP_READ|MONO_MMAP_32BIT, MONO_MEM_ACCOUNT_OTHER);
        mono_mprotect (bp_trigger_page, mono_pagesize (), 0);
 }
 
@@ -5889,8 +5889,8 @@ mono_arch_context_get_int_reg (MonoContext *ctx, int reg)
  * LOCKING: called with the domain lock held
  */
 gpointer
-mono_arch_build_imt_thunk (MonoVTable *vtable, MonoDomain *domain, MonoIMTCheckItem **imt_entries, int count,
-       gpointer fail_tramp)
+mono_arch_build_imt_trampoline (MonoVTable *vtable, MonoDomain *domain, MonoIMTCheckItem **imt_entries, int count,
+                                                               gpointer fail_tramp)
 {
        int i;
        int size = 0;
@@ -5928,7 +5928,7 @@ mono_arch_build_imt_thunk (MonoVTable *vtable, MonoDomain *domain, MonoIMTCheckI
        /* the initial load of the vtable address */
        size += MIPS_LOAD_SEQUENCE_LENGTH;
        if (fail_tramp) {
-               code = mono_method_alloc_generic_virtual_thunk (domain, size);
+               code = mono_method_alloc_generic_virtual_trampoline (domain, size);
        } else {
                code = mono_domain_code_reserve (domain, size);
        }
@@ -6016,7 +6016,7 @@ mono_arch_build_imt_thunk (MonoVTable *vtable, MonoDomain *domain, MonoIMTCheckI
        }
 
        if (!fail_tramp)
-               mono_stats.imt_thunks_size += code - start;
+               mono_stats.imt_trampolines_size += code - start;
        g_assert (code - start <= size);
        mono_arch_flush_icache (start, size);
 
index 73d0ad3272062fad992e68c42e33ca075b703a07..06c533aee46cffa33e738dfd1b665dd6685f85e9 100644 (file)
@@ -264,7 +264,7 @@ typedef struct MonoCompileArch {
 #define MONO_ARCH_HAVE_DECOMPOSE_OPTS 1
 #define MONO_ARCH_HAVE_DECOMPOSE_LONG_OPTS 1
 
-#define MONO_ARCH_HAVE_GENERALIZED_IMT_THUNK 1
+#define MONO_ARCH_HAVE_GENERALIZED_IMT_TRAMPOLINE 1
 #define MONO_ARCH_SOFT_DEBUG_SUPPORTED 1
 #define MONO_ARCH_HAVE_SIGCTX_TO_MONOCTX 1
 #define MONO_ARCH_HAVE_SETUP_RESUME_FROM_SIGNAL_HANDLER_CTX 1
index 7d2c0d8b8cfda73cacd3b6847b37f7c5dd523da4..656ba1ed916e58c7eec2c00d683cea8fb106d1e6 100644 (file)
@@ -627,8 +627,8 @@ mono_arch_init (void)
 
        mono_os_mutex_init_recursive (&mini_arch_mutex);
 
-       ss_trigger_page = mono_valloc (NULL, mono_pagesize (), MONO_MMAP_READ|MONO_MMAP_32BIT);
-       bp_trigger_page = mono_valloc (NULL, mono_pagesize (), MONO_MMAP_READ|MONO_MMAP_32BIT);
+       ss_trigger_page = mono_valloc (NULL, mono_pagesize (), MONO_MMAP_READ|MONO_MMAP_32BIT, MONO_MEM_ACCOUNT_OTHER);
+       bp_trigger_page = mono_valloc (NULL, mono_pagesize (), MONO_MMAP_READ|MONO_MMAP_32BIT, MONO_MEM_ACCOUNT_OTHER);
        mono_mprotect (bp_trigger_page, mono_pagesize (), 0);
 
        mono_aot_register_jit_icall ("mono_ppc_throw_exception", mono_ppc_throw_exception);
@@ -5824,8 +5824,8 @@ mono_arch_free_jit_tls_data (MonoJitTlsData *tls)
  * LOCKING: called with the domain lock held
  */
 gpointer
-mono_arch_build_imt_thunk (MonoVTable *vtable, MonoDomain *domain, MonoIMTCheckItem **imt_entries, int count,
-       gpointer fail_tramp)
+mono_arch_build_imt_trampoline (MonoVTable *vtable, MonoDomain *domain, MonoIMTCheckItem **imt_entries, int count,
+                                                               gpointer fail_tramp)
 {
        int i;
        int size = 0;
@@ -5862,7 +5862,7 @@ mono_arch_build_imt_thunk (MonoVTable *vtable, MonoDomain *domain, MonoIMTCheckI
        /* the initial load of the vtable address */
        size += PPC_LOAD_SEQUENCE_LENGTH + LOADSTORE_SIZE;
        if (fail_tramp) {
-               code = mono_method_alloc_generic_virtual_thunk (domain, size);
+               code = mono_method_alloc_generic_virtual_trampoline (domain, size);
        } else {
                code = mono_domain_code_reserve (domain, size);
        }
@@ -5955,7 +5955,7 @@ mono_arch_build_imt_thunk (MonoVTable *vtable, MonoDomain *domain, MonoIMTCheckI
        }
 
        if (!fail_tramp)
-               mono_stats.imt_thunks_size += code - start;
+               mono_stats.imt_trampolines_size += code - start;
        g_assert (code - start <= size);
        mono_arch_flush_icache (start, size);
 
index b0d4654de83ef98cbbb778de7b877fa6a16d860b..2ea49cc45689839ed2262a3a372731b8fa5a69b6 100644 (file)
@@ -221,7 +221,7 @@ typedef struct MonoCompileArch {
 #define MONO_ARCH_HAVE_DECOMPOSE_OPTS 1
 #define MONO_ARCH_HAVE_DECOMPOSE_LONG_OPTS 1
 
-#define MONO_ARCH_HAVE_GENERALIZED_IMT_THUNK 1
+#define MONO_ARCH_HAVE_GENERALIZED_IMT_TRAMPOLINE 1
 
 #define MONO_ARCH_HAVE_FULL_AOT_TRAMPOLINES 1
 
index f4f30c69e6ba02fb18ddc33d4b0c2e580d4d541b..a9c87011153b35ba64bf2d25f057801ea21ee03a 100644 (file)
@@ -2562,34 +2562,34 @@ mono_jit_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObjec
 typedef struct {
        MonoVTable *vtable;
        int slot;
-} IMTThunkInfo;
+} IMTTrampInfo;
 
-typedef gpointer (*IMTThunkFunc) (gpointer *arg, MonoMethod *imt_method);
+typedef gpointer (*IMTTrampFunc) (gpointer *arg, MonoMethod *imt_method);
 
 /*
- * mini_llvmonly_initial_imt_thunk:
+ * mini_llvmonly_initial_imt_tramp:
  *
- *  This function is called the first time a call is made through an IMT thunk.
- * It should have the same signature as the mono_llvmonly_imt_thunk_... functions.
+ *  This function is called the first time a call is made through an IMT trampoline.
+ * It should have the same signature as the mono_llvmonly_imt_tramp_... functions.
  */
 static gpointer
-mini_llvmonly_initial_imt_thunk (gpointer *arg, MonoMethod *imt_method)
+mini_llvmonly_initial_imt_tramp (gpointer *arg, MonoMethod *imt_method)
 {
-       IMTThunkInfo *info = (IMTThunkInfo*)arg;
+       IMTTrampInfo *info = (IMTTrampInfo*)arg;
        gpointer *imt;
        gpointer *ftndesc;
-       IMTThunkFunc func;
+       IMTTrampFunc func;
 
        mono_vtable_build_imt_slot (info->vtable, info->slot);
 
        imt = (gpointer*)info->vtable;
        imt -= MONO_IMT_SIZE;
 
-       /* Return what the real IMT thunk returns */
+       /* Return what the real IMT trampoline returns */
        ftndesc = imt [info->slot];
        func = ftndesc [0];
 
-       if (func == (IMTThunkFunc)mini_llvmonly_initial_imt_thunk)
+       if (func == (IMTTrampFunc)mini_llvmonly_initial_imt_tramp)
                /* Happens when the imt slot contains only a generic virtual method */
                return NULL;
        return func ((gpointer *)ftndesc [1], imt_method);
@@ -2597,11 +2597,11 @@ mini_llvmonly_initial_imt_thunk (gpointer *arg, MonoMethod *imt_method)
 
 /* This is called indirectly through an imt slot. */
 static gpointer
-mono_llvmonly_imt_thunk (gpointer *arg, MonoMethod *imt_method)
+mono_llvmonly_imt_tramp (gpointer *arg, MonoMethod *imt_method)
 {
        int i = 0;
 
-       /* arg points to an array created in mono_llvmonly_get_imt_thunk () */
+       /* arg points to an array created in mono_llvmonly_get_imt_trampoline () */
        while (arg [i] && arg [i] != imt_method)
                i += 2;
        g_assert (arg [i]);
@@ -2609,16 +2609,16 @@ mono_llvmonly_imt_thunk (gpointer *arg, MonoMethod *imt_method)
        return arg [i + 1];
 }
 
-/* Optimized versions of mono_llvmonly_imt_thunk () for different table sizes */
+/* Optimized versions of mono_llvmonly_imt_trampoline () for different table sizes */
 static gpointer
-mono_llvmonly_imt_thunk_1 (gpointer *arg, MonoMethod *imt_method)
+mono_llvmonly_imt_tramp_1 (gpointer *arg, MonoMethod *imt_method)
 {
        //g_assert (arg [0] == imt_method);
        return arg [1];
 }
 
 static gpointer
-mono_llvmonly_imt_thunk_2 (gpointer *arg, MonoMethod *imt_method)
+mono_llvmonly_imt_tramp_2 (gpointer *arg, MonoMethod *imt_method)
 {
        //g_assert (arg [0] == imt_method || arg [2] == imt_method);
        if (arg [0] == imt_method)
@@ -2628,7 +2628,7 @@ mono_llvmonly_imt_thunk_2 (gpointer *arg, MonoMethod *imt_method)
 }
 
 static gpointer
-mono_llvmonly_imt_thunk_3 (gpointer *arg, MonoMethod *imt_method)
+mono_llvmonly_imt_tramp_3 (gpointer *arg, MonoMethod *imt_method)
 {
        //g_assert (arg [0] == imt_method || arg [2] == imt_method || arg [4] == imt_method);
        if (arg [0] == imt_method)
@@ -2640,14 +2640,14 @@ mono_llvmonly_imt_thunk_3 (gpointer *arg, MonoMethod *imt_method)
 }
 
 /*
- * A version of the imt thunk used for generic virtual/variant iface methods.
- * Unlikely a normal imt thunk, its possible that IMT_METHOD is not found
+ * A version of the imt trampoline used for generic virtual/variant iface methods.
+ * Unlikely a normal imt trampoline, its possible that IMT_METHOD is not found
  * in the search table. The original JIT code had a 'fallback' trampoline it could
  * call, but we can't do that, so we just return NULL, and the compiled code
  * will handle it.
  */
 static gpointer
-mono_llvmonly_fallback_imt_thunk (gpointer *arg, MonoMethod *imt_method)
+mono_llvmonly_fallback_imt_tramp (gpointer *arg, MonoMethod *imt_method)
 {
        int i = 0;
 
@@ -2660,7 +2660,7 @@ mono_llvmonly_fallback_imt_thunk (gpointer *arg, MonoMethod *imt_method)
 }
 
 static gpointer
-mono_llvmonly_get_imt_thunk (MonoVTable *vtable, MonoDomain *domain, MonoIMTCheckItem **imt_entries, int count, gpointer fail_tramp)
+mono_llvmonly_get_imt_trampoline (MonoVTable *vtable, MonoDomain *domain, MonoIMTCheckItem **imt_entries, int count, gpointer fail_tramp)
 {
        gpointer *buf;
        gpointer *res;
@@ -2668,7 +2668,7 @@ mono_llvmonly_get_imt_thunk (MonoVTable *vtable, MonoDomain *domain, MonoIMTChec
        gboolean virtual_generic = FALSE;
 
        /*
-        * Create an array which is passed to the imt thunk functions.
+        * Create an array which is passed to the imt trampoline functions.
         * The array contains MonoMethod-function descriptor pairs, terminated by a NULL entry.
         */
 
@@ -2723,20 +2723,20 @@ mono_llvmonly_get_imt_thunk (MonoVTable *vtable, MonoDomain *domain, MonoIMTChec
        res = (void **)mono_domain_alloc (domain, 2 * sizeof (gpointer));
        switch (real_count) {
        case 1:
-               res [0] = mono_llvmonly_imt_thunk_1;
+               res [0] = mono_llvmonly_imt_tramp_1;
                break;
        case 2:
-               res [0] = mono_llvmonly_imt_thunk_2;
+               res [0] = mono_llvmonly_imt_tramp_2;
                break;
        case 3:
-               res [0] = mono_llvmonly_imt_thunk_3;
+               res [0] = mono_llvmonly_imt_tramp_3;
                break;
        default:
-               res [0] = mono_llvmonly_imt_thunk;
+               res [0] = mono_llvmonly_imt_tramp;
                break;
        }
        if (virtual_generic || fail_tramp)
-               res [0] = mono_llvmonly_fallback_imt_thunk;
+               res [0] = mono_llvmonly_fallback_imt_tramp;
        res [1] = buf;
 
        return res;
@@ -2958,13 +2958,13 @@ mini_get_vtable_trampoline (MonoVTable *vt, int slot_index)
 
        if (mono_llvm_only) {
                if (slot_index < 0) {
-                       /* Initialize the IMT thunks to a 'trampoline' so the generated code doesn't have to initialize it */
+                       /* Initialize the IMT trampoline to a 'trampoline' so the generated code doesn't have to initialize it */
                        // FIXME: Memory management
                        gpointer *ftndesc = g_malloc (2 * sizeof (gpointer));
-                       IMTThunkInfo *info = g_new0 (IMTThunkInfo, 1);
+                       IMTTrampInfo *info = g_new0 (IMTTrampInfo, 1);
                        info->vtable = vt;
                        info->slot = index;
-                       ftndesc [0] = mini_llvmonly_initial_imt_thunk;
+                       ftndesc [0] = mini_llvmonly_initial_imt_tramp;
                        ftndesc [1] = info;
                        mono_memory_barrier ();
                        return ftndesc;
@@ -3663,12 +3663,12 @@ mini_init (const char *filename, const char *runtime_version)
        }
 
        if (mono_llvm_only) {
-               mono_install_imt_thunk_builder (mono_llvmonly_get_imt_thunk);
-               mono_set_always_build_imt_thunks (TRUE);
+               mono_install_imt_trampoline_builder (mono_llvmonly_get_imt_trampoline);
+               mono_set_always_build_imt_trampolines (TRUE);
        } else if (mono_aot_only) {
-               mono_install_imt_thunk_builder (mono_aot_get_imt_thunk);
+               mono_install_imt_trampoline_builder (mono_aot_get_imt_trampoline);
        } else {
-               mono_install_imt_thunk_builder (mono_arch_build_imt_thunk);
+               mono_install_imt_trampoline_builder (mono_arch_build_imt_trampoline);
        }
 
        /*Init arch tls information only after the metadata side is inited to make sure we see dynamic appdomain tls keys*/
@@ -3715,6 +3715,8 @@ mini_init (const char *filename, const char *runtime_version)
                 */
                mono_runtime_set_no_exec (TRUE);
 
+       mono_mem_account_register_counters ();
+
 #define JIT_RUNTIME_WORKS
 #ifdef JIT_RUNTIME_WORKS
        mono_install_runtime_cleanup ((MonoDomainFunc)mini_cleanup);
@@ -4032,7 +4034,7 @@ print_jit_stats (void)
                g_print ("IMT colliding slots:    %ld\n", mono_stats.imt_slots_with_collisions);
                g_print ("IMT max collisions:     %ld\n", mono_stats.imt_max_collisions_in_slot);
                g_print ("IMT methods at max col: %ld\n", mono_stats.imt_method_count_when_max_collisions);
-               g_print ("IMT thunks size:        %ld\n", mono_stats.imt_thunks_size);
+               g_print ("IMT trampolines size:   %ld\n", mono_stats.imt_trampolines_size);
 
                g_print ("JIT info table inserts: %ld\n", mono_stats.jit_info_table_insert_count);
                g_print ("JIT info table removes: %ld\n", mono_stats.jit_info_table_remove_count);
index a1094afa173fbe0baeb75c2ff221e0e9b73ae7e9..420a7b1a3bf6e0ce0c8dc951b45fa71049e34eb9 100644 (file)
@@ -237,7 +237,7 @@ if (ins->inst_target_bb->native_offset) {                                   \
 #define MAX(a, b) ((a) > (b) ? (a) : (b))
 
 /*
- * imt thunking size values
+ * imt trampoline size values
  */
 #define CMP_SIZE       24
 #define LOADCON_SIZE   20
@@ -1328,8 +1328,8 @@ mono_arch_init (void)
        mono_set_partial_sharing_supported (FALSE);
        mono_os_mutex_init_recursive (&mini_arch_mutex);
 
-       ss_trigger_page = mono_valloc (NULL, mono_pagesize (), MONO_MMAP_READ);
-       bp_trigger_page = mono_valloc (NULL, mono_pagesize (), MONO_MMAP_READ);
+       ss_trigger_page = mono_valloc (NULL, mono_pagesize (), MONO_MMAP_READ, MONO_MEM_ACCOUNT_OTHER);
+       bp_trigger_page = mono_valloc (NULL, mono_pagesize (), MONO_MMAP_READ, MONO_MEM_ACCOUNT_OTHER);
        mono_mprotect (bp_trigger_page, mono_pagesize (), 0);
        
        code = (guint8 *) &breakpointCode;
@@ -1354,9 +1354,9 @@ void
 mono_arch_cleanup (void)
 {
        if (ss_trigger_page)
-               mono_vfree (ss_trigger_page, mono_pagesize ());
+               mono_vfree (ss_trigger_page, mono_pagesize (), MONO_MEM_ACCOUNT_OTHER);
        if (bp_trigger_page)
-               mono_vfree (bp_trigger_page, mono_pagesize ());
+               mono_vfree (bp_trigger_page, mono_pagesize (), MONO_MEM_ACCOUNT_OTHER);
        mono_os_mutex_destroy (&mini_arch_mutex);
 }
 
@@ -6662,16 +6662,16 @@ mono_arch_get_delegate_virtual_invoke_impl (MonoMethodSignature *sig, MonoMethod
 
 /*------------------------------------------------------------------*/
 /*                                                                  */
-/* Name                - mono_arch_build_imt_thunk.                        */
+/* Name                - mono_arch_build_imt_trampoline.                       */
 /*                                                                  */
 /* Function    -                                                   */
 /*                                                                 */
 /*------------------------------------------------------------------*/
 
 gpointer
-mono_arch_build_imt_thunk (MonoVTable *vtable, MonoDomain *domain, 
-                          MonoIMTCheckItem **imt_entries, int count,
-                          gpointer fail_tramp)
+mono_arch_build_imt_trampoline (MonoVTable *vtable, MonoDomain *domain, 
+                                                               MonoIMTCheckItem **imt_entries, int count,
+                                                               gpointer fail_tramp)
 {
        int i;
        int size = 0;
@@ -6710,7 +6710,7 @@ mono_arch_build_imt_thunk (MonoVTable *vtable, MonoDomain *domain,
        }
 
        if (fail_tramp)
-               code = mono_method_alloc_generic_virtual_thunk (domain, size);
+               code = mono_method_alloc_generic_virtual_trampoline (domain, size);
        else
                code = mono_domain_code_reserve (domain, size);
 
@@ -6793,11 +6793,11 @@ mono_arch_build_imt_thunk (MonoVTable *vtable, MonoDomain *domain,
        mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_IMT_TRAMPOLINE, NULL);
 
        if (!fail_tramp) 
-               mono_stats.imt_thunks_size += (code - start);
+               mono_stats.imt_trampolines_size += (code - start);
 
        g_assert (code - start <= size);
 
-       snprintf(trampName, sizeof(trampName), "%d_imt_thunk_trampoline", domain->domain_id);
+       snprintf(trampName, sizeof(trampName), "%d_imt_trampoline", domain->domain_id);
        mono_tramp_info_register (mono_tramp_info_create (trampName, start, code - start, NULL, NULL), domain);
 
        return (start);
index 5003bfe025403fa2d02c9709b18d04fa2e26b491..e43410353d1928e5b6ba332a678ca45426c7047b 100644 (file)
@@ -2256,8 +2256,8 @@ mono_sparc_is_virtual_call (guint32 *code)
  * LOCKING: called with the domain lock held
  */
 gpointer
-mono_arch_build_imt_thunk (MonoVTable *vtable, MonoDomain *domain, MonoIMTCheckItem **imt_entries, int count,
-       gpointer fail_tramp)
+mono_arch_build_imt_trampoline (MonoVTable *vtable, MonoDomain *domain, MonoIMTCheckItem **imt_entries, int count,
+                                                               gpointer fail_tramp)
 {
        int i;
        int size = 0;
@@ -2285,7 +2285,7 @@ mono_arch_build_imt_thunk (MonoVTable *vtable, MonoDomain *domain, MonoIMTCheckI
                size += item->chunk_size;
        }
        if (fail_tramp)
-               code = mono_method_alloc_generic_virtual_thunk (domain, size * 4);
+               code = mono_method_alloc_generic_virtual_trampoline (domain, size * 4);
        else
                code = mono_domain_code_reserve (domain, size * 4);
        start = code;
@@ -2352,7 +2352,7 @@ mono_arch_build_imt_thunk (MonoVTable *vtable, MonoDomain *domain, MonoIMTCheckI
 
        mono_arch_flush_icache ((guint8*)start, (code - start) * 4);
 
-       mono_stats.imt_thunks_size += (code - start) * 4;
+       mono_stats.imt_trampolines_size += (code - start) * 4;
        g_assert (code - start <= size);
 
        mono_tramp_info_register (mono_tramp_info_create (NULL, start, code - start, NULL, NULL), domain);
index 8c1fe23297bffd8ba8b6ce8c9a6f43e62fff2b78..77775169fd7d0d5a615fdd69e4b2dd761566f948 100644 (file)
@@ -564,7 +564,7 @@ common_call_trampoline (mgreg_t *regs, guint8 *code, MonoMethod *m, MonoVTable *
                        vtable_slot = mini_resolve_imt_method (vt, vtable_slot, imt_method, &impl_method, &addr, &need_rgctx_tramp, &variant_iface, error);
                        return_val_if_nok (error, NULL);
 
-                       /* This is the vcall slot which gets called through the IMT thunk */
+                       /* This is the vcall slot which gets called through the IMT trampoline */
                        vtable_slot_to_patch = vtable_slot;
 
                        if (addr) {
index 288af652434bf9ffc25e4ad0893d5087409de286..bcd050b24f64ce11327d9d3d368dece51e36a3ce 100644 (file)
@@ -5613,7 +5613,7 @@ imt_branch_distance (MonoIMTCheckItem **imt_entries, int start, int target)
  * LOCKING: called with the domain lock held
  */
 gpointer
-mono_arch_build_imt_thunk (MonoVTable *vtable, MonoDomain *domain, MonoIMTCheckItem **imt_entries, int count,
+mono_arch_build_imt_trampoline (MonoVTable *vtable, MonoDomain *domain, MonoIMTCheckItem **imt_entries, int count,
        gpointer fail_tramp)
 {
        int i;
@@ -5645,7 +5645,7 @@ mono_arch_build_imt_thunk (MonoVTable *vtable, MonoDomain *domain, MonoIMTCheckI
                size += item->chunk_size;
        }
        if (fail_tramp)
-               code = mono_method_alloc_generic_virtual_thunk (domain, size);
+               code = mono_method_alloc_generic_virtual_trampoline (domain, size);
        else
                code = mono_domain_code_reserve (domain, size);
        start = code;
@@ -5715,7 +5715,7 @@ mono_arch_build_imt_thunk (MonoVTable *vtable, MonoDomain *domain, MonoIMTCheckI
        }
 
        if (!fail_tramp)
-               mono_stats.imt_thunks_size += code - start;
+               mono_stats.imt_trampolines_size += code - start;
        g_assert (code - start <= size);
 
 #if DEBUG_IMT
@@ -5730,7 +5730,7 @@ mono_arch_build_imt_thunk (MonoVTable *vtable, MonoDomain *domain, MonoIMTCheckI
                if (vtable)
                        buff = g_strdup_printf ("imt_%s_%s_entries_%d", vtable->klass->name_space, vtable->klass->name, count);
                else
-                       buff = g_strdup_printf ("imt_thunk_entries_%d", count);
+                       buff = g_strdup_printf ("imt_trampoline_entries_%d", count);
                mono_emit_jit_tramp (start, code - start, buff);
                g_free (buff);
        }
index b70d836c2aa07fd9758bf632c62cb5cd404582a1..be98276e63f2ae26e8fe3f70dd2816901932562c 100644 (file)
@@ -207,7 +207,7 @@ typedef struct {
 #define MONO_ARCH_VTABLE_REG X86_EDX
 #define MONO_ARCH_RGCTX_REG MONO_ARCH_IMT_REG
 #define MONO_ARCH_EXC_REG X86_EAX
-#define MONO_ARCH_HAVE_GENERALIZED_IMT_THUNK 1
+#define MONO_ARCH_HAVE_GENERALIZED_IMT_TRAMPOLINE 1
 #define MONO_ARCH_HAVE_LIVERANGE_OPS 1
 #define MONO_ARCH_HAVE_SIGCTX_TO_MONOCTX 1
 #define MONO_ARCH_HAVE_FULL_AOT_TRAMPOLINES 1
index 750410441af8afda4ad292c84405f3e195b47c24..0dd4af7a71ede59872342fd943775750d3a50d52 100644 (file)
@@ -3136,8 +3136,8 @@ init_backend (MonoBackend *backend)
 #ifdef MONO_ARCH_HAVE_OBJC_GET_SELECTOR
        backend->have_objc_get_selector = 1;
 #endif
-#ifdef MONO_ARCH_HAVE_GENERALIZED_IMT_THUNK
-       backend->have_generalized_imt_thunk = 1;
+#ifdef MONO_ARCH_HAVE_GENERALIZED_IMT_TRAMPOLINE
+       backend->have_generalized_imt_trampoline = 1;
 #endif
 #ifdef MONO_ARCH_GSHARED_SUPPORTED
        backend->gshared_supported = 1;
index 845162f76f7349228657010d253c8dbfbae09b4f..d3a550946013f217c8c53ccb20b118d2d844badf 100644 (file)
@@ -179,7 +179,7 @@ enum {
 typedef enum {
        MONO_AOT_TRAMP_SPECIFIC = 0,
        MONO_AOT_TRAMP_STATIC_RGCTX = 1,
-       MONO_AOT_TRAMP_IMT_THUNK = 2,
+       MONO_AOT_TRAMP_IMT = 2,
        MONO_AOT_TRAMP_GSHAREDVT_ARG = 3,
        MONO_AOT_TRAMP_NUM = 4
 } MonoAotTrampoline;
@@ -254,7 +254,7 @@ typedef struct MonoAotFileInfo
        /* Blocks of various kinds of trampolines */
        gpointer specific_trampolines;
        gpointer static_rgctx_trampolines;
-       gpointer imt_thunks;
+       gpointer imt_trampolines;
        gpointer gsharedvt_arg_trampolines;
        /* In static mode, points to a table of global symbols for trampolines etc */
        gpointer globals;
@@ -1484,7 +1484,7 @@ typedef struct {
        guint            emulate_div : 1;
        guint            emulate_long_shift_opts : 1;
        guint            have_objc_get_selector : 1;
-       guint            have_generalized_imt_thunk : 1;
+       guint            have_generalized_imt_trampoline : 1;
        guint            have_tls_get : 1;
        guint            have_tls_get_reg : 1;
        guint            have_liverange_ops: 1;
@@ -2501,7 +2501,7 @@ gpointer mono_aot_get_trampoline_full       (const char *name, MonoTrampInfo **o
 gpointer mono_aot_get_unbox_trampoline      (MonoMethod *method);
 gpointer mono_aot_get_lazy_fetch_trampoline (guint32 slot);
 gpointer mono_aot_get_static_rgctx_trampoline (gpointer ctx, gpointer addr);
-gpointer mono_aot_get_imt_thunk             (MonoVTable *vtable, MonoDomain *domain, MonoIMTCheckItem **imt_entries, int count, gpointer fail_tramp);
+gpointer mono_aot_get_imt_trampoline        (MonoVTable *vtable, MonoDomain *domain, MonoIMTCheckItem **imt_entries, int count, gpointer fail_tramp);
 gpointer mono_aot_get_gsharedvt_arg_trampoline(gpointer arg, gpointer addr);
 guint8*  mono_aot_get_unwind_info           (MonoJitInfo *ji, guint32 *unwind_info_len);
 guint32  mono_aot_method_hash               (MonoMethod *method);
@@ -2790,7 +2790,7 @@ gpointer mono_arch_get_delegate_virtual_invoke_impl (MonoMethodSignature *sig, M
 gpointer mono_arch_create_specific_trampoline   (gpointer arg1, MonoTrampolineType tramp_type, MonoDomain *domain, guint32 *code_len);
 MonoMethod* mono_arch_find_imt_method           (mgreg_t *regs, guint8 *code);
 MonoVTable* mono_arch_find_static_call_vtable   (mgreg_t *regs, guint8 *code);
-gpointer    mono_arch_build_imt_thunk           (MonoVTable *vtable, MonoDomain *domain, MonoIMTCheckItem **imt_entries, int count, gpointer fail_tramp);
+gpointer    mono_arch_build_imt_trampoline      (MonoVTable *vtable, MonoDomain *domain, MonoIMTCheckItem **imt_entries, int count, gpointer fail_tramp);
 void    mono_arch_notify_pending_exc            (MonoThreadInfo *info);
 guint8* mono_arch_get_call_target               (guint8 *code);
 guint32 mono_arch_get_plt_info_offset           (guint8 *plt_entry, mgreg_t *regs, guint8 *code);
index b213528caaa35b55a02a43f0c8b2329a40eeab75..338150494dd0315582003170457d0172b9294b31 100644 (file)
@@ -633,7 +633,7 @@ add_class (intptr_t klass, const char *name)
        /* we resolved an unknown class (unless we had the code unloaded) */
        if (cd) {
                /*printf ("resolved unknown: %s\n", name);*/
-               free (cd->name);
+               g_free (cd->name);
                cd->name = pstrdup (name);
                return cd;
        }
@@ -699,7 +699,7 @@ add_method (intptr_t method, const char *name, intptr_t code, int len)
                cd->code = code;
                cd->len = len;
                /*printf ("resolved unknown: %s\n", name);*/
-               free (cd->name);
+               g_free (cd->name);
                cd->name = pstrdup (name);
                return cd;
        }
@@ -1099,7 +1099,7 @@ add_heap_class_rev (HeapClassDesc *from, HeapClassDesc *to)
                                add_rev_class_hashed (n, to->rev_hash_size, to->rev_hash [i].klass, to->rev_hash [i].count);
                }
                if (to->rev_hash)
-                       free (to->rev_hash);
+                       g_free (to->rev_hash);
                to->rev_hash = n;
        }
        to->rev_count += add_rev_class_hashed (to->rev_hash, to->rev_hash_size, from, 1);
@@ -1217,7 +1217,7 @@ add_heap_shot_class (HeapShot *hs, ClassDesc *klass, uint64_t size)
                                add_heap_hashed (n, &res, hs->hash_size, hs->class_hash [i]->klass, hs->class_hash [i]->total_size, hs->class_hash [i]->count);
                }
                if (hs->class_hash)
-                       free (hs->class_hash);
+                       g_free (hs->class_hash);
                hs->class_hash = n;
        }
        res = NULL;
@@ -1269,7 +1269,7 @@ heap_shot_obj_add_refs (HeapShot *hs, uintptr_t objaddr, uintptr_t num, uintptr_
                HeapObjectDesc* ho = alloc_heap_obj (objaddr, hash [i]->hklass, hash [i]->num_refs + num);
                *ref_offset = hash [i]->num_refs;
                memcpy (ho->refs, hash [i]->refs, hash [i]->num_refs * sizeof (uintptr_t));
-               free (hash [i]);
+               g_free (hash [i]);
                hash [i] = ho;
                return ho;
        }
@@ -1319,7 +1319,7 @@ add_heap_shot_obj (HeapShot *hs, HeapObjectDesc *obj)
                                add_heap_hashed_obj (n, hs->objects_hash_size, hs->objects_hash [i]);
                }
                if (hs->objects_hash)
-                       free (hs->objects_hash);
+                       g_free (hs->objects_hash);
                hs->objects_hash = n;
        }
        hs->objects_count += add_heap_hashed_obj (hs->objects_hash, hs->objects_hash_size, obj);
@@ -1413,7 +1413,7 @@ heap_shot_mark_objects (HeapShot *hs)
                }
        }
        fprintf (outfile, "Total unmarked: %zd/%zd\n", num_unmarked, hs->objects_count);
-       free (marks);
+       g_free (marks);
 }
 
 static void
@@ -1423,10 +1423,10 @@ heap_shot_free_objects (HeapShot *hs)
        for (i = 0; i < hs->objects_hash_size; ++i) {
                HeapObjectDesc *ho = hs->objects_hash [i];
                if (ho)
-                       free (ho);
+                       g_free (ho);
        }
        if (hs->objects_hash)
-               free (hs->objects_hash);
+               g_free (hs->objects_hash);
        hs->objects_hash = NULL;
        hs->objects_hash_size = 0;
        hs->objects_count = 0;
@@ -1726,7 +1726,7 @@ add_trace_bt (BackTrace *bt, TraceDesc *trace, uint64_t value)
                                add_trace_hashed (n, trace->size, trace->traces [i].bt, trace->traces [i].count);
                }
                if (trace->traces)
-                       free (trace->traces);
+                       g_free (trace->traces);
                trace->traces = n;
        }
        trace->count += add_trace_hashed (trace->traces, trace->size, bt, value);
@@ -2371,7 +2371,7 @@ decode_buffer (ProfContext *ctx)
                                if (debug)
                                        fprintf (outfile, "handle (%s) %u created for object %p\n", get_handle_name (htype), handle, (void*)OBJ_ADDR (objdiff));
                                if (frames != sframes)
-                                       free (frames);
+                                       g_free (frames);
                        } else if (subtype == TYPE_GC_HANDLE_DESTROYED || subtype == TYPE_GC_HANDLE_DESTROYED_BT) {
                                int has_bt = subtype == TYPE_GC_HANDLE_DESTROYED_BT;
                                int num_bt = 0;
@@ -2402,7 +2402,7 @@ decode_buffer (ProfContext *ctx)
                                if (debug)
                                        fprintf (outfile, "handle (%s) %u destroyed\n", get_handle_name (htype), handle);
                                if (frames != sframes)
-                                       free (frames);
+                                       g_free (frames);
                        } else if (subtype == TYPE_GC_FINALIZE_START) {
                                // TODO: Generate a finalizer report based on these events.
                                if (debug)
@@ -2543,7 +2543,7 @@ decode_buffer (ProfContext *ctx)
                                        tracked_creation (OBJ_ADDR (objdiff), cd, len, bt, time_base);
                        }
                        if (frames != sframes)
-                               free (frames);
+                               g_free (frames);
                        break;
                }
                case TYPE_METHOD: {
@@ -2666,9 +2666,9 @@ decode_buffer (ProfContext *ctx)
                                                hs->roots_extra = thread->roots_extra;
                                                hs->roots_types = thread->roots_types;
                                        } else {
-                                               free (thread->roots);
-                                               free (thread->roots_extra);
-                                               free (thread->roots_types);
+                                               g_free (thread->roots);
+                                               g_free (thread->roots_extra);
+                                               g_free (thread->roots_types);
                                        }
                                        thread->num_roots = 0;
                                        thread->size_roots = 0;
@@ -2753,7 +2753,7 @@ decode_buffer (ProfContext *ctx)
                        if (debug)
                                fprintf (outfile, "monitor %s for object %p\n", monitor_ev_name (event), (void*)OBJ_ADDR (objdiff));
                        if (frames != sframes)
-                               free (frames);
+                               g_free (frames);
                        break;
                }
                case TYPE_EXCEPTION: {
@@ -2799,7 +2799,7 @@ decode_buffer (ProfContext *ctx)
                                                add_trace_thread (thread, &exc_traces, 1);
                                }
                                if (frames != sframes)
-                                       free (frames);
+                                       g_free (frames);
                                if (debug)
                                        fprintf (outfile, "throw %p\n", (void*)OBJ_ADDR (objdiff));
                        }
@@ -3698,9 +3698,9 @@ heap_shot_summary (HeapShot *hs, int hs_num, HeapShot *last_hs)
                if (cd->root_references)
                        fprintf (outfile, "\t\t%zd root references (%zd pinning)\n", cd->root_references, cd->pinned_references);
                dump_rev_claases (rev_sorted, cd->rev_count);
-               free (rev_sorted);
+               g_free (rev_sorted);
        }
-       free (sorted);
+       g_free (sorted);
 }
 
 static int
@@ -4216,7 +4216,7 @@ main (int argc, char *argv[])
                        *top++ = 0;
                        from_secs = atof (val);
                        to_secs = atof (top);
-                       free (val);
+                       g_free (val);
                        if (from_secs > to_secs) {
                                usage ();
                                return 1;
index 3f071a108798834e9b64cbc978a537336940bb8b..78de58aaa08de08e66e16439a294f494979335c5 100644 (file)
@@ -109,7 +109,7 @@ method_jit_result (MonoProfiler *prof, MonoMethod *method, MonoJitInfo* jinfo, i
                                sourceLoc = mono_debug_lookup_source_location (method, dmji->line_numbers[i].native_offset, mono_domain_get());
                                if (sourceLoc == NULL)
                                {
-                                       free(vtuneMethod.line_number_table);
+                                       g_free (vtuneMethod.line_number_table);
                                        vtuneMethod.line_number_table = NULL;
                                        vtuneMethod.line_number_size = 0;
                                        break;
@@ -126,9 +126,9 @@ method_jit_result (MonoProfiler *prof, MonoMethod *method, MonoJitInfo* jinfo, i
                iJIT_NotifyEvent(iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED, &vtuneMethod);
 
                if (vtuneMethod.source_file_name != NULL)
-                       free(vtuneMethod.source_file_name);
+                       g_free (vtuneMethod.source_file_name);
                if (vtuneMethod.line_number_table != NULL)
-                       free(vtuneMethod.line_number_table);
+                       g_free (vtuneMethod.line_number_table);
        
                g_free (signature);
                g_free (name);
index 40e4187280464b96aac6aa5ea5d1f8539689ea02..17f43836afdee6caccfd37e4889a97851a61b939 100644 (file)
@@ -1939,7 +1939,7 @@ class_loaded (MonoProfiler *prof, MonoClass *klass, int result)
        if (runtime_inited)
                mono_free (name);
        else
-               free (name);
+               g_free (name);
 
        send_if_needed (prof);
 
@@ -1983,7 +1983,7 @@ class_unloaded (MonoProfiler *prof, MonoClass *klass)
        if (runtime_inited)
                mono_free (name);
        else
-               free (name);
+               g_free (name);
 
        send_if_needed (prof);
 
@@ -2562,7 +2562,7 @@ add_code_pointer (uintptr_t ip)
                                add_code_page (n, size_code_pages, code_pages [i]);
                }
                if (code_pages)
-                       free (code_pages);
+                       g_free (code_pages);
                code_pages = n;
        }
        num_code_pages += add_code_page (code_pages, size_code_pages, ip & CPAGE_MASK);
@@ -2742,7 +2742,7 @@ elf_dl_callback (struct dl_phdr_info *info, size_t size, void *data)
                        filename = buf;
                }
        }
-       obj = calloc (sizeof (BinaryObject), 1);
+       obj = g_calloc (sizeof (BinaryObject), 1);
        obj->addr = (void*)info->dlpi_addr;
        obj->name = pstrdup (filename);
        obj->next = prof->binary_objects;
@@ -2816,7 +2816,7 @@ symbol_for (uintptr_t code)
                names = backtrace_symbols (&ip, 1);
                if (names) {
                        const char* p = names [0];
-                       free (names);
+                       g_free (names);
                        return p;
                }
                */
@@ -3143,13 +3143,13 @@ setup_perf_event (void)
        int i, count = 0;
        mmap_mask = num_pages * getpagesize () - 1;
        num_perf = mono_cpu_count ();
-       perf_data = calloc (num_perf, sizeof (PerfData));
+       perf_data = g_calloc (num_perf, sizeof (PerfData));
        for (i = 0; i < num_perf; ++i) {
                count += setup_perf_event_for_cpu (perf_data + i, i);
        }
        if (count)
                return 1;
-       free (perf_data);
+       g_free (perf_data);
        perf_data = NULL;
        return 0;
 }
@@ -3187,7 +3187,7 @@ counters_add_agent (MonoCounter *counter)
                if (agent->counter == counter) {
                        agent->value_size = 0;
                        if (agent->value) {
-                               free (agent->value);
+                               g_free (agent->value);
                                agent->value = NULL;
                        }
                        mono_os_mutex_unlock (&counters_mutex);
@@ -3316,7 +3316,7 @@ counters_sample (MonoProfiler *profiler, uint64_t timestamp)
        counters_emit (profiler);
 
        buffer_size = 8;
-       buffer = calloc (1, buffer_size);
+       buffer = g_calloc (1, buffer_size);
 
        mono_os_mutex_lock (&counters_mutex);
 
@@ -3352,7 +3352,7 @@ counters_sample (MonoProfiler *profiler, uint64_t timestamp)
                        continue; // FIXME error
                } else if (size > buffer_size) {
                        buffer_size = size;
-                       buffer = realloc (buffer, buffer_size);
+                       buffer = g_realloc (buffer, buffer_size);
                }
 
                memset (buffer, 0, buffer_size);
@@ -3363,7 +3363,7 @@ counters_sample (MonoProfiler *profiler, uint64_t timestamp)
                type = mono_counter_get_type (counter);
 
                if (!agent->value) {
-                       agent->value = calloc (1, size);
+                       agent->value = g_calloc (1, size);
                        agent->value_size = size;
                } else {
                        if (type == MONO_COUNTER_STRING) {
@@ -3413,14 +3413,14 @@ counters_sample (MonoProfiler *profiler, uint64_t timestamp)
                }
 
                if (type == MONO_COUNTER_STRING && size > agent->value_size) {
-                       agent->value = realloc (agent->value, size);
+                       agent->value = g_realloc (agent->value, size);
                        agent->value_size = size;
                }
 
                if (size > 0)
                        memcpy (agent->value, buffer, size);
        }
-       free (buffer);
+       g_free (buffer);
 
        emit_value (logbuffer, 0);
 
@@ -4350,8 +4350,8 @@ log_shutdown (MonoProfiler *prof)
 
        PROF_TLS_FREE ();
 
-       free (prof->args);
-       free (prof);
+       g_free (prof->args);
+       g_free (prof);
 }
 
 static char*
@@ -4660,7 +4660,7 @@ handle_writer_queue_entry (MonoProfiler *prof)
                        mono_free (name);
 
                free_info:
-                       free (info);
+                       g_free (info);
                }
 
                g_ptr_array_free (entry->methods, TRUE);
@@ -4889,7 +4889,7 @@ create_profiler (const char *args, const char *filename, GPtrArray *filters)
                        int s = strlen (nf) + 32;
                        char *p = (char *)malloc (s);
                        snprintf (p, s, "|mprof-report '--out=%s' -", nf);
-                       free (nf);
+                       g_free (nf);
                        nf = p;
                }
        }
@@ -4913,7 +4913,7 @@ create_profiler (const char *args, const char *filename, GPtrArray *filters)
                prof->gzfile = gzdopen (fileno (prof->file), "wb");
 #endif
 #if USE_PERF_EVENTS
-       if (sample_type && !do_mono_sample)
+       if (sample_type && sample_freq && !do_mono_sample)
                need_helper_thread = setup_perf_event ();
        if (!perf_data) {
                /* FIXME: warn if different freq or sample type */
@@ -4935,7 +4935,7 @@ create_profiler (const char *args, const char *filename, GPtrArray *filters)
 
        // FIXME: We should free this stuff too.
        mono_lock_free_allocator_init_size_class (&prof->sample_size_class, SAMPLE_SLOT_SIZE (num_frames), SAMPLE_BLOCK_SIZE);
-       mono_lock_free_allocator_init_allocator (&prof->sample_allocator, &prof->sample_size_class);
+       mono_lock_free_allocator_init_allocator (&prof->sample_allocator, &prof->sample_size_class, MONO_MEM_ACCOUNT_PROFILER);
 
        mono_lock_free_queue_init (&prof->sample_reuse_queue);
 
@@ -4952,7 +4952,7 @@ create_profiler (const char *args, const char *filename, GPtrArray *filters)
 
        // FIXME: We should free this stuff too.
        mono_lock_free_allocator_init_size_class (&prof->writer_entry_size_class, sizeof (WriterQueueEntry), WRITER_ENTRY_BLOCK_SIZE);
-       mono_lock_free_allocator_init_allocator (&prof->writer_entry_allocator, &prof->writer_entry_size_class);
+       mono_lock_free_allocator_init_allocator (&prof->writer_entry_allocator, &prof->writer_entry_size_class, MONO_MEM_ACCOUNT_PROFILER);
 
        mono_lock_free_queue_init (&prof->writer_queue);
        mono_os_sem_init (&prof->writer_queue_sem, 0);
@@ -5074,7 +5074,7 @@ set_sample_mode (char* val, int allow_empty)
        if (strcmp (val, "mono") == 0) {
                do_mono_sample = 1;
                sample_type = SAMPLE_CYCLES;
-               free (val);
+               g_free (val);
                return;
        }
        for (smode = sample_modes; smode->name; smode++) {
@@ -5097,7 +5097,7 @@ set_sample_mode (char* val, int allow_empty)
        } else {
                sample_freq = 100;
        }
-       free (val);
+       g_free (val);
 }
 
 static void
@@ -5109,7 +5109,7 @@ set_hsmode (char* val, int allow_empty)
                return;
        if (strcmp (val, "ondemand") == 0) {
                hs_mode_ondemand = 1;
-               free (val);
+               g_free (val);
                return;
        }
        count = strtoul (val, &end, 10);
@@ -5121,7 +5121,7 @@ set_hsmode (char* val, int allow_empty)
                hs_mode_gc = count;
        else
                usage (1);
-       free (val);
+       g_free (val);
 }
 
 /*
@@ -5206,7 +5206,7 @@ mono_profiler_startup (const char *desc)
                                fast_time = 2;
                        else
                                usage (1);
-                       free (val);
+                       g_free (val);
                        continue;
                }
                if ((opt = match_option (p, "report", NULL)) != p) {
@@ -5256,7 +5256,7 @@ mono_profiler_startup (const char *desc)
                if ((opt = match_option (p, "port", &val)) != p) {
                        char *end;
                        command_port = strtoul (val, &end, 10);
-                       free (val);
+                       g_free (val);
                        continue;
                }
                if ((opt = match_option (p, "maxframes", &val)) != p) {
@@ -5264,7 +5264,7 @@ mono_profiler_startup (const char *desc)
                        num_frames = strtoul (val, &end, 10);
                        if (num_frames > MAX_FRAMES)
                                num_frames = MAX_FRAMES;
-                       free (val);
+                       g_free (val);
                        notraces = num_frames == 0;
                        continue;
                }
@@ -5273,13 +5273,13 @@ mono_profiler_startup (const char *desc)
                        max_allocated_sample_hits = strtoul (val, &end, 10);
                        if (!max_allocated_sample_hits)
                                max_allocated_sample_hits = G_MAXINT32;
-                       free (val);
+                       g_free (val);
                        continue;
                }
                if ((opt = match_option (p, "calldepth", &val)) != p) {
                        char *end;
                        max_call_depth = strtoul (val, &end, 10);
-                       free (val);
+                       g_free (val);
                        continue;
                }
                if ((opt = match_option (p, "counters", NULL)) != p) {
@@ -5384,7 +5384,7 @@ mono_profiler_startup (const char *desc)
        if (do_coverage)
                mono_profiler_install_coverage_filter (coverage_filter);
 
-       if (do_mono_sample && sample_type == SAMPLE_CYCLES && !only_counters) {
+       if (do_mono_sample && sample_type == SAMPLE_CYCLES && sample_freq && !only_counters) {
                events |= MONO_PROFILE_STATISTICAL;
                mono_profiler_set_statistical_mode (sampling_mode, sample_freq);
                mono_profiler_install_statistical (mono_sample_hit);
index c3e14e4af89065ae8683cd821e6d155251eab515..cfa7589a6b2bd0edaf550bea60c8250e680bc536 100644 (file)
@@ -26,7 +26,7 @@
 #include <pthread.h>
 #include <sched.h>
 #endif
-
+#include <glib.h>
 
 #ifdef HAVE_SYS_TIME_H
 #include <sys/time.h>
@@ -61,7 +61,7 @@ typedef struct {
 
 #ifdef HOST_WIN32
 static int tls_data;
-#define DECL_TLS_DATA TlsData *tls; tls = (TlsData *) TlsGetValue (tls_data); if (tls == NULL) { tls = (TlsData *) calloc (sizeof (TlsData), 1); TlsSetValue (tls_data, tls); }
+#define DECL_TLS_DATA TlsData *tls; tls = (TlsData *) TlsGetValue (tls_data); if (tls == NULL) { tls = (TlsData *) g_calloc (sizeof (TlsData), 1); TlsSetValue (tls_data, tls); }
 #define TLS_INIT(x) x = TlsAlloc()
 #elif HAVE_KW_THREAD
 static __thread TlsData tls_data;
@@ -69,7 +69,7 @@ static __thread TlsData tls_data;
 #define TLS_INIT(x)
 #else
 static pthread_key_t tls_data;
-#define DECL_TLS_DATA TlsData *tls; tls = (TlsData *) pthread_getspecific (tls_data); if (tls == NULL) { tls = (TlsData *) calloc (sizeof (TlsData), 1); pthread_setspecific (tls_data, tls); }
+#define DECL_TLS_DATA TlsData *tls; tls = (TlsData *) pthread_getspecific (tls_data); if (tls == NULL) { tls = (TlsData *) g_calloc (sizeof (TlsData), 1); pthread_setspecific (tls_data, tls); }
 #define TLS_INIT(x) pthread_key_create(&x, NULL)
 #endif
 
index 50369b0a783f22a7314279f70f0416c6a3ab84aa..af9fd1e33d525a20df807957f744911e64deb73a 100644 (file)
@@ -573,10 +573,10 @@ sgen_card_tables_collect_stats (gboolean begin)
 void
 sgen_card_table_init (SgenRememberedSet *remset)
 {
-       sgen_cardtable = (guint8 *)sgen_alloc_os_memory (CARD_COUNT_IN_BYTES, (SgenAllocFlags)(SGEN_ALLOC_INTERNAL | SGEN_ALLOC_ACTIVATE), "card table");
+       sgen_cardtable = (guint8 *)sgen_alloc_os_memory (CARD_COUNT_IN_BYTES, (SgenAllocFlags)(SGEN_ALLOC_INTERNAL | SGEN_ALLOC_ACTIVATE), "card table", MONO_MEM_ACCOUNT_SGEN_CARD_TABLE);
 
 #ifdef SGEN_HAVE_OVERLAPPING_CARDS
-       sgen_shadow_cardtable = (guint8 *)sgen_alloc_os_memory (CARD_COUNT_IN_BYTES, (SgenAllocFlags)(SGEN_ALLOC_INTERNAL | SGEN_ALLOC_ACTIVATE), "shadow card table");
+       sgen_shadow_cardtable = (guint8 *)sgen_alloc_os_memory (CARD_COUNT_IN_BYTES, (SgenAllocFlags)(SGEN_ALLOC_INTERNAL | SGEN_ALLOC_ACTIVATE), "shadow card table", MONO_MEM_ACCOUNT_SGEN_SHADOW_CARD_TABLE);
 #endif
 
 #ifdef HEAVY_STATISTICS
index f073dc740648154853db6016d8a4564f7f137fe0..04de0ac5876ea17087fb04e4cdf546437044444a 100644 (file)
@@ -216,7 +216,7 @@ is_major_or_los_object_marked (GCObject *obj)
 #undef HANDLE_PTR
 #define HANDLE_PTR(ptr,obj)    do {    \
        if (*(ptr) && !sgen_ptr_in_nursery ((char*)*(ptr)) && !is_major_or_los_object_marked ((GCObject*)*(ptr))) { \
-               if (!sgen_get_remset ()->find_address_with_cards (start, cards, (char*)(ptr))) { \
+               if (!cards || !sgen_get_remset ()->find_address_with_cards (start, cards, (char*)(ptr))) { \
                        GCVTable __vt = SGEN_LOAD_VTABLE (obj); \
                        SGEN_LOG (0, "major->major reference %p at offset %zd in object %p (%s.%s) not found in remsets.", *(ptr), (char*)(ptr) - (char*)(obj), (obj), sgen_client_vtable_get_namespace (__vt), sgen_client_vtable_get_name (__vt)); \
                        binary_protocol_missing_remset ((obj), __vt, (int) ((char*)(ptr) - (char*)(obj)), *(ptr), (gpointer)LOAD_VTABLE(*(ptr)), object_is_pinned (*(ptr))); \
@@ -243,8 +243,6 @@ check_mod_union_callback (GCObject *obj, size_t size, void *dummy)
        else
                cards = sgen_get_major_collector ()->get_cardtable_mod_union_for_reference (start);
 
-       SGEN_ASSERT (0, cards, "we must have mod union for marked major objects");
-
 #include "sgen-scan-object.h"
 }
 
@@ -253,7 +251,7 @@ sgen_check_mod_union_consistency (void)
 {
        missing_remsets = FALSE;
 
-       major_collector.iterate_objects (ITERATE_OBJECTS_ALL, (IterateObjectCallbackFunc)check_mod_union_callback, (void*)FALSE);
+       major_collector.iterate_objects (ITERATE_OBJECTS_SWEEP_ALL, (IterateObjectCallbackFunc)check_mod_union_callback, (void*)FALSE);
 
        sgen_los_iterate_objects ((IterateObjectCallbackFunc)check_mod_union_callback, (void*)TRUE);
 
@@ -326,7 +324,7 @@ static void
 setup_valid_nursery_objects (void)
 {
        if (!valid_nursery_objects)
-               valid_nursery_objects = (GCObject **)sgen_alloc_os_memory (DEFAULT_NURSERY_SIZE, (SgenAllocFlags)(SGEN_ALLOC_INTERNAL | SGEN_ALLOC_ACTIVATE), "debugging data");
+               valid_nursery_objects = (GCObject **)sgen_alloc_os_memory (DEFAULT_NURSERY_SIZE, (SgenAllocFlags)(SGEN_ALLOC_INTERNAL | SGEN_ALLOC_ACTIVATE), "debugging data", MONO_MEM_ACCOUNT_SGEN_DEBUGGING);
        valid_nursery_object_count = 0;
        sgen_scan_area_with_callback (nursery_section->data, nursery_section->end_data, setup_mono_sgen_scan_area_with_callback, NULL, FALSE, FALSE);
 }
@@ -445,7 +443,7 @@ verify_object_pointers_callback (GCObject *obj, size_t size, void *data)
 {
        char *start = (char*)obj;
        gboolean allow_missing_pinned = (gboolean) (size_t) data;
-       SgenDescriptor desc = sgen_obj_get_descriptor (obj);
+       SgenDescriptor desc = sgen_obj_get_descriptor_safe (obj);
 
 #include "sgen-scan-object.h"
 }
index 842144e56f4aed079bbed1dd86e77c6b57ee5920..ff078a716739439b233abc2afa39189035ed8c24 100644 (file)
@@ -1461,7 +1461,7 @@ enqueue_scan_from_roots_jobs (SgenGrayQueue *gc_thread_gray_queue, char *heap_st
  * Return whether any objects were late-pinned due to being out of memory.
  */
 static gboolean
-collect_nursery (const char *reason, gboolean is_overflow, SgenGrayQueue *unpin_queue, gboolean finish_up_concurrent_mark)
+collect_nursery (const char *reason, gboolean is_overflow, SgenGrayQueue *unpin_queue)
 {
        gboolean needs_major;
        size_t max_garbage_amount;
@@ -1529,11 +1529,6 @@ collect_nursery (const char *reason, gboolean is_overflow, SgenGrayQueue *unpin_
 
        gc_stats.minor_gc_count ++;
 
-       if (whole_heap_check_before_collection) {
-               sgen_clear_nursery_fragments ();
-               sgen_check_whole_heap (finish_up_concurrent_mark);
-       }
-
        sgen_process_fin_stage_entries ();
 
        /* pin from pinned handles */
@@ -1552,6 +1547,11 @@ collect_nursery (const char *reason, gboolean is_overflow, SgenGrayQueue *unpin_
        if (remset_consistency_checks)
                sgen_check_remset_consistency ();
 
+       if (whole_heap_check_before_collection) {
+               sgen_clear_nursery_fragments ();
+               sgen_check_whole_heap (FALSE);
+       }
+
        TV_GETTIME (atv);
        time_minor_pinning += TV_ELAPSED (btv, atv);
        SGEN_LOG (2, "Finding pinned pointers: %zd in %lld usecs", sgen_get_pinned_count (), (long long)TV_ELAPSED (btv, atv));
@@ -1697,7 +1697,7 @@ major_copy_or_mark_from_roots (SgenGrayQueue *gc_thread_gray_queue, size_t *old_
        sgen_clear_nursery_fragments ();
 
        if (whole_heap_check_before_collection)
-               sgen_check_whole_heap (mode == COPY_OR_MARK_FROM_ROOTS_FINISH_CONCURRENT);
+               sgen_check_whole_heap (TRUE);
 
        TV_GETTIME (btv);
        time_major_pre_collection_fragment_clear += TV_ELAPSED (atv, btv);
@@ -1786,13 +1786,6 @@ major_copy_or_mark_from_roots (SgenGrayQueue *gc_thread_gray_queue, size_t *old_
        if (old_next_pin_slot)
                *old_next_pin_slot = sgen_get_pinned_count ();
 
-       /*
-        * We don't actually pin when starting a concurrent collection, so the remset
-        * consistency check won't work.
-        */
-       if (remset_consistency_checks && mode != COPY_OR_MARK_FROM_ROOTS_START_CONCURRENT)
-               sgen_check_remset_consistency ();
-
        TV_GETTIME (btv);
        time_major_pinning += TV_ELAPSED (atv, btv);
        SGEN_LOG (2, "Finding pinned pointers: %zd in %lld usecs", sgen_get_pinned_count (), (long long)TV_ELAPSED (atv, btv));
@@ -1975,9 +1968,6 @@ major_finish_collection (SgenGrayQueue *gc_thread_gray_queue, const char *reason
        reset_heap_boundaries ();
        sgen_update_heap_boundaries ((mword)sgen_get_nursery_start (), (mword)sgen_get_nursery_end ());
 
-       if (whole_heap_check_before_collection)
-               sgen_check_whole_heap (FALSE);
-
        /* walk the pin_queue, build up the fragment list of free memory, unmark
         * pinned objects as we go, memzero() the empty fragments so they are ready for the
         * next allocations.
@@ -2257,7 +2247,7 @@ sgen_perform_collection (size_t requested_size, int generation_to_collect, const
                if (concurrent_collection_in_progress)
                        major_update_concurrent_collection ();
 
-               if (collect_nursery (reason, FALSE, NULL, FALSE) && !concurrent_collection_in_progress) {
+               if (collect_nursery (reason, FALSE, NULL) && !concurrent_collection_in_progress) {
                        overflow_generation_to_collect = GENERATION_OLD;
                        overflow_reason = "Minor overflow";
                }
@@ -2267,7 +2257,7 @@ sgen_perform_collection (size_t requested_size, int generation_to_collect, const
        } else {
                SGEN_ASSERT (0, generation_to_collect == GENERATION_OLD, "We should have handled nursery collections above");
                if (major_collector.is_concurrent && !wait_to_finish) {
-                       collect_nursery ("Concurrent start", FALSE, NULL, FALSE);
+                       collect_nursery ("Concurrent start", FALSE, NULL);
                        major_start_concurrent_collection (reason);
                        oldest_generation_collected = GENERATION_NURSERY;
                } else if (major_do_collection (reason, FALSE, wait_to_finish)) {
@@ -2285,7 +2275,7 @@ sgen_perform_collection (size_t requested_size, int generation_to_collect, const
                 */
 
                if (overflow_generation_to_collect == GENERATION_NURSERY)
-                       collect_nursery (overflow_reason, TRUE, NULL, FALSE);
+                       collect_nursery (overflow_reason, TRUE, NULL);
                else
                        major_do_collection (overflow_reason, TRUE, wait_to_finish);
 
@@ -3259,7 +3249,7 @@ sgen_check_whole_heap_stw (void)
 {
        sgen_stop_world (0);
        sgen_clear_nursery_fragments ();
-       sgen_check_whole_heap (FALSE);
+       sgen_check_whole_heap (TRUE);
        sgen_restart_world (0);
 }
 
index f67a15cd74aac377e7eded4aecf705bf60fcd789..aefb07f23c5b6a99b9f3510a43d90c353f7a829d 100644 (file)
@@ -599,7 +599,6 @@ typedef enum {
        ITERATE_OBJECTS_SWEEP = 1,
        ITERATE_OBJECTS_NON_PINNED = 2,
        ITERATE_OBJECTS_PINNED = 4,
-       ITERATE_OBJECTS_ALL = ITERATE_OBJECTS_NON_PINNED | ITERATE_OBJECTS_PINNED,
        ITERATE_OBJECTS_SWEEP_NON_PINNED = ITERATE_OBJECTS_SWEEP | ITERATE_OBJECTS_NON_PINNED,
        ITERATE_OBJECTS_SWEEP_PINNED = ITERATE_OBJECTS_SWEEP | ITERATE_OBJECTS_PINNED,
        ITERATE_OBJECTS_SWEEP_ALL = ITERATE_OBJECTS_SWEEP | ITERATE_OBJECTS_NON_PINNED | ITERATE_OBJECTS_PINNED
@@ -654,7 +653,7 @@ struct _SgenMajorCollector {
        void (*sweep) (void);
        gboolean (*have_swept) (void);
        void (*finish_sweeping) (void);
-       void (*free_swept_blocks) (size_t allowance);
+       void (*free_swept_blocks) (size_t section_reserve);
        void (*check_scan_starts) (void);
        void (*dump_heap) (FILE *heap_dump_file);
        gint64 (*get_used_size) (void);
index 12ace19a3e904e4782f5bdc8febd21709cb3e78d..ca30670b71ab4e712d39639fc1c7e6bd2e2ba307 100644 (file)
@@ -23,13 +23,13 @@ static const int allocator_sizes [] = {
           8,   16,   24,   32,   40,   48,   64,   80,
          96,  128,  160,  192,  224,  248,  296,  320,
         384,  448,  504,  528,  584,  680,  816, 1088,
-       1360, 2044, 2336, 2728, 3272, 4092, 5456, 8188 };
+       1360, 2046, 2336, 2728, 3272, 4094, 5456, 8190 };
 #else
 static const int allocator_sizes [] = {
           8,   16,   24,   32,   40,   48,   64,   80,
-         96,  128,  160,  192,  224,  248,  320,  328,
-        384,  448,  528,  584,  680,  816, 1016, 1088,
-       1360, 2040, 2336, 2728, 3272, 4088, 5456, 8184 };
+         96,  128,  160,  192,  224,  248,  296,  320,
+        384,  448,  504,  528,  584,  680,  816, 1088,
+       1360, 2044, 2336, 2728, 3272, 4092, 5456, 8188 };
 #endif
 
 #define NUM_ALLOCATORS (sizeof (allocator_sizes) / sizeof (int))
@@ -158,7 +158,7 @@ sgen_alloc_internal_dynamic (size_t size, int type, gboolean assert_on_failure)
        void *p;
 
        if (size > allocator_sizes [NUM_ALLOCATORS - 1]) {
-               p = sgen_alloc_os_memory (size, (SgenAllocFlags)(SGEN_ALLOC_INTERNAL | SGEN_ALLOC_ACTIVATE), NULL);
+               p = sgen_alloc_os_memory (size, (SgenAllocFlags)(SGEN_ALLOC_INTERNAL | SGEN_ALLOC_ACTIVATE), NULL, MONO_MEM_ACCOUNT_SGEN_INTERNAL);
                if (!p)
                        sgen_assert_memory_alloc (NULL, size, description_for_type (type));
        } else {
@@ -183,7 +183,7 @@ sgen_free_internal_dynamic (void *addr, size_t size, int type)
                return;
 
        if (size > allocator_sizes [NUM_ALLOCATORS - 1])
-               sgen_free_os_memory (addr, size, SGEN_ALLOC_INTERNAL);
+               sgen_free_os_memory (addr, size, SGEN_ALLOC_INTERNAL, MONO_MEM_ACCOUNT_SGEN_INTERNAL);
        else
                mono_lock_free_free (addr, block_size (size));
 }
@@ -260,7 +260,7 @@ sgen_init_internal_allocator (void)
        for (i = 0; i < NUM_ALLOCATORS; ++i) {
                allocator_block_sizes [i] = block_size (allocator_sizes [i]);
                mono_lock_free_allocator_init_size_class (&size_classes [i], allocator_sizes [i], allocator_block_sizes [i]);
-               mono_lock_free_allocator_init_allocator (&allocators [i], &size_classes [i]);
+               mono_lock_free_allocator_init_allocator (&allocators [i], &size_classes [i], MONO_MEM_ACCOUNT_SGEN_INTERNAL);
        }
 
        for (size = mono_pagesize (); size <= LOCK_FREE_ALLOC_SB_MAX_SIZE; size <<= 1) {
index c032d1946f41c18b3dcf1df001b2f1b976025253..454cb89fda70eb88ce31bd6277b148fb323acf64 100644 (file)
@@ -251,7 +251,7 @@ get_los_section_memory (size_t size)
        if (!sgen_memgov_try_alloc_space (LOS_SECTION_SIZE, SPACE_LOS))
                return NULL;
 
-       section = (LOSSection *)sgen_alloc_os_memory_aligned (LOS_SECTION_SIZE, LOS_SECTION_SIZE, (SgenAllocFlags)(SGEN_ALLOC_HEAP | SGEN_ALLOC_ACTIVATE), NULL);
+       section = (LOSSection *)sgen_alloc_os_memory_aligned (LOS_SECTION_SIZE, LOS_SECTION_SIZE, (SgenAllocFlags)(SGEN_ALLOC_HEAP | SGEN_ALLOC_ACTIVATE), NULL, MONO_MEM_ACCOUNT_SGEN_LOS);
 
        if (!section)
                return NULL;
@@ -323,13 +323,13 @@ sgen_los_free_object (LOSObject *obj)
        los_num_objects--;
 
 #ifdef USE_MALLOC
-       free (obj);
+       g_free (obj);
 #else
        if (size > LOS_SECTION_OBJECT_LIMIT) {
                int pagesize = mono_pagesize ();
                size += sizeof (LOSObject);
                size = SGEN_ALIGN_UP_TO (size, pagesize);
-               sgen_free_os_memory ((gpointer)SGEN_ALIGN_DOWN_TO ((mword)obj, pagesize), size, SGEN_ALLOC_HEAP);
+               sgen_free_os_memory ((gpointer)SGEN_ALIGN_DOWN_TO ((mword)obj, pagesize), size, SGEN_ALLOC_HEAP, MONO_MEM_ACCOUNT_SGEN_LOS);
                los_memory_usage_total -= size;
                sgen_memgov_release_space (size, SPACE_LOS);
        } else {
@@ -379,7 +379,7 @@ sgen_los_alloc_large_inner (GCVTable vtable, size_t size)
        sgen_ensure_free_space (size, GENERATION_OLD);
 
 #ifdef USE_MALLOC
-       obj = malloc (size + sizeof (LOSObject));
+       obj = g_malloc (size + sizeof (LOSObject));
        memset (obj, 0, size + sizeof (LOSObject));
 #else
        if (size > LOS_SECTION_OBJECT_LIMIT) {
@@ -387,7 +387,7 @@ sgen_los_alloc_large_inner (GCVTable vtable, size_t size)
                int pagesize = mono_pagesize ();
                size_t alloc_size = SGEN_ALIGN_UP_TO (obj_size, pagesize);
                if (sgen_memgov_try_alloc_space (alloc_size, SPACE_LOS)) {
-                       obj = (LOSObject *)sgen_alloc_os_memory (alloc_size, (SgenAllocFlags)(SGEN_ALLOC_HEAP | SGEN_ALLOC_ACTIVATE), NULL);
+                       obj = (LOSObject *)sgen_alloc_os_memory (alloc_size, (SgenAllocFlags)(SGEN_ALLOC_HEAP | SGEN_ALLOC_ACTIVATE), NULL, MONO_MEM_ACCOUNT_SGEN_LOS);
                        if (obj) {
                                los_memory_usage_total += alloc_size;
                                obj = randomize_los_object_start (obj, obj_size, alloc_size, pagesize);
@@ -479,7 +479,7 @@ sgen_los_sweep (void)
                                prev->next = next;
                        else
                                los_sections = next;
-                       sgen_free_os_memory (section, LOS_SECTION_SIZE, SGEN_ALLOC_HEAP);
+                       sgen_free_os_memory (section, LOS_SECTION_SIZE, SGEN_ALLOC_HEAP, MONO_MEM_ACCOUNT_SGEN_LOS);
                        sgen_memgov_release_space (LOS_SECTION_SIZE, SPACE_LOS);
                        section = next;
                        --los_num_sections;
index a215c44502c12b226359ff45fddafe511f569374..8ae553c23b3d90687ef6ac7720a4e0d68127b155 100644 (file)
@@ -240,12 +240,10 @@ static guint64 stat_major_blocks_alloced = 0;
 static guint64 stat_major_blocks_freed = 0;
 static guint64 stat_major_blocks_lazy_swept = 0;
 
-#if SIZEOF_VOID_P != 8
 static guint64 stat_major_blocks_freed_ideal = 0;
 static guint64 stat_major_blocks_freed_less_ideal = 0;
 static guint64 stat_major_blocks_freed_individual = 0;
 static guint64 stat_major_blocks_alloced_less_ideal = 0;
-#endif
 
 #ifdef SGEN_COUNT_NUMBER_OF_MAJOR_OBJECTS_MARKED
 static guint64 num_major_objects_marked = 0;
@@ -297,9 +295,9 @@ major_alloc_heap (mword nursery_size, mword nursery_align, int the_nursery_bits)
 {
        char *start;
        if (nursery_align)
-               start = (char *)sgen_alloc_os_memory_aligned (nursery_size, nursery_align, (SgenAllocFlags)(SGEN_ALLOC_HEAP | SGEN_ALLOC_ACTIVATE), "nursery");
+               start = (char *)sgen_alloc_os_memory_aligned (nursery_size, nursery_align, (SgenAllocFlags)(SGEN_ALLOC_HEAP | SGEN_ALLOC_ACTIVATE), "nursery", MONO_MEM_ACCOUNT_SGEN_NURSERY);
        else
-               start = (char *)sgen_alloc_os_memory (nursery_size, (SgenAllocFlags)(SGEN_ALLOC_HEAP | SGEN_ALLOC_ACTIVATE), "nursery");
+               start = (char *)sgen_alloc_os_memory (nursery_size, (SgenAllocFlags)(SGEN_ALLOC_HEAP | SGEN_ALLOC_ACTIVATE), "nursery", MONO_MEM_ACCOUNT_SGEN_NURSERY);
 
        return start;
 }
@@ -331,7 +329,7 @@ ms_get_empty_block (void)
                for (;;) {
                        p = (char *)sgen_alloc_os_memory_aligned (MS_BLOCK_SIZE * alloc_num, MS_BLOCK_SIZE,
                                (SgenAllocFlags)(SGEN_ALLOC_HEAP | SGEN_ALLOC_ACTIVATE),
-                               alloc_num == 1 ? "major heap section" : NULL);
+                               alloc_num == 1 ? "major heap section" : NULL, MONO_MEM_ACCOUNT_SGEN_MARKSWEEP);
                        if (p)
                                break;
                        alloc_num >>= 1;
@@ -872,6 +870,7 @@ major_iterate_objects (IterateObjectsFlags flags, IterateObjectCallbackFunc call
        gboolean pinned = flags & ITERATE_OBJECTS_PINNED;
        MSBlockInfo *block;
 
+       /* No actual sweeping will take place if we are in the middle of a major collection. */
        major_finish_sweep_checking ();
        FOREACH_BLOCK_NO_LOCK (block) {
                int count = MS_BLOCK_FREE / block->obj_size;
@@ -881,26 +880,13 @@ major_iterate_objects (IterateObjectsFlags flags, IterateObjectCallbackFunc call
                        continue;
                if (!block->pinned && !non_pinned)
                        continue;
-               if (sweep && lazy_sweep) {
+               if (sweep && lazy_sweep && !block_is_swept_or_marking (block)) {
                        sweep_block (block);
                        SGEN_ASSERT (6, block->state == BLOCK_STATE_SWEPT, "Block must be swept after sweeping");
                }
 
                for (i = 0; i < count; ++i) {
                        void **obj = (void**) MS_BLOCK_OBJ (block, i);
-                       /*
-                        * We've finished sweep checking, but if we're sweeping lazily and
-                        * the flags don't require us to sweep, the block might still need
-                        * sweeping.  In that case, we need to consult the mark bits to tell
-                        * us whether an object slot is live.
-                        */
-                       if (!block_is_swept_or_marking (block)) {
-                               int word, bit;
-                               SGEN_ASSERT (6, !sweep && block->state == BLOCK_STATE_NEED_SWEEPING, "Has sweeping not finished?");
-                               MS_CALC_MARK_BIT (word, bit, obj);
-                               if (!MS_MARK_BIT (block, word, bit))
-                                       continue;
-                       }
                        if (MS_OBJ_ALLOCED (obj, block))
                                callback ((GCObject*)obj, block->obj_size, data);
                }
@@ -1953,7 +1939,6 @@ major_finish_major_collection (ScannedObjectCounts *counts)
 #endif
 }
 
-#if SIZEOF_VOID_P != 8
 static int
 compare_pointers (const void *va, const void *vb) {
        char *a = *(char**)va, *b = *(char**)vb;
@@ -1963,17 +1948,13 @@ compare_pointers (const void *va, const void *vb) {
                return 1;
        return 0;
 }
-#endif
 
 /*
  * This is called with sweep completed and the world stopped.
  */
 static void
-major_free_swept_blocks (size_t allowance)
+major_free_swept_blocks (size_t section_reserve)
 {
-       /* FIXME: This is probably too much.  It's assuming all objects are small. */
-       size_t section_reserve = allowance / MS_BLOCK_SIZE;
-
        SGEN_ASSERT (0, sweep_state == SWEEP_STATE_SWEPT, "Sweeping must have finished before freeing blocks");
 
 #ifdef TARGET_WIN32
@@ -1984,7 +1965,6 @@ major_free_swept_blocks (size_t allowance)
                return;
 #endif
 
-#if SIZEOF_VOID_P != 8
        {
                int i, num_empty_blocks_orig, num_blocks, arr_length;
                void *block;
@@ -2057,7 +2037,7 @@ major_free_swept_blocks (size_t allowance)
                                         * we're iterating.
                                         */
                                        int j;
-                                       sgen_free_os_memory (empty_block_arr [first], MS_BLOCK_SIZE * num_blocks, SGEN_ALLOC_HEAP);
+                                       sgen_free_os_memory (empty_block_arr [first], MS_BLOCK_SIZE * num_blocks, SGEN_ALLOC_HEAP, MONO_MEM_ACCOUNT_SGEN_MARKSWEEP);
                                        for (j = first; j <= d; ++j)
                                                empty_block_arr [j] = NULL;
                                        dest = first;
@@ -2104,11 +2084,10 @@ major_free_swept_blocks (size_t allowance)
         */
        if (num_empty_blocks <= num_major_sections)
                return;
-#endif
 
        while (num_empty_blocks > section_reserve) {
                void *next = *(void**)empty_blocks;
-               sgen_free_os_memory (empty_blocks, MS_BLOCK_SIZE, SGEN_ALLOC_HEAP);
+               sgen_free_os_memory (empty_blocks, MS_BLOCK_SIZE, SGEN_ALLOC_HEAP, MONO_MEM_ACCOUNT_SGEN_MARKSWEEP);
                empty_blocks = next;
                /*
                 * Needs not be atomic because this is running
@@ -2117,9 +2096,7 @@ major_free_swept_blocks (size_t allowance)
                --num_empty_blocks;
 
                ++stat_major_blocks_freed;
-#if SIZEOF_VOID_P != 8
                ++stat_major_blocks_freed_individual;
-#endif
        }
 }
 
@@ -2608,12 +2585,10 @@ sgen_marksweep_init_internal (SgenMajorCollector *collector, gboolean is_concurr
        mono_counters_register ("# major blocks allocated", MONO_COUNTER_GC | MONO_COUNTER_ULONG, &stat_major_blocks_alloced);
        mono_counters_register ("# major blocks freed", MONO_COUNTER_GC | MONO_COUNTER_ULONG, &stat_major_blocks_freed);
        mono_counters_register ("# major blocks lazy swept", MONO_COUNTER_GC | MONO_COUNTER_ULONG, &stat_major_blocks_lazy_swept);
-#if SIZEOF_VOID_P != 8
        mono_counters_register ("# major blocks freed ideally", MONO_COUNTER_GC | MONO_COUNTER_ULONG, &stat_major_blocks_freed_ideal);
        mono_counters_register ("# major blocks freed less ideally", MONO_COUNTER_GC | MONO_COUNTER_ULONG, &stat_major_blocks_freed_less_ideal);
        mono_counters_register ("# major blocks freed individually", MONO_COUNTER_GC | MONO_COUNTER_ULONG, &stat_major_blocks_freed_individual);
        mono_counters_register ("# major blocks allocated less ideally", MONO_COUNTER_GC | MONO_COUNTER_ULONG, &stat_major_blocks_alloced_less_ideal);
-#endif
 
        collector->section_size = MAJOR_SECTION_SIZE;
 
index e7de362976055377c0a67e6da9e4874d0c3b2db5..dc69381547f60bfb192de3cbec934092f20022c3 100644 (file)
@@ -111,7 +111,7 @@ sgen_memgov_calculate_minor_collection_allowance (void)
 
        /* FIXME: Why is this here? */
        if (major_collector.free_swept_blocks)
-               major_collector.free_swept_blocks (allowance);
+               major_collector.free_swept_blocks (major_collector.get_num_major_sections () * SGEN_DEFAULT_ALLOWANCE_HEAP_SIZE_RATIO);
 
        major_collection_trigger_size = new_heap_size + allowance;
 
@@ -384,13 +384,13 @@ sgen_assert_memory_alloc (void *ptr, size_t requested_size, const char *assert_d
  * This must not require any lock.
  */
 void*
-sgen_alloc_os_memory (size_t size, SgenAllocFlags flags, const char *assert_description)
+sgen_alloc_os_memory (size_t size, SgenAllocFlags flags, const char *assert_description, MonoMemAccountType type)
 {
        void *ptr;
 
        g_assert (!(flags & ~(SGEN_ALLOC_HEAP | SGEN_ALLOC_ACTIVATE)));
 
-       ptr = mono_valloc (0, size, prot_flags_for_activate (flags & SGEN_ALLOC_ACTIVATE));
+       ptr = mono_valloc (0, size, prot_flags_for_activate (flags & SGEN_ALLOC_ACTIVATE), type);
        sgen_assert_memory_alloc (ptr, size, assert_description);
        if (ptr) {
                SGEN_ATOMIC_ADD_P (total_alloc, size);
@@ -400,14 +400,15 @@ sgen_alloc_os_memory (size_t size, SgenAllocFlags flags, const char *assert_desc
 }
 
 /* size must be a power of 2 */
+// FIXME: remove assert_description
 void*
-sgen_alloc_os_memory_aligned (size_t size, mword alignment, SgenAllocFlags flags, const char *assert_description)
+sgen_alloc_os_memory_aligned (size_t size, mword alignment, SgenAllocFlags flags, const char *assert_description, MonoMemAccountType type)
 {
        void *ptr;
 
        g_assert (!(flags & ~(SGEN_ALLOC_HEAP | SGEN_ALLOC_ACTIVATE)));
 
-       ptr = mono_valloc_aligned (size, alignment, prot_flags_for_activate (flags & SGEN_ALLOC_ACTIVATE));
+       ptr = mono_valloc_aligned (size, alignment, prot_flags_for_activate (flags & SGEN_ALLOC_ACTIVATE), type);
        sgen_assert_memory_alloc (ptr, size, assert_description);
        if (ptr) {
                SGEN_ATOMIC_ADD_P (total_alloc, size);
@@ -420,11 +421,11 @@ sgen_alloc_os_memory_aligned (size_t size, mword alignment, SgenAllocFlags flags
  * Free the memory returned by sgen_alloc_os_memory (), returning it to the OS.
  */
 void
-sgen_free_os_memory (void *addr, size_t size, SgenAllocFlags flags)
+sgen_free_os_memory (void *addr, size_t size, SgenAllocFlags flags, MonoMemAccountType type)
 {
        g_assert (!(flags & ~SGEN_ALLOC_HEAP));
 
-       mono_vfree (addr, size);
+       mono_vfree (addr, size, type);
        SGEN_ATOMIC_ADD_P (total_alloc, -(gssize)size);
        total_alloc_max = MAX (total_alloc_max, total_alloc);
 }
@@ -476,8 +477,8 @@ sgen_memgov_init (size_t max_heap, size_t soft_limit, gboolean debug_allowance,
        debug_print_allowance = debug_allowance;
        major_collection_trigger_size = MIN_MINOR_COLLECTION_ALLOWANCE;
 
-       mono_counters_register ("Memgov alloc", MONO_COUNTER_GC | MONO_COUNTER_WORD | MONO_COUNTER_BYTES | MONO_COUNTER_VARIABLE, &total_alloc);
-       mono_counters_register ("Memgov max alloc", MONO_COUNTER_GC | MONO_COUNTER_WORD | MONO_COUNTER_BYTES | MONO_COUNTER_MONOTONIC, &total_alloc_max);
+       mono_counters_register ("Memgov alloc", MONO_COUNTER_GC | MONO_COUNTER_WORD | MONO_COUNTER_BYTES | MONO_COUNTER_VARIABLE, (void*)&total_alloc);
+       mono_counters_register ("Memgov max alloc", MONO_COUNTER_GC | MONO_COUNTER_WORD | MONO_COUNTER_BYTES | MONO_COUNTER_MONOTONIC, (void*)&total_alloc_max);
 
        mono_coop_mutex_init (&log_entries_mutex);
 
index d669e4730d18a058c44a026e9ae7dd48446c71a5..585fbe9a8388af909098645da5304d8a7ff2e121 100644 (file)
@@ -54,9 +54,9 @@ typedef struct {
 } SgenLogEntry;
 
 /* OS memory allocation */
-void* sgen_alloc_os_memory (size_t size, SgenAllocFlags flags, const char *assert_description);
-void* sgen_alloc_os_memory_aligned (size_t size, mword alignment, SgenAllocFlags flags, const char *assert_description);
-void sgen_free_os_memory (void *addr, size_t size, SgenAllocFlags flags);
+void* sgen_alloc_os_memory (size_t size, SgenAllocFlags flags, const char *assert_description, MonoMemAccountType type);
+void* sgen_alloc_os_memory_aligned (size_t size, mword alignment, SgenAllocFlags flags, const char *assert_description, MonoMemAccountType type);
+void sgen_free_os_memory (void *addr, size_t size, SgenAllocFlags flags, MonoMemAccountType type);
 
 /* Error handling */
 void sgen_assert_memory_alloc (void *ptr, size_t requested_size, const char *assert_description);
index ce504201f62d7ce42f8c0f5d64df086f7ed9d786..8b9c432961fee581d76dc597dd08f7179617c72e 100644 (file)
@@ -231,7 +231,7 @@ binary_protocol_flush_buffer (BinaryProtocolBuffer *buffer)
 
        current_file_size += buffer->index;
 
-       sgen_free_os_memory (buffer, sizeof (BinaryProtocolBuffer), SGEN_ALLOC_INTERNAL);
+       sgen_free_os_memory (buffer, sizeof (BinaryProtocolBuffer), SGEN_ALLOC_INTERNAL, MONO_MEM_ACCOUNT_SGEN_BINARY_PROTOCOL);
 }
 
 static void
@@ -315,12 +315,12 @@ binary_protocol_get_buffer (int length)
        if (buffer && buffer->index + length <= BINARY_PROTOCOL_BUFFER_SIZE)
                return buffer;
 
-       new_buffer = (BinaryProtocolBuffer *)sgen_alloc_os_memory (sizeof (BinaryProtocolBuffer), (SgenAllocFlags)(SGEN_ALLOC_INTERNAL | SGEN_ALLOC_ACTIVATE), "debugging memory");
+       new_buffer = (BinaryProtocolBuffer *)sgen_alloc_os_memory (sizeof (BinaryProtocolBuffer), (SgenAllocFlags)(SGEN_ALLOC_INTERNAL | SGEN_ALLOC_ACTIVATE), "debugging memory", MONO_MEM_ACCOUNT_SGEN_BINARY_PROTOCOL);
        new_buffer->next = buffer;
        new_buffer->index = 0;
 
        if (InterlockedCompareExchangePointer ((void**)&binary_protocol_buffers, new_buffer, buffer) != buffer) {
-               sgen_free_os_memory (new_buffer, sizeof (BinaryProtocolBuffer), SGEN_ALLOC_INTERNAL);
+               sgen_free_os_memory (new_buffer, sizeof (BinaryProtocolBuffer), SGEN_ALLOC_INTERNAL, MONO_MEM_ACCOUNT_SGEN_BINARY_PROTOCOL);
                goto retry;
        }
 
index 6f5606bdb80919b7890bd9bed1da15997a77757d..43a690c75920671419df88b5d2dc80ba1f8c1ca0 100644 (file)
@@ -146,7 +146,7 @@ translate_backtrace (gpointer native_trace[], int size)
                        g_string_append_printf (bt, "\tat %s\n", names [i]);
        }
 
-       free (names);
+       g_free (names);
        return g_string_free (bt, FALSE);
 }
 
index cddcd1c63b037edc4192e7e2fb0c969372f350bc..cc00f5c8eba8b3d44318745c735ec03ce4abae32 100644 (file)
@@ -52,7 +52,7 @@ static volatile gint32 overflow_busy [HAZARD_TABLE_OVERFLOW];
 
 /* The table where we keep pointers to blocks to be freed but that
    have to wait because they're guarded by a hazard pointer. */
-static MonoLockFreeArrayQueue delayed_free_queue = MONO_LOCK_FREE_ARRAY_QUEUE_INIT (sizeof (DelayedFreeItem));
+static MonoLockFreeArrayQueue delayed_free_queue = MONO_LOCK_FREE_ARRAY_QUEUE_INIT (sizeof (DelayedFreeItem), MONO_MEM_ACCOUNT_HAZARD_POINTERS);
 
 /* The table for small ID assignment */
 static mono_mutex_t small_id_mutex;
@@ -112,7 +112,7 @@ mono_thread_small_id_alloc (void)
                if (hazard_table == NULL) {
                        hazard_table = (MonoThreadHazardPointers *volatile) mono_valloc (NULL,
                                sizeof (MonoThreadHazardPointers) * HAZARD_TABLE_MAX_SIZE,
-                               MONO_MMAP_NONE);
+                               MONO_MMAP_NONE, MONO_MEM_ACCOUNT_HAZARD_POINTERS);
                }
 
                g_assert (hazard_table != NULL);
index d5da3896343906457b70d185db3f4df793f9828e..08b4deff37c0379b92524ce00ee5788e717b57b0 100644 (file)
@@ -138,8 +138,8 @@ alloc_sb (Descriptor *desc)
                pagesize = mono_pagesize ();
 
        sb_header = desc->block_size == pagesize ?
-               mono_valloc (NULL, desc->block_size, prot_flags_for_activate (TRUE)) :
-               mono_valloc_aligned (desc->block_size, desc->block_size, prot_flags_for_activate (TRUE));
+               mono_valloc (NULL, desc->block_size, prot_flags_for_activate (TRUE), desc->heap->account_type) :
+               mono_valloc_aligned (desc->block_size, desc->block_size, prot_flags_for_activate (TRUE), desc->heap->account_type);
 
        g_assert (sb_header == sb_header_for_addr (sb_header, desc->block_size));
 
@@ -150,11 +150,11 @@ alloc_sb (Descriptor *desc)
 }
 
 static void
-free_sb (gpointer sb, size_t block_size)
+free_sb (gpointer sb, size_t block_size, MonoMemAccountType type)
 {
        gpointer sb_header = sb_header_for_addr (sb, block_size);
        g_assert ((char*)sb_header + LOCK_FREE_ALLOC_SB_HEADER_SIZE == sb);
-       mono_vfree (sb_header, block_size);
+       mono_vfree (sb_header, block_size, type);
        //g_print ("free sb %p\n", sb_header);
 }
 
@@ -162,7 +162,7 @@ free_sb (gpointer sb, size_t block_size)
 static Descriptor * volatile desc_avail;
 
 static Descriptor*
-desc_alloc (void)
+desc_alloc (MonoMemAccountType type)
 {
        MonoThreadHazardPointers *hp = mono_hazard_pointer_get ();
        Descriptor *desc;
@@ -179,7 +179,7 @@ desc_alloc (void)
                        Descriptor *d;
                        int i;
 
-                       desc = (Descriptor *) mono_valloc (NULL, desc_size * NUM_DESC_BATCH, prot_flags_for_activate (TRUE));
+                       desc = (Descriptor *) mono_valloc (NULL, desc_size * NUM_DESC_BATCH, prot_flags_for_activate (TRUE), type);
 
                        /* Organize into linked list. */
                        d = desc;
@@ -195,7 +195,7 @@ desc_alloc (void)
                        success = (InterlockedCompareExchangePointer ((gpointer * volatile)&desc_avail, desc->next, NULL) == NULL);
 
                        if (!success)
-                               mono_vfree (desc, desc_size * NUM_DESC_BATCH);
+                               mono_vfree (desc, desc_size * NUM_DESC_BATCH, type);
                }
 
                mono_hazard_pointer_clear (hp, 1);
@@ -232,27 +232,27 @@ desc_retire (Descriptor *desc)
        g_assert (desc->anchor.data.state == STATE_EMPTY);
        g_assert (desc->in_use);
        desc->in_use = FALSE;
-       free_sb (desc->sb, desc->block_size);
+       free_sb (desc->sb, desc->block_size, desc->heap->account_type);
        mono_thread_hazardous_try_free (desc, desc_enqueue_avail);
 }
 #else
 MonoLockFreeQueue available_descs;
 
 static Descriptor*
-desc_alloc (void)
+desc_alloc (MonoMemAccountType type)
 {
        Descriptor *desc = (Descriptor*)mono_lock_free_queue_dequeue (&available_descs);
 
        if (desc)
                return desc;
 
-       return calloc (1, sizeof (Descriptor));
+       return g_calloc (1, sizeof (Descriptor));
 }
 
 static void
 desc_retire (Descriptor *desc)
 {
-       free_sb (desc->sb, desc->block_size);
+       free_sb (desc->sb, desc->block_size, desc->heap->account_type);
        mono_lock_free_queue_enqueue (&available_descs, &desc->node);
 }
 #endif
@@ -390,7 +390,7 @@ static gpointer
 alloc_from_new_sb (MonoLockFreeAllocator *heap)
 {
        unsigned int slot_size, block_size, count, i;
-       Descriptor *desc = desc_alloc ();
+       Descriptor *desc = desc_alloc (heap->account_type);
 
        slot_size = desc->slot_size = heap->sc->slot_size;
        block_size = desc->block_size = heap->sc->block_size;
@@ -611,8 +611,9 @@ mono_lock_free_allocator_init_size_class (MonoLockFreeAllocSizeClass *sc, unsign
 }
 
 void
-mono_lock_free_allocator_init_allocator (MonoLockFreeAllocator *heap, MonoLockFreeAllocSizeClass *sc)
+mono_lock_free_allocator_init_allocator (MonoLockFreeAllocator *heap, MonoLockFreeAllocSizeClass *sc, MonoMemAccountType account_type)
 {
        heap->sc = sc;
        heap->active = NULL;
+       heap->account_type = account_type;
 }
index f0420b492ec1bc39ee043f826f85bd933996ea0f..70d550d95c239b6b6d5ce5d868f31633a590c7d1 100644 (file)
@@ -41,14 +41,15 @@ struct _MonoLockFreeAllocDescriptor;
 typedef struct {
        struct _MonoLockFreeAllocDescriptor *active;
        MonoLockFreeAllocSizeClass *sc;
+       MonoMemAccountType account_type;
 } MonoLockFreeAllocator;
 
 #define LOCK_FREE_ALLOC_SB_MAX_SIZE                                    16384
-#define LOCK_FREE_ALLOC_SB_HEADER_SIZE                         (sizeof (MonoLockFreeAllocator))
+#define LOCK_FREE_ALLOC_SB_HEADER_SIZE                         (sizeof (gpointer))
 #define LOCK_FREE_ALLOC_SB_USABLE_SIZE(block_size)     ((block_size) - LOCK_FREE_ALLOC_SB_HEADER_SIZE)
 
 MONO_API void mono_lock_free_allocator_init_size_class (MonoLockFreeAllocSizeClass *sc, unsigned int slot_size, unsigned int block_size);
-MONO_API void mono_lock_free_allocator_init_allocator (MonoLockFreeAllocator *heap, MonoLockFreeAllocSizeClass *sc);
+MONO_API void mono_lock_free_allocator_init_allocator (MonoLockFreeAllocator *heap, MonoLockFreeAllocSizeClass *sc, MonoMemAccountType account_type);
 
 MONO_API gpointer mono_lock_free_alloc (MonoLockFreeAllocator *heap);
 MONO_API void mono_lock_free_free (gpointer ptr, size_t block_size);
index b0d0a9a1dfe593ab67005f1cb52e960b0d89447b..5e48558a0d94c438b9afd9db4994ce8c538b7002 100644 (file)
@@ -45,16 +45,16 @@ alloc_chunk (MonoLockFreeArray *arr)
 {
        int size = mono_pagesize ();
        int num_entries = (size - (sizeof (Chunk) - arr->entry_size * MONO_ZERO_LEN_ARRAY)) / arr->entry_size;
-       Chunk *chunk = (Chunk *) mono_valloc (NULL, size, MONO_MMAP_READ | MONO_MMAP_WRITE);
+       Chunk *chunk = (Chunk *) mono_valloc (NULL, size, MONO_MMAP_READ | MONO_MMAP_WRITE, arr->account_type);
        g_assert (chunk);
        chunk->num_entries = num_entries;
        return chunk;
 }
 
 static void
-free_chunk (Chunk *chunk)
+free_chunk (Chunk *chunk, MonoMemAccountType type)
 {
-       mono_vfree (chunk, mono_pagesize ());
+       mono_vfree (chunk, mono_pagesize (), type);
 }
 
 gpointer
@@ -68,7 +68,7 @@ mono_lock_free_array_nth (MonoLockFreeArray *arr, int index)
                chunk = alloc_chunk (arr);
                mono_memory_write_barrier ();
                if (InterlockedCompareExchangePointer ((volatile gpointer *)&arr->chunk_list, chunk, NULL) != NULL)
-                       free_chunk (chunk);
+                       free_chunk (chunk, arr->account_type);
        }
 
        chunk = arr->chunk_list;
@@ -80,7 +80,7 @@ mono_lock_free_array_nth (MonoLockFreeArray *arr, int index)
                        next = alloc_chunk (arr);
                        mono_memory_write_barrier ();
                        if (InterlockedCompareExchangePointer ((volatile gpointer *) &chunk->next, next, NULL) != NULL) {
-                               free_chunk (next);
+                               free_chunk (next, arr->account_type);
                                next = chunk->next;
                                g_assert (next);
                        }
@@ -116,7 +116,7 @@ mono_lock_free_array_cleanup (MonoLockFreeArray *arr)
        arr->chunk_list = NULL;
        while (chunk) {
                Chunk *next = chunk->next;
-               free_chunk (chunk);
+               free_chunk (chunk, arr->account_type);
                chunk = next;
        }
 }
index fc924a7639ab011bf567d6f44db039d9648ee899..8e198e9227df62230c3e31cf092401d66c117c15 100644 (file)
 
 #include <glib.h>
 #include <mono/utils/mono-compiler.h>
+#include <mono/utils/mono-mmap.h>
 
 typedef struct _MonoLockFreeArrayChunk MonoLockFreeArrayChunk;
 
 typedef struct {
        size_t entry_size;
        MonoLockFreeArrayChunk *chunk_list;
+       MonoMemAccountType account_type;
 } MonoLockFreeArray;
 
 typedef struct {
@@ -23,8 +25,8 @@ typedef struct {
        gint32 num_used_entries;
 } MonoLockFreeArrayQueue;
 
-#define MONO_LOCK_FREE_ARRAY_INIT(entry_size)          { (entry_size), NULL }
-#define MONO_LOCK_FREE_ARRAY_QUEUE_INIT(entry_size)    { MONO_LOCK_FREE_ARRAY_INIT ((entry_size) + sizeof (gpointer)), 0 }
+#define MONO_LOCK_FREE_ARRAY_INIT(entry_size, account_type)            { (entry_size), NULL, (account_type) }
+#define MONO_LOCK_FREE_ARRAY_QUEUE_INIT(entry_size, account_type)      { MONO_LOCK_FREE_ARRAY_INIT ((entry_size) + sizeof (gpointer), (account_type)), 0 }
 
 gpointer mono_lock_free_array_nth (MonoLockFreeArray *arr, int index);
 
index 83c2bdcc690dcf1847789d4491897350cf6dea90..56948bdd901da23ae66edd34b6e7d19cf218c902 100644 (file)
@@ -115,9 +115,9 @@ codechunk_valloc (void *preferred, guint32 size)
                freelist = g_slist_delete_link (freelist, freelist);
                g_hash_table_insert (valloc_freelists, GUINT_TO_POINTER (size), freelist);
        } else {
-               ptr = mono_valloc (preferred, size, MONO_PROT_RWX | ARCH_MAP_FLAGS);
+               ptr = mono_valloc (preferred, size, MONO_PROT_RWX | ARCH_MAP_FLAGS, MONO_MEM_ACCOUNT_CODE);
                if (!ptr && preferred)
-                       ptr = mono_valloc (NULL, size, MONO_PROT_RWX | ARCH_MAP_FLAGS);
+                       ptr = mono_valloc (NULL, size, MONO_PROT_RWX | ARCH_MAP_FLAGS, MONO_MEM_ACCOUNT_CODE);
        }
        mono_os_mutex_unlock (&valloc_mutex);
        return ptr;
@@ -134,7 +134,7 @@ codechunk_vfree (void *ptr, guint32 size)
                freelist = g_slist_prepend (freelist, ptr);
                g_hash_table_insert (valloc_freelists, GUINT_TO_POINTER (size), freelist);
        } else {
-               mono_vfree (ptr, size);
+               mono_vfree (ptr, size, MONO_MEM_ACCOUNT_CODE);
        }
        mono_os_mutex_unlock (&valloc_mutex);
 }              
@@ -153,7 +153,7 @@ codechunk_cleanup (void)
                GSList *l;
 
                for (l = freelist; l; l = l->next) {
-                       mono_vfree (l->data, GPOINTER_TO_UINT (key));
+                       mono_vfree (l->data, GPOINTER_TO_UINT (key), MONO_MEM_ACCOUNT_CODE);
                }
                g_slist_free (freelist);
        }
@@ -234,7 +234,7 @@ free_chunklist (CodeChunk *chunk)
                        dlfree (dead->data);
                }
                code_memory_used -= dead->size;
-               free (dead);
+               g_free (dead);
        }
 }
 
@@ -249,7 +249,7 @@ mono_code_manager_destroy (MonoCodeManager *cman)
 {
        free_chunklist (cman->full);
        free_chunklist (cman->current);
-       free (cman);
+       g_free (cman);
 }
 
 /**
@@ -398,12 +398,12 @@ new_codechunk (CodeChunk *last, int dynamic, int size)
 #endif
        }
 
-       chunk = (CodeChunk *) malloc (sizeof (CodeChunk));
+       chunk = (CodeChunk *) g_malloc (sizeof (CodeChunk));
        if (!chunk) {
                if (flags == CODE_FLAG_MALLOC)
                        dlfree (ptr);
                else
-                       mono_vfree (ptr, chunk_size);
+                       mono_vfree (ptr, chunk_size, MONO_MEM_ACCOUNT_CODE);
                return NULL;
        }
        chunk->next = NULL;
index 2ca19a8b3d645fca66230e58f15d4b0e2b9cccf2..ae33b4a9f39336cb31f1c31f31d43ee7e4d497ed 100644 (file)
@@ -166,7 +166,7 @@ register_internal (const char *name, int type, void *addr, int size)
                }
        }
 
-       counter = (MonoCounter *) malloc (sizeof (MonoCounter));
+       counter = (MonoCounter *) g_malloc (sizeof (MonoCounter));
        if (!counter) {
                mono_os_mutex_unlock (&counters_mutex);
                return;
@@ -648,8 +648,8 @@ mono_counters_cleanup (void)
        while (counter) {
                MonoCounter *tmp = counter;
                counter = counter->next;
-               free ((void*)tmp->name);
-               free (tmp);
+               g_free ((void*)tmp->name);
+               g_free (tmp);
        }
 
        mono_os_mutex_unlock (&counters_mutex);
index 43116130309eec7195e24a87f8d39e10e544dbce..6c0f582cf6d1ddc170d86bf4f6fb40374138525a 100644 (file)
@@ -140,7 +140,7 @@ mono_dl_open (const char *name, int flags, char **error_msg)
        if (error_msg)
                *error_msg = NULL;
 
-       module = (MonoDl *) malloc (sizeof (MonoDl));
+       module = (MonoDl *) g_malloc (sizeof (MonoDl));
        if (!module) {
                if (error_msg)
                        *error_msg = g_strdup ("Out of memory");
@@ -174,7 +174,7 @@ mono_dl_open (const char *name, int flags, char **error_msg)
                const char *ext;
                /* This platform does not support dlopen */
                if (name == NULL) {
-                       free (module);
+                       g_free (module);
                        return NULL;
                }
                
@@ -193,7 +193,7 @@ mono_dl_open (const char *name, int flags, char **error_msg)
                        if (error_msg) {
                                *error_msg = mono_dl_current_error_string ();
                        }
-                       free (module);
+                       g_free (module);
                        return NULL;
                }
        }
@@ -224,11 +224,11 @@ mono_dl_symbol (MonoDl *module, const char *name, void **symbol)
        } else {
 #if MONO_DL_NEED_USCORE
                {
-                       char *usname = malloc (strlen (name) + 2);
+                       char *usname = g_malloc (strlen (name) + 2);
                        *usname = '_';
                        strcpy (usname + 1, name);
                        sym = mono_dl_lookup_symbol (module, usname);
-                       free (usname);
+                       g_free (usname);
                }
 #else
                sym = mono_dl_lookup_symbol (module, name);
@@ -264,7 +264,7 @@ mono_dl_close (MonoDl *module)
        } else
                mono_dl_close_handle (module);
        
-       free (module);
+       g_free (module);
 }
 
 /**
index cf73d9acbb84cbcafc5328dc5fb6b3b6f9975e50..4948b91b80fbd84435428d56098e47d751d3b2a0 100644 (file)
@@ -132,7 +132,7 @@ mono_log_write_logfile (const char *log_domain, GLogLevelFlags level, mono_bool
 
        fflush(logFile);
 
-       if (level == G_LOG_FLAG_FATAL)
+       if (level & G_LOG_LEVEL_ERROR)
                abort();
 }
 
index 388fd26202f6c5f4b2b936b6bf81592d6ed0d049..6d25d3a6117b7cc4237bc10c8c6ef9e1e67cec3d 100644 (file)
@@ -84,7 +84,7 @@ mono_log_write_syslog(const char *domain, GLogLevelFlags level, mono_bool hdr, c
 {
        syslog (mapSyslogLevel(level), "%s", message);
 
-       if (level == G_LOG_FLAG_FATAL)
+       if (level & G_LOG_LEVEL_ERROR)
                abort();
 }
 
index d0ee01994371e00665dcea0f29e18634b377a66d..f6cd987fbba85c31ebda11b966b220ef3067f7ac 100644 (file)
@@ -104,7 +104,7 @@ mono_log_write_syslog(const char *domain, GLogLevelFlags level, mono_bool hdr, c
 
        fflush(logFile);
 
-       if (level == G_LOG_FLAG_FATAL)
+       if (level & G_LOG_LEVEL_ERROR)
                abort();
 }
 
index 7fa483ce593747f586e4842fed1a720ffeff2dee..491318465faf804a0767d46b45b838d8020814b5 100644 (file)
@@ -35,6 +35,8 @@
 #include "mono-mmap-internals.h"
 #include "mono-proclib.h"
 #include <mono/utils/mono-threads.h>
+#include <mono/utils/atomic.h>
+#include <mono/utils/mono-counters.h>
 
 
 #define BEGIN_CRITICAL_SECTION do { \
@@ -84,6 +86,54 @@ aligned_address (char *mem, size_t size, size_t alignment)
        return aligned;
 }
 
+static volatile size_t allocation_count [MONO_MEM_ACCOUNT_MAX];
+
+static void
+account_mem (MonoMemAccountType type, ssize_t size)
+{
+#if SIZEOF_VOID_P == 4
+       InterlockedAdd ((volatile gint32*)&allocation_count [type], (gint32)size);
+#else
+       InterlockedAdd64 ((volatile gint64*)&allocation_count [type], (gint64)size);
+#endif
+}
+
+const char*
+mono_mem_account_type_name (MonoMemAccountType type)
+{
+       static const char *names[] = {
+               "code",
+               "hazard pointers",
+               "domain",
+               "SGen internal",
+               "SGen nursery",
+               "SGen LOS",
+               "SGen mark&sweep",
+               "SGen card table",
+               "SGen shadow card table",
+               "SGen debugging",
+               "SGen binary protocol",
+               "exceptions",
+               "profiler",
+               "other"
+       };
+
+       return names [type];
+}
+
+void
+mono_mem_account_register_counters (void)
+{
+       for (int i = 0; i < MONO_MEM_ACCOUNT_MAX; ++i) {
+               const char *prefix = "Valloc ";
+               const char *name = mono_mem_account_type_name (i);
+               char descr [128];
+               g_assert (strlen (prefix) + strlen (name) < sizeof (descr));
+               sprintf (descr, "%s%s", prefix, name);
+               mono_counters_register (descr, MONO_COUNTER_WORD | MONO_COUNTER_RUNTIME | MONO_COUNTER_BYTES | MONO_COUNTER_VARIABLE, (void*)&allocation_count [i]);
+       }
+}
+
 #ifdef HOST_WIN32
 
 int
@@ -118,7 +168,7 @@ prot_from_flags (int flags)
 }
 
 void*
-mono_valloc (void *addr, size_t length, int flags)
+mono_valloc (void *addr, size_t length, int flags, MonoMemAccountType type)
 {
        void *ptr;
        int mflags = MEM_RESERVE|MEM_COMMIT;
@@ -126,11 +176,14 @@ mono_valloc (void *addr, size_t length, int flags)
        /* translate the flags */
 
        ptr = VirtualAlloc (addr, length, mflags, prot);
+
+       account_mem (type, (ssize_t)length);
+
        return ptr;
 }
 
 void*
-mono_valloc_aligned (size_t length, size_t alignment, int flags)
+mono_valloc_aligned (size_t length, size_t alignment, int flags, MonoMemAccountType type)
 {
        int prot = prot_from_flags (flags);
        char *mem = VirtualAlloc (NULL, length + alignment, MEM_RESERVE, prot);
@@ -144,13 +197,15 @@ mono_valloc_aligned (size_t length, size_t alignment, int flags)
        aligned = VirtualAlloc (aligned, length, MEM_COMMIT, prot);
        g_assert (aligned);
 
+       account_mem (type, (ssize_t)length);
+
        return aligned;
 }
 
 #define HAVE_VALLOC_ALIGNED
 
 int
-mono_vfree (void *addr, size_t length)
+mono_vfree (void *addr, size_t length, MonoMemAccountType type)
 {
        MEMORY_BASIC_INFORMATION mbi;
        SIZE_T query_result = VirtualQuery (addr, &mbi, sizeof (mbi));
@@ -162,6 +217,8 @@ mono_vfree (void *addr, size_t length)
 
        g_assert (res);
 
+       account_mem (type, -(ssize_t)length);
+
        return 0;
 }
 
@@ -307,7 +364,7 @@ prot_from_flags (int flags)
  * Returns: NULL on failure, the address of the memory area otherwise
  */
 void*
-mono_valloc (void *addr, size_t length, int flags)
+mono_valloc (void *addr, size_t length, int flags, MonoMemAccountType type)
 {
        void *ptr;
        int mflags = 0;
@@ -334,6 +391,9 @@ mono_valloc (void *addr, size_t length, int flags)
 
        if (ptr == MAP_FAILED)
                return NULL;
+
+       account_mem (type, (ssize_t)length);
+
        return ptr;
 }
 
@@ -347,12 +407,15 @@ mono_valloc (void *addr, size_t length, int flags)
  * Returns: 0 on success.
  */
 int
-mono_vfree (void *addr, size_t length)
+mono_vfree (void *addr, size_t length, MonoMemAccountType type)
 {
        int res;
        BEGIN_CRITICAL_SECTION;
        res = munmap (addr, length);
        END_CRITICAL_SECTION;
+
+       account_mem (type, -(ssize_t)length);
+
        return res;
 }
 
@@ -482,13 +545,13 @@ mono_pagesize (void)
 }
 
 void*
-mono_valloc (void *addr, size_t length, int flags)
+mono_valloc (void *addr, size_t length, int flags, MonoMemAccountType type)
 {
-       return malloc (length);
+       return g_malloc (length);
 }
 
 void*
-mono_valloc_aligned (size_t length, size_t alignment, int flags)
+mono_valloc_aligned (size_t size, size_t alignment, int flags, MonoMemAccountType type)
 {
        g_assert_not_reached ();
 }
@@ -496,9 +559,9 @@ mono_valloc_aligned (size_t length, size_t alignment, int flags)
 #define HAVE_VALLOC_ALIGNED
 
 int
-mono_vfree (void *addr, size_t length)
+mono_vfree (void *addr, size_t length, MonoMemAccountType type)
 {
-       free (addr);
+       g_free (addr);
        return 0;
 }
 
@@ -747,10 +810,10 @@ mono_shared_area_instances (void **array, int count)
 
 #ifndef HAVE_VALLOC_ALIGNED
 void*
-mono_valloc_aligned (size_t size, size_t alignment, int flags)
+mono_valloc_aligned (size_t size, size_t alignment, int flags, MonoMemAccountType type)
 {
        /* Allocate twice the memory to be able to put the block on an aligned address */
-       char *mem = (char *) mono_valloc (NULL, size + alignment, flags);
+       char *mem = (char *) mono_valloc (NULL, size + alignment, flags, type);
        char *aligned;
 
        if (!mem)
@@ -759,9 +822,9 @@ mono_valloc_aligned (size_t size, size_t alignment, int flags)
        aligned = aligned_address (mem, size, alignment);
 
        if (aligned > mem)
-               mono_vfree (mem, aligned - mem);
+               mono_vfree (mem, aligned - mem, type);
        if (aligned + size < mem + size + alignment)
-               mono_vfree (aligned + size, (mem + size + alignment) - (aligned + size));
+               mono_vfree (aligned + size, (mem + size + alignment) - (aligned + size), type);
 
        return aligned;
 }
index 017bbcec5bb6aab1b023661caa5b2102b17469b7..d441751c802da5bb60f36c29d638377b7f426c26 100644 (file)
@@ -20,6 +20,24 @@ enum {
        MONO_MMAP_32BIT   = 1 << 8
 };
 
+typedef enum {
+       MONO_MEM_ACCOUNT_CODE,
+       MONO_MEM_ACCOUNT_HAZARD_POINTERS,
+       MONO_MEM_ACCOUNT_DOMAIN,
+       MONO_MEM_ACCOUNT_SGEN_INTERNAL,
+       MONO_MEM_ACCOUNT_SGEN_NURSERY,
+       MONO_MEM_ACCOUNT_SGEN_LOS,
+       MONO_MEM_ACCOUNT_SGEN_MARKSWEEP,
+       MONO_MEM_ACCOUNT_SGEN_CARD_TABLE,
+       MONO_MEM_ACCOUNT_SGEN_SHADOW_CARD_TABLE,
+       MONO_MEM_ACCOUNT_SGEN_DEBUGGING,
+       MONO_MEM_ACCOUNT_SGEN_BINARY_PROTOCOL,
+       MONO_MEM_ACCOUNT_EXCEPTIONS,
+       MONO_MEM_ACCOUNT_PROFILER,
+       MONO_MEM_ACCOUNT_OTHER,
+       MONO_MEM_ACCOUNT_MAX
+} MonoMemAccountType;
+
 /*
  * A simple interface to fopen/fstat/fileno
  */
@@ -31,9 +49,9 @@ MONO_API int          mono_file_map_fd    (MonoFileMap *fmap);
 MONO_API int          mono_file_map_close (MonoFileMap *fmap);
 
 MONO_API int   mono_pagesize   (void);
-MONO_API void* mono_valloc     (void *addr, size_t length, int flags);
-MONO_API void* mono_valloc_aligned (size_t length, size_t alignment, int flags);
-MONO_API int   mono_vfree      (void *addr, size_t length);
+MONO_API void* mono_valloc     (void *addr, size_t length, int flags, MonoMemAccountType type);
+MONO_API void* mono_valloc_aligned (size_t length, size_t alignment, int flags, MonoMemAccountType type);
+MONO_API int   mono_vfree      (void *addr, size_t length, MonoMemAccountType type);
 MONO_API void* mono_file_map   (size_t length, int flags, int fd, guint64 offset, void **ret_handle);
 MONO_API int   mono_file_unmap (void *addr, void *handle);
 #ifndef HOST_WIN32
@@ -42,6 +60,9 @@ MONO_API int   mono_file_unmap_fileio (void *addr, void *handle);
 #endif
 MONO_API int   mono_mprotect   (void *addr, size_t length, int flags);
 
+MONO_API const char* mono_mem_account_type_name (MonoMemAccountType type);
+MONO_API void  mono_mem_account_register_counters (void);
+
 MONO_API void* mono_shared_area         (void);
 MONO_API void  mono_shared_area_remove  (void);
 MONO_API void* mono_shared_area_for_pid (void *pid);
index 7a589314f1f43b5032ec78182bd4a377e00ba22e..79da32b45118f4e6f992207c723ce14f880477c0 100644 (file)
@@ -80,7 +80,7 @@ mono_process_list (int *size)
 #ifdef KERN_PROC2
        int mib [6];
        size_t data_len = sizeof (struct kinfo_proc2) * 400;
-       struct kinfo_proc2 *processes = malloc (data_len);
+       struct kinfo_proc2 *processes = g_malloc (data_len);
 #else
        int mib [4];
        size_t data_len = sizeof (struct kinfo_proc) * 16;
@@ -105,7 +105,7 @@ mono_process_list (int *size)
 
        res = sysctl (mib, 6, processes, &data_len, NULL, 0);
        if (res < 0) {
-               free (processes);
+               g_free (processes);
                return NULL;
        }
 #else
@@ -119,10 +119,10 @@ mono_process_list (int *size)
                res = sysctl (mib, 4, NULL, &data_len, NULL, 0);
                if (res)
                        return NULL;
-               processes = (struct kinfo_proc *) malloc (data_len);
+               processes = (struct kinfo_proc *) g_malloc (data_len);
                res = sysctl (mib, 4, processes, &data_len, NULL, 0);
                if (res < 0) {
-                       free (processes);
+                       g_free (processes);
                        if (errno != ENOMEM)
                                return NULL;
                        limit --;
@@ -140,7 +140,7 @@ mono_process_list (int *size)
        buf = (void **) g_realloc (buf, res * sizeof (void*));
        for (i = 0; i < res; ++i)
                buf [i] = GINT_TO_POINTER (processes [i].kinfo_pid_member);
-       free (processes);
+       g_free (processes);
        if (size)
                *size = res;
        return buf;
index 67b470467b96339e10e560a26f99a1f2ee644b07..4b9f5d393f5e79fb7ee9dc489f7fe8b00a0e7f69 100644 (file)
@@ -18,6 +18,7 @@
 #include <mono/utils/mono-threads-posix-signals.h>
 #include <mono/utils/mono-coop-semaphore.h>
 #include <mono/metadata/gc-internals.h>
+#include <mono/metadata/w32mutex-utils.h>
 #include <mono/utils/w32handle.h>
 
 #include <errno.h>
@@ -46,17 +47,11 @@ mono_threads_platform_register (MonoThreadInfo *info)
        gpointer thread_handle;
 
        info->owned_mutexes = g_ptr_array_new ();
-       info->priority = MONO_THREAD_PRIORITY_NORMAL;
 
        thread_handle = mono_w32handle_new (MONO_W32HANDLE_THREAD, NULL);
        if (thread_handle == INVALID_HANDLE_VALUE)
                g_error ("%s: failed to create handle", __func__);
 
-       /* We need to keep the handle alive, as long as the corresponding managed
-        * thread object is alive. The handle is going to be unref when calling
-        * the finalizer on the MonoThreadInternal object */
-       mono_w32handle_ref (thread_handle);
-
        g_assert (!info->handle);
        info->handle = thread_handle;
 }
@@ -66,6 +61,8 @@ mono_threads_platform_create_thread (MonoThreadStart thread_fn, gpointer thread_
 {
        pthread_attr_t attr;
        pthread_t thread;
+       int policy;
+       struct sched_param param;
        gint res;
 
        res = pthread_attr_init (&attr);
@@ -92,6 +89,45 @@ mono_threads_platform_create_thread (MonoThreadStart thread_fn, gpointer thread_
        g_assert (!res);
 #endif /* HAVE_PTHREAD_ATTR_SETSTACKSIZE */
 
+       memset (&param, 0, sizeof (param));
+
+       res = pthread_attr_getschedpolicy (&attr, &policy);
+       if (res != 0)
+               g_error ("%s: pthread_attr_getschedpolicy failed, error: \"%s\" (%d)", g_strerror (res), res);
+
+#ifdef _POSIX_PRIORITY_SCHEDULING
+       int max, min;
+
+       /* Necessary to get valid priority range */
+
+       min = sched_get_priority_min (policy);
+       max = sched_get_priority_max (policy);
+
+       if (max > 0 && min >= 0 && max > min)
+               param.sched_priority = (max - min) / 2 + min;
+       else
+#endif
+       {
+               switch (policy) {
+               case SCHED_FIFO:
+               case SCHED_RR:
+                       param.sched_priority = 50;
+                       break;
+#ifdef SCHED_BATCH
+               case SCHED_BATCH:
+#endif
+               case SCHED_OTHER:
+                       param.sched_priority = 0;
+                       break;
+               default:
+                       g_error ("%s: unknown policy %d", __func__, policy);
+               }
+       }
+
+       res = pthread_attr_setschedparam (&attr, &param);
+       if (res != 0)
+               g_error ("%s: pthread_attr_setschedparam failed, error: \"%s\" (%d)", g_strerror (res), res);
+
        /* Actually start the thread */
        res = mono_gc_pthread_create (&thread, &attr, (gpointer (*)(gpointer)) thread_fn, thread_data);
        if (res)
@@ -141,6 +177,14 @@ mono_threads_get_max_stack_size (void)
        return (int)lim.rlim_max;
 }
 
+gpointer
+mono_threads_platform_duplicate_handle (MonoThreadInfo *info)
+{
+       g_assert (info->handle);
+       mono_w32handle_ref (info->handle);
+       return info->handle;
+}
+
 HANDLE
 mono_threads_platform_open_thread_handle (HANDLE handle, MonoNativeThreadId tid)
 {
@@ -248,7 +292,6 @@ mono_threads_platform_set_exited (MonoThreadInfo *info)
 {
        gpointer mutex_handle;
        int i, thr_ret;
-       pid_t pid;
        pthread_t tid;
 
        g_assert (info->handle);
@@ -258,12 +301,11 @@ mono_threads_platform_set_exited (MonoThreadInfo *info)
        if (mono_w32handle_get_type (info->handle) == MONO_W32HANDLE_UNUSED)
                g_error ("%s: handle %p thread %p has already exited, it's handle type is 'unused'", __func__, info->handle, mono_thread_info_get_tid (info));
 
-       pid = wapi_getpid ();
        tid = pthread_self ();
 
        for (i = 0; i < info->owned_mutexes->len; i++) {
                mutex_handle = g_ptr_array_index (info->owned_mutexes, i);
-               wapi_mutex_abandon (mutex_handle, pid, tid);
+               mono_w32mutex_abandon (mutex_handle, tid);
                mono_thread_info_disown_mutex (info, mutex_handle);
        }
 
@@ -314,76 +356,6 @@ mono_threads_platform_disown_mutex (MonoThreadInfo *info, gpointer mutex_handle)
        g_ptr_array_remove (info->owned_mutexes, mutex_handle);
 }
 
-MonoThreadPriority
-mono_threads_platform_get_priority (MonoThreadInfo *info)
-{
-       return info->priority;
-}
-
-void
-mono_threads_platform_set_priority (MonoThreadInfo *info, MonoThreadPriority priority)
-{
-       int policy;
-       struct sched_param param;
-       pthread_t tid;
-       gint res;
-
-       g_assert (priority >= MONO_THREAD_PRIORITY_LOWEST);
-       g_assert (priority <= MONO_THREAD_PRIORITY_HIGHEST);
-       g_assert (MONO_THREAD_PRIORITY_LOWEST < MONO_THREAD_PRIORITY_HIGHEST);
-
-       tid = mono_thread_info_get_tid (info);
-
-       res = pthread_getschedparam (tid, &policy, &param);
-       if (res != 0)
-               g_error ("%s: pthread_getschedparam failed, error: \"%s\" (%d)", g_strerror (res), res);
-
-#ifdef _POSIX_PRIORITY_SCHEDULING
-       int max, min;
-
-       /* Necessary to get valid priority range */
-
-       min = sched_get_priority_min (policy);
-       max = sched_get_priority_max (policy);
-
-       if (max > 0 && min >= 0 && max > min) {
-               double srange, drange, sposition, dposition;
-               srange = MONO_THREAD_PRIORITY_HIGHEST - MONO_THREAD_PRIORITY_LOWEST;
-               drange = max - min;
-               sposition = priority - MONO_THREAD_PRIORITY_LOWEST;
-               dposition = (sposition / srange) * drange;
-               param.sched_priority = (int)(dposition + min);
-       } else
-#endif
-       {
-               switch (policy) {
-               case SCHED_FIFO:
-               case SCHED_RR:
-                       param.sched_priority = 50;
-                       break;
-#ifdef SCHED_BATCH
-               case SCHED_BATCH:
-#endif
-               case SCHED_OTHER:
-                       param.sched_priority = 0;
-                       break;
-               default:
-                       g_error ("%s: unknown policy %d", __func__, policy);
-               }
-       }
-
-       res = pthread_setschedparam (tid, policy, &param);
-       if (res != 0) {
-               if (res == EPERM) {
-                       g_warning ("%s: pthread_setschedparam failed, error: \"%s\" (%d)", g_strerror (res), res);
-                       return;
-               }
-               g_error ("%s: pthread_setschedparam failed, error: \"%s\" (%d)", g_strerror (res), res);
-       }
-
-       info->priority = priority;
-}
-
 static const gchar* thread_typename (void)
 {
        return "Thread";
index 4f8495054334310bb2f7289e8778e657915e59f2..4761af48d0c90507c6fc9433a6b882b05afb804f 100644 (file)
@@ -253,6 +253,17 @@ mono_threads_get_max_stack_size (void)
        return INT_MAX;
 }
 
+gpointer
+mono_threads_platform_duplicate_handle (MonoThreadInfo *info)
+{
+       HANDLE thread_handle;
+
+       g_assert (info->handle);
+       DuplicateHandle (GetCurrentProcess (), info->handle, GetCurrentProcess (), &thread_handle, THREAD_ALL_ACCESS, TRUE, 0);
+
+       return thread_handle;
+}
+
 HANDLE
 mono_threads_platform_open_thread_handle (HANDLE handle, MonoNativeThreadId tid)
 {
@@ -324,25 +335,6 @@ mono_threads_platform_disown_mutex (MonoThreadInfo *info, gpointer mutex_handle)
        g_assert_not_reached ();
 }
 
-MonoThreadPriority
-mono_threads_platform_get_priority (MonoThreadInfo *info)
-{
-       g_assert (info->handle);
-       return GetThreadPriority (info->handle) + 2;
-}
-
-void
-mono_threads_platform_set_priority (MonoThreadInfo *info, MonoThreadPriority priority)
-{
-       BOOL res;
-
-       g_assert (info->handle);
-
-       res = SetThreadPriority (info->handle, priority - 2);
-       if (!res)
-               g_error ("%s: SetThreadPriority failed, error %d", __func__, GetLastError ());
-}
-
 void
 mono_threads_platform_init (void)
 {
index a75adc4599f523313fd5ce23bfb4eb966654e562..2f07dbae1f1393f39fd62d5ac0a32d3eaae39864 100644 (file)
@@ -766,12 +766,6 @@ static gboolean
 mono_thread_info_core_resume (MonoThreadInfo *info)
 {
        gboolean res = FALSE;
-       if (info->create_suspended) {
-               /* Have to special case this, as the normal suspend/resume pair are racy, they don't work if he resume is received before the suspend */
-               info->create_suspended = FALSE;
-               mono_coop_sem_post (&info->create_suspended_sem);
-               return TRUE;
-       }
 
        switch (mono_threads_transition_request_resume (info)) {
        case ResumeError:
@@ -1142,10 +1136,9 @@ typedef struct {
        gint32 ref;
        MonoThreadStart start_routine;
        gpointer start_routine_arg;
-       gboolean create_suspended;
        gint32 priority;
        MonoCoopSem registered;
-       MonoThreadInfo *info;
+       gpointer handle;
 } CreateThreadData;
 
 static gsize WINAPI
@@ -1156,10 +1149,7 @@ inner_start_thread (gpointer data)
        MonoThreadStart start_routine;
        gpointer start_routine_arg;
        guint32 start_routine_res;
-       gboolean create_suspended;
-       gint32 priority;
        gsize dummy;
-       gint res;
 
        thread_data = (CreateThreadData*) data;
        g_assert (thread_data);
@@ -1167,20 +1157,10 @@ inner_start_thread (gpointer data)
        start_routine = thread_data->start_routine;
        start_routine_arg = thread_data->start_routine_arg;
 
-       create_suspended = thread_data->create_suspended;
-       priority = thread_data->priority;
-
        info = mono_thread_info_attach (&dummy);
        info->runtime_thread = TRUE;
 
-       mono_threads_platform_set_priority (info, priority);
-
-       if (create_suspended) {
-               info->create_suspended = TRUE;
-               mono_coop_sem_init (&info->create_suspended_sem, 0);
-       }
-
-       thread_data->info = info;
+       thread_data->handle = mono_thread_info_duplicate_handle (info);
 
        mono_coop_sem_post (&thread_data->registered);
 
@@ -1192,13 +1172,6 @@ inner_start_thread (gpointer data)
        /* thread_data is not valid anymore */
        thread_data = NULL;
 
-       if (create_suspended) {
-               res = mono_coop_sem_wait (&info->create_suspended_sem, MONO_SEM_FLAGS_NONE);
-               g_assert (res == 0);
-
-               mono_coop_sem_destroy (&info->create_suspended_sem);
-       }
-
        /* Run the actual main function of the thread */
        start_routine_res = start_routine (start_routine_arg);
 
@@ -1214,10 +1187,9 @@ inner_start_thread (gpointer data)
  * Returns: a windows or io-layer handle for the thread.
  */
 HANDLE
-mono_threads_create_thread (MonoThreadStart start, gpointer arg, MonoThreadParm *tp, MonoNativeThreadId *out_tid)
+mono_threads_create_thread (MonoThreadStart start, gpointer arg, gsize stack_size, MonoNativeThreadId *out_tid)
 {
        CreateThreadData *thread_data;
-       MonoThreadInfo *info;
        gint res;
        gpointer ret;
 
@@ -1225,11 +1197,9 @@ mono_threads_create_thread (MonoThreadStart start, gpointer arg, MonoThreadParm
        thread_data->ref = 2;
        thread_data->start_routine = start;
        thread_data->start_routine_arg = arg;
-       thread_data->create_suspended = tp->creation_flags & CREATE_SUSPENDED;
-       thread_data->priority = tp->priority;
        mono_coop_sem_init (&thread_data->registered, 0);
 
-       res = mono_threads_platform_create_thread (inner_start_thread, (gpointer) thread_data, tp->stack_size, out_tid);
+       res = mono_threads_platform_create_thread (inner_start_thread, (gpointer) thread_data, stack_size, out_tid);
        if (res != 0) {
                /* ref is not going to be decremented in inner_start_thread */
                InterlockedDecrement (&thread_data->ref);
@@ -1240,10 +1210,7 @@ mono_threads_create_thread (MonoThreadStart start, gpointer arg, MonoThreadParm
        res = mono_coop_sem_wait (&thread_data->registered, MONO_SEM_FLAGS_NONE);
        g_assert (res == 0);
 
-       info = thread_data->info;
-       g_assert (info);
-
-       ret = info->handle;
+       ret = thread_data->handle;
        g_assert (ret);
 
 done:
@@ -1311,7 +1278,7 @@ sleep_interruptable (guint32 ms, gboolean *alerted)
        *alerted = FALSE;
 
        if (ms != INFINITE)
-               end = mono_100ns_ticks () + (ms * 1000 * 10);
+               end = mono_msec_ticks() + ms;
 
        mono_lazy_initialize (&sleep_init, sleep_initialize);
 
@@ -1319,8 +1286,8 @@ sleep_interruptable (guint32 ms, gboolean *alerted)
 
        for (;;) {
                if (ms != INFINITE) {
-                       now = mono_100ns_ticks ();
-                       if (now > end)
+                       now = mono_msec_ticks();
+                       if (now >= end)
                                break;
                }
 
@@ -1331,7 +1298,7 @@ sleep_interruptable (guint32 ms, gboolean *alerted)
                }
 
                if (ms != INFINITE)
-                       mono_coop_cond_timedwait (&sleep_cond, &sleep_mutex, (end - now) / 10 / 1000);
+                       mono_coop_cond_timedwait (&sleep_cond, &sleep_mutex, end - now);
                else
                        mono_coop_cond_wait (&sleep_cond, &sleep_mutex);
 
@@ -1689,10 +1656,10 @@ mono_thread_info_set_exited (THREAD_INFO_TYPE *info)
 }
 
 gpointer
-mono_thread_info_get_handle (THREAD_INFO_TYPE *info)
+mono_thread_info_duplicate_handle (MonoThreadInfo *info)
 {
-       g_assert (info->handle);
-       return info->handle;
+       g_assert (mono_thread_info_is_current (info));
+       return mono_threads_platform_duplicate_handle (info);
 }
 
 void
@@ -1712,15 +1679,3 @@ mono_thread_info_disown_mutex (MonoThreadInfo *info, gpointer mutex_handle)
 {
        mono_threads_platform_disown_mutex (info, mutex_handle);
 }
-
-MonoThreadPriority
-mono_thread_info_get_priority (MonoThreadInfo *info)
-{
-       return mono_threads_platform_get_priority (info);
-}
-
-void
-mono_thread_info_set_priority (MonoThreadInfo *info, MonoThreadPriority priority)
-{
-       mono_threads_platform_set_priority (info, priority);
-}
index c81f3c6ba3f4e8c4f97fb6528ec103c86b9ee120..493d44884ca49f564d9f9f057479bf082645848a 100644 (file)
@@ -221,11 +221,6 @@ typedef struct {
         */
        gboolean is_async_context;
 
-       gboolean create_suspended;
-
-       /* Semaphore used to implement CREATE_SUSPENDED */
-       MonoCoopSem create_suspended_sem;
-
        /*
         * Values of TLS variables for this thread.
         * This can be used to obtain the values of TLS variable for threads
@@ -250,7 +245,6 @@ typedef struct {
 #if defined(_POSIX_VERSION) || defined(__native_client__)
        /* This is the data that was stored in the w32 handle */
        GPtrArray *owned_mutexes;
-       gint32 priority;
 #endif
 } MonoThreadInfo;
 
@@ -290,23 +284,6 @@ typedef enum {
 
 typedef SuspendThreadResult (*MonoSuspendThreadCallback) (THREAD_INFO_TYPE *info, gpointer user_data);
 
-/*
- * Parameters to pass for thread creation
- */
-typedef struct {
-       int priority;
-       guint32 creation_flags; 
-       guint32 stack_size;             
-} MonoThreadParm;
-
-typedef enum {
-       MONO_THREAD_PRIORITY_LOWEST       = 0,
-       MONO_THREAD_PRIORITY_BELOW_NORMAL = 1,
-       MONO_THREAD_PRIORITY_NORMAL       = 2,
-       MONO_THREAD_PRIORITY_ABOVE_NORMAL = 3,
-       MONO_THREAD_PRIORITY_HIGHEST      = 4,
-} MonoThreadPriority;
-
 static inline gboolean
 mono_threads_filter_tools_threads (THREAD_INFO_TYPE *info)
 {
@@ -471,7 +448,7 @@ gboolean
 mono_thread_info_is_live (THREAD_INFO_TYPE *info);
 
 HANDLE
-mono_threads_create_thread (MonoThreadStart start, gpointer arg, MonoThreadParm *tp, MonoNativeThreadId *out_tid);
+mono_threads_create_thread (MonoThreadStart start, gpointer arg, gsize stack_size, MonoNativeThreadId *out_tid);
 
 int
 mono_threads_get_max_stack_size (void);
@@ -554,8 +531,7 @@ void mono_threads_platform_set_exited (THREAD_INFO_TYPE *info);
 void mono_threads_platform_describe (THREAD_INFO_TYPE *info, GString *text);
 void mono_threads_platform_own_mutex (THREAD_INFO_TYPE *info, gpointer mutex_handle);
 void mono_threads_platform_disown_mutex (THREAD_INFO_TYPE *info, gpointer mutex_handle);
-MonoThreadPriority mono_threads_platform_get_priority (THREAD_INFO_TYPE *info);
-void mono_threads_platform_set_priority (THREAD_INFO_TYPE *info, MonoThreadPriority priority);
+gpointer mono_threads_platform_duplicate_handle (THREAD_INFO_TYPE *info);
 
 void mono_threads_coop_begin_global_suspend (void);
 void mono_threads_coop_end_global_suspend (void);
@@ -671,7 +647,7 @@ gboolean
 mono_thread_info_is_current (THREAD_INFO_TYPE *info);
 
 gpointer
-mono_thread_info_get_handle (THREAD_INFO_TYPE *info);
+mono_thread_info_duplicate_handle (THREAD_INFO_TYPE *info);
 
 void
 mono_thread_info_describe (THREAD_INFO_TYPE *info, GString *text);
@@ -682,10 +658,4 @@ mono_thread_info_own_mutex (THREAD_INFO_TYPE *info, gpointer mutex_handle);
 void
 mono_thread_info_disown_mutex (THREAD_INFO_TYPE *info, gpointer mutex_handle);
 
-MonoThreadPriority
-mono_thread_info_get_priority (THREAD_INFO_TYPE *info);
-
-void
-mono_thread_info_set_priority (THREAD_INFO_TYPE *info, MonoThreadPriority priority);
-
 #endif /* __MONO_THREADS_H__ */
index 7a2c4ac8100ebd9afec9607a8b7b0640c498f3a5..8ebc25a69b303019f66ecd117a2e9f7a5843a0c1 100644 (file)
@@ -36,7 +36,7 @@ mono_escape_uri_string (const gchar *string)
 #if TEST
 int main ()
 {
-       char *s = malloc (256);
+       char *s = g_malloc (256);
        int i = 0;
        
        s [255] = 0;
index 41f6439154b8065c50523f175f48f0c55c97835b..78517bc7c3aece3e8f2b96fc3d519c791872fe43 100644 (file)
@@ -26,6 +26,9 @@
     <ClCompile Include="..\mono\metadata\class.c" />\r
     <ClCompile Include="..\mono\metadata\cominterop.c" />\r
     <ClCompile Include="..\mono\metadata\console-win32.c" />\r
+    <ClCompile Include="..\mono\metadata\w32mutex-win32.c" />\r
+    <ClCompile Include="..\mono\metadata\w32semaphore-win32.c" />\r
+    <ClCompile Include="..\mono\metadata\w32event-win32.c" />\r
     <ClCompile Include="..\mono\metadata\coree.c" />\r
     <ClCompile Include="..\mono\metadata\custom-attrs.c" />\r
     <ClCompile Include="..\mono\metadata\debug-helpers.c" />\r
index 13f50fb2be4cdd5171a246f051f07b3b60db1da9..ba4d25f1ba94d8e9c6028b819c66bbfb4f414532 100644 (file)
     <ClCompile Include="..\mono\metadata\console-win32.c">\r
       <Filter>Source Files</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="..\mono\metadata\w32mutex-win32.c">\r
+      <Filter>Source Files</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\mono\metadata\w32semaphore-win32.c">\r
+      <Filter>Source Files</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\mono\metadata\w32event-win32.c">\r
+      <Filter>Source Files</Filter>\r
+    </ClCompile>\r
     <ClCompile Include="..\mono\metadata\coree.c">\r
       <Filter>Source Files</Filter>\r
     </ClCompile>\r
index b202c2493fb11fac4ff3acf6dce92f6ecb56e979..74f0d1bbf386169c651b16b7ff4828e506e0bf64 100755 (executable)
@@ -59,6 +59,11 @@ if [[ -n "${ghprbPullId}" ]] && [[ ${label} == w* ]];
 fi
 
 if [[ ${CI_TAGS} == *'acceptance-tests'* ]];
-then $(dirname "${BASH_SOURCE[0]}")/run-test-acceptance-tests.sh
-else make check-ci
-fi
\ No newline at end of file
+    then
+       $(dirname "${BASH_SOURCE[0]}")/run-test-acceptance-tests.sh
+elif [[ ${CI_TAGS} == *'profiler-stress-tests'* ]];
+    then
+       $(dirname "${BASH_SOURCE[0]}")/run-test-profiler-stress-tests.sh
+else
+       make check-ci
+fi
diff --git a/scripts/ci/run-test-profiler-stress-tests.sh b/scripts/ci/run-test-profiler-stress-tests.sh
new file mode 100755 (executable)
index 0000000..52d6f16
--- /dev/null
@@ -0,0 +1,5 @@
+#!/bin/bash -e
+
+export TESTCMD=`dirname "${BASH_SOURCE[0]}"`/run-step.sh
+
+${TESTCMD} --label=check-profiler-stress --timeout=20h make -C acceptance-tests check-profiler-stress