Skip to content

Commit

Permalink
[corlib] Import System.Threading.Monitor
Browse files Browse the repository at this point in the history
  • Loading branch information
luhenry committed May 4, 2016
1 parent 39ebee1 commit 873e014
Show file tree
Hide file tree
Showing 9 changed files with 46 additions and 184 deletions.
179 changes: 28 additions & 151 deletions mcs/class/corlib/System.Threading/Monitor.cs
Expand Up @@ -37,151 +37,51 @@

namespace System.Threading
{
[ComVisible (true)]
public static class Monitor
public static partial class Monitor
{
// Grabs the mutex on object 'obj', with a maximum
// wait time 'ms' but doesn't block - if it can't get
// the lock it returns false, true if it can
[MethodImplAttribute(MethodImplOptions.InternalCall)]
private extern static bool Monitor_try_enter(object obj, int ms);
extern static bool Monitor_test_synchronised(object obj);

// Enter/Exit are implemented directly as icalls for performance reasons

// Acquires the mutex on object 'obj'
[MethodImplAttribute(MethodImplOptions.InternalCall)]
public extern static void Enter(object obj);

// Releases the mutex on object 'obj'
[ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
[MethodImplAttribute(MethodImplOptions.InternalCall)]
public extern static void Exit(object obj);

// Signals one of potentially many objects waiting on
// object 'obj'
[MethodImplAttribute(MethodImplOptions.InternalCall)]
private extern static void Monitor_pulse(object obj);
extern static void Monitor_pulse(object obj);

// Checks whether object 'obj' is currently synchronised
[MethodImplAttribute(MethodImplOptions.InternalCall)]
private extern static bool Monitor_test_synchronised(object obj);

public static void Pulse(object obj) {
if(obj==null) {
throw new ArgumentNullException("obj");
}
if(Monitor_test_synchronised(obj)==false) {
static void ObjPulse(Object obj)
{
if (!Monitor_test_synchronised (obj))
throw new SynchronizationLockException("Object is not synchronized");
}

Monitor_pulse(obj);
Monitor_pulse (obj);
}

// Signals all of potentially many objects waiting on
// object 'obj'
[MethodImplAttribute(MethodImplOptions.InternalCall)]
private extern static void Monitor_pulse_all(object obj);

public static void PulseAll(object obj) {
if(obj==null) {
throw new ArgumentNullException("obj");
}
if(Monitor_test_synchronised(obj)==false) {
throw new SynchronizationLockException("Object is not synchronized");
}

Monitor_pulse_all(obj);
}
extern static void Monitor_pulse_all(object obj);

public static bool TryEnter (object obj)
static void ObjPulseAll(Object obj)
{
return TryEnter (obj, 0);
}

public static bool TryEnter (object obj, int millisecondsTimeout)
{
if (obj == null)
throw new ArgumentNullException ("obj");

if (millisecondsTimeout == Timeout.Infinite) {
Enter (obj);
return true;
}

if (millisecondsTimeout < 0)
throw new ArgumentException ("negative value for millisecondsTimeout", "millisecondsTimeout");

return Monitor_try_enter (obj, millisecondsTimeout);
}
if (!Monitor_test_synchronised (obj))
throw new SynchronizationLockException("Object is not synchronized");

public static bool TryEnter (object obj, TimeSpan timeout)
{
long ms = (long) timeout.TotalMilliseconds;
if (ms < Timeout.Infinite || ms > Int32.MaxValue)
throw new ArgumentOutOfRangeException ("timeout", "timeout out of range");

return TryEnter (obj, (int) ms);
Monitor_pulse_all (obj);
}

// Waits for a signal on object 'obj' with maximum
// wait time 'ms'. Returns true if the object was
// signalled, false if it timed out
[MethodImplAttribute(MethodImplOptions.InternalCall)]
private extern static bool Monitor_wait(object obj, int ms);

public static bool Wait (object obj)
{
return Wait (obj, Timeout.Infinite);
}
extern static bool Monitor_wait(object obj, int ms);

public static bool Wait (object obj, int millisecondsTimeout)
static bool ObjWait(bool exitContext, int millisecondsTimeout, Object obj)
{
if (obj == null)
throw new ArgumentNullException ("obj");

if (millisecondsTimeout < Timeout.Infinite)
throw new ArgumentOutOfRangeException ("millisecondsTimeout", "timeout out of range");

if (millisecondsTimeout < 0 && millisecondsTimeout != (int) Timeout.Infinite)
throw new ArgumentOutOfRangeException ("millisecondsTimeout");
if (!Monitor_test_synchronised (obj))
throw new SynchronizationLockException ("Object is not synchronized");

return Monitor_wait (obj, millisecondsTimeout);
}

public static bool Wait (object obj, TimeSpan timeout)
{
long ms = (long) timeout.TotalMilliseconds;
if (ms < Timeout.Infinite || ms > Int32.MaxValue)
throw new ArgumentOutOfRangeException ("timeout", "timeout out of range");

return Wait (obj, (int) ms);
}

public static bool Wait(object obj, int millisecondsTimeout, bool exitContext) {
try {
#if !DISABLE_REMOTING
if (exitContext)
SynchronizationAttribute.ExitContext ();
#endif
return Wait (obj, millisecondsTimeout);
}
finally {
#if !DISABLE_REMOTING
if (exitContext)
SynchronizationAttribute.EnterContext ();
#endif
}
}

public static bool Wait(object obj, TimeSpan timeout, bool exitContext) {
try {
#if !DISABLE_REMOTING
if (exitContext)
SynchronizationAttribute.ExitContext ();
#endif
return Wait (obj, timeout);
}
finally {
return Monitor_wait (obj, millisecondsTimeout);
} finally {
#if !DISABLE_REMOTING
if (exitContext)
SynchronizationAttribute.EnterContext ();
Expand All @@ -192,50 +92,27 @@ public static bool Wait (object obj, TimeSpan timeout)
[MethodImplAttribute(MethodImplOptions.InternalCall)]
extern static void try_enter_with_atomic_var (object obj, int millisecondsTimeout, ref bool lockTaken);

[MethodImplAttribute(MethodImplOptions.InternalCall)]
extern static void enter_with_atomic_var (object obj, ref bool lockTaken);

// Can't make this an icall since it has the same name as the other Enter method
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void Enter (object obj, ref bool lockTaken)
static void ReliableEnterTimeout(Object obj, int timeout, ref bool lockTaken)
{
enter_with_atomic_var (obj, ref lockTaken);
}
if (obj == null)
throw new ArgumentNullException ("obj");
if (timeout < 0 && timeout != (int) Timeout.Infinite)
throw new ArgumentOutOfRangeException ("millisecondsTimeout");

public static void TryEnter (object obj, ref bool lockTaken)
{
TryEnter (obj, 0, ref lockTaken);
try_enter_with_atomic_var (obj, timeout, ref lockTaken);
}

public static void TryEnter (object obj, TimeSpan timeout, ref bool lockTaken)
static void ReliableEnter(Object obj, ref bool lockTaken)
{
long ms = (long) timeout.TotalMilliseconds;
if (ms < Timeout.Infinite || ms > Int32.MaxValue)
throw new ArgumentOutOfRangeException ("timeout", "timeout out of range");
TryEnter (obj, (int)ms, ref lockTaken);
ReliableEnterTimeout (obj, (int) Timeout.Infinite, ref lockTaken);
}

public static void TryEnter (object obj, int millisecondsTimeout, ref bool lockTaken)
{
if (obj == null)
throw new ArgumentNullException ("obj");
if (lockTaken)
throw new ArgumentException ("lockTaken");

if (millisecondsTimeout < 0 && millisecondsTimeout != Timeout.Infinite)
throw new ArgumentException ("negative value for millisecondsTimeout", "millisecondsTimeout");

try_enter_with_atomic_var (obj, millisecondsTimeout, ref lockTaken);
}


[MethodImplAttribute(MethodImplOptions.InternalCall)]
extern static bool Monitor_test_owner (object obj);

public
static bool IsEntered (object obj)
static bool IsEnteredNative(Object obj)
{
return Monitor_test_owner(obj);
return Monitor_test_owner (obj);
}
}
}
2 changes: 1 addition & 1 deletion mcs/class/corlib/Test/System.Threading/MonitorTest.cs
Expand Up @@ -144,7 +144,7 @@ public void TryEnter_Null_Int ()
}

[Test]
[ExpectedException (typeof (ArgumentException))]
[ExpectedException (typeof (ArgumentOutOfRangeException))]
public void TryEnter_Int_Negative ()
{
object o = new object ();
Expand Down
1 change: 1 addition & 0 deletions mcs/class/corlib/corlib.dll.sources
Expand Up @@ -1556,6 +1556,7 @@ ReferenceSources/SecurityContext.cs
../referencesource/mscorlib/system/threading/lockrecursionexception.cs
../referencesource/mscorlib/system/threading/manualresetevent.cs
../referencesource/mscorlib/system/threading/ManualResetEventSlim.cs
../referencesource/mscorlib/system/threading/monitor.cs
../referencesource/mscorlib/system/threading/parameterizedthreadstart.cs
../referencesource/mscorlib/system/threading/semaphorefullexception.cs
../referencesource/mscorlib/system/threading/SemaphoreSlim.cs
Expand Down
15 changes: 13 additions & 2 deletions mcs/class/referencesource/mscorlib/system/threading/monitor.cs
Expand Up @@ -31,7 +31,7 @@ namespace System.Threading {

[HostProtection(Synchronization=true, ExternalThreading=true)]
[System.Runtime.InteropServices.ComVisible(true)]
public static class Monitor
public static partial class Monitor
{
/*=========================================================================
** Obtain the monitor lock of obj. Will block if another thread holds the lock
Expand Down Expand Up @@ -66,11 +66,12 @@ private static void ThrowLockTakenException()
throw new ArgumentException(Environment.GetResourceString("Argument_MustBeFalse"), "lockTaken");
}

#if !MONO
[System.Security.SecuritySafeCritical]
[ResourceExposure(ResourceScope.None)]
[MethodImplAttribute(MethodImplOptions.InternalCall)]
private static extern void ReliableEnter(Object obj, ref bool lockTaken);

#endif


/*=========================================================================
Expand Down Expand Up @@ -160,10 +161,12 @@ public static void TryEnter(Object obj, TimeSpan timeout, ref bool lockTaken)
ReliableEnterTimeout(obj, MillisecondsTimeoutFromTimeSpan(timeout), ref lockTaken);
}

#if !MONO
[System.Security.SecuritySafeCritical]
[ResourceExposure(ResourceScope.None)]
[MethodImplAttribute(MethodImplOptions.InternalCall)]
private static extern void ReliableEnterTimeout(Object obj, int timeout, ref bool lockTaken);
#endif

[System.Security.SecuritySafeCritical]
public static bool IsEntered(object obj)
Expand All @@ -174,10 +177,12 @@ public static bool IsEntered(object obj)
return IsEnteredNative(obj);
}

#if !MONO
[System.Security.SecurityCritical]
[ResourceExposure(ResourceScope.None)]
[MethodImplAttribute(MethodImplOptions.InternalCall)]
private static extern bool IsEnteredNative(Object obj);
#endif

/*========================================================================
** Waits for notification from the object (via a Pulse/PulseAll).
Expand All @@ -190,10 +195,12 @@ public static bool IsEntered(object obj)
**
** Exceptions: ArgumentNullException if object is null.
========================================================================*/
#if !MONO
[System.Security.SecurityCritical] // auto-generated
[ResourceExposure(ResourceScope.None)]
[MethodImplAttribute(MethodImplOptions.InternalCall)]
private static extern bool ObjWait(bool exitContext, int millisecondsTimeout, Object obj);
#endif

[System.Security.SecuritySafeCritical] // auto-generated
public static bool Wait(Object obj, int millisecondsTimeout, bool exitContext)
Expand Down Expand Up @@ -228,10 +235,12 @@ public static bool Wait(Object obj)
* Exceptions: SynchronizationLockException if this method is not called inside
* a synchronized block of code.
========================================================================*/
#if !MONO
[System.Security.SecurityCritical] // auto-generated
[ResourceExposure(ResourceScope.None)]
[MethodImplAttribute(MethodImplOptions.InternalCall)]
private static extern void ObjPulse(Object obj);
#endif

[System.Security.SecuritySafeCritical] // auto-generated
public static void Pulse(Object obj)
Expand All @@ -247,10 +256,12 @@ public static void Pulse(Object obj)
/*========================================================================
** Sends a notification to all waiting objects.
========================================================================*/
#if !MONO
[System.Security.SecurityCritical] // auto-generated
[ResourceExposure(ResourceScope.None)]
[MethodImplAttribute(MethodImplOptions.InternalCall)]
private static extern void ObjPulseAll(Object obj);
#endif

[System.Security.SecuritySafeCritical] // auto-generated
public static void PulseAll(Object obj)
Expand Down
2 changes: 0 additions & 2 deletions mono/metadata/icall-def.h
Expand Up @@ -873,9 +873,7 @@ ICALL(MONIT_2, "Monitor_pulse", ves_icall_System_Threading_Monitor_Monitor_pulse
ICALL(MONIT_3, "Monitor_pulse_all", ves_icall_System_Threading_Monitor_Monitor_pulse_all)
ICALL(MONIT_4, "Monitor_test_owner", ves_icall_System_Threading_Monitor_Monitor_test_owner)
ICALL(MONIT_5, "Monitor_test_synchronised", ves_icall_System_Threading_Monitor_Monitor_test_synchronised)
ICALL(MONIT_6, "Monitor_try_enter", ves_icall_System_Threading_Monitor_Monitor_try_enter)
ICALL(MONIT_7, "Monitor_wait", ves_icall_System_Threading_Monitor_Monitor_wait)
ICALL(MONIT_10, "enter_with_atomic_var", mono_monitor_enter_v4)
ICALL(MONIT_9, "try_enter_with_atomic_var", ves_icall_System_Threading_Monitor_Monitor_try_enter_with_atomic_var)

ICALL_TYPE(MUTEX, "System.Threading.Mutex", MUTEX_1)
Expand Down
2 changes: 1 addition & 1 deletion mono/metadata/marshal.c
Expand Up @@ -9202,7 +9202,7 @@ mono_marshal_get_synchronized_wrapper (MonoMethod *method)
if (!enter_method) {
MonoMethodDesc *desc;

desc = mono_method_desc_new ("Monitor:enter_with_atomic_var(object,bool&)", FALSE);
desc = mono_method_desc_new ("Monitor:Enter(object,bool&)", FALSE);
enter_method = mono_method_desc_search_in_class (desc, mono_defaults.monitor_class);
g_assert (enter_method);
mono_method_desc_free (desc);
Expand Down
19 changes: 0 additions & 19 deletions mono/metadata/monitor.c
Expand Up @@ -1076,25 +1076,6 @@ mono_monitor_threads_sync_members_offset (int *status_offset, int *nest_offset)
*nest_offset = ENCODE_OFF_SIZE (MONO_STRUCT_OFFSET (MonoThreadsSync, nest), sizeof (ts.nest));
}

gboolean
ves_icall_System_Threading_Monitor_Monitor_try_enter (MonoObject *obj, guint32 ms)
{
gint32 res;

do {
res = mono_monitor_try_enter_internal (obj, ms, TRUE);
if (res == -1) {
MonoException *exc = mono_thread_interruption_checkpoint ();
if (exc) {
mono_set_pending_exception (exc);
return FALSE;
}
}
} while (res == -1);

return res == 1;
}

void
ves_icall_System_Threading_Monitor_Monitor_try_enter_with_atomic_var (MonoObject *obj, guint32 ms, char *lockTaken)
{
Expand Down
1 change: 0 additions & 1 deletion mono/metadata/monitor.h
Expand Up @@ -115,7 +115,6 @@ void mono_monitor_threads_sync_members_offset (int *status_offset, int *nest_off
#define MONO_THREADS_SYNC_MEMBER_OFFSET(o) ((o)>>8)
#define MONO_THREADS_SYNC_MEMBER_SIZE(o) ((o)&0xff)

extern gboolean ves_icall_System_Threading_Monitor_Monitor_try_enter(MonoObject *obj, guint32 ms);
extern gboolean ves_icall_System_Threading_Monitor_Monitor_test_owner(MonoObject *obj);
extern gboolean ves_icall_System_Threading_Monitor_Monitor_test_synchronised(MonoObject *obj);
extern void ves_icall_System_Threading_Monitor_Monitor_pulse(MonoObject *obj);
Expand Down

0 comments on commit 873e014

Please sign in to comment.