[prev in list] [next in list] [prev in thread] [next in thread] 

List:       mono-devel-list
Subject:    Re: [Mono-dev] Jump trampoline threading problem with synchronized
From:       Martin_Däumler <mdae () cs ! tu-chemnitz ! de>
Date:       2011-06-09 7:41:25
Message-ID: 4DF07925.5060302 () cs ! tu-chemnitz ! de
[Download RAW message or body]

On 08.06.11 11:13 pm, Rodrigo Kumpera wrote:
>
>
> On Wed, Jun 8, 2011 at 10:49 AM, Martin Däumler <mdae@cs.tu-chemnitz.de
> <mailto:mdae@cs.tu-chemnitz.de>> wrote:
>
>     On 30.05.11 4:50 pm, Rodrigo Kumpera wrote:
>      > The fix is to actually disable jmp to synchronized methods and use a
>      > regular call.
>
>     Hello,
>
>     what is about the "LDFTN" IL-opcode? Mono's JIT-compiler emits
>     an internal jit call to "mono_ldftn()" that uses jump trampolines.
>     So I assume that the optimization also might bypass a wrapper
>     of the method going to be loaded.

Hello,

I appended a test case. In the test case, two threads are started.
The threads execute the methods "jumpStart1()" and "jumpStart2()",
respectively. Those methods load a pointer to the synchronized
method "syncMethod()" via "ldftn". That method is called via
"calli" and it increments a static class variable ten times. So,
the expected output is "10" and "20", because the method
"syncMethod()" is synchronized. However, sometimes the output
is "10" and "10". I tested with Mono 2.6.1 on x86 Linux and
Mono 2.10.2 on Mac OS X. On .NET, it seems to work because
in all test runs the output was "10" and "20".


If I disable the jump trampoline optimization in
"mono_create_jump_trampoline()", "mono_jit_compile_method_inner()"
and "mono_post_process_patches()" it seems to work correctly.



With kind regards,
Martin Däumler

["thread-ldftn.il" (text/plain)]

.assembly extern mscorlib
{
  .ver 1:0:5000:0
  .publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4..
}
.assembly 'thread-ldftn'
{
  .hash algorithm 0x00008004
  .ver  0:0:0:0
}
.module 'thread-ldftn.exe' // GUID = {709F3652-CB60-4263-B48A-B18AD4536D6F}


  .class private auto ansi beforefieldinit TestClass
  	extends [mscorlib]System.Object
  {
    .field  private static  int32 count

    // method line 1
    .method public hidebysig  specialname  rtspecialname 
           instance default void '.ctor' ()  cil managed 
    {
        // Method begins at RVA 0x20ec
	// Code size 7 (0x7)
	.maxstack 8
	IL_0000:  ldarg.0 
	IL_0001:  call instance void object::'.ctor'()
	IL_0006:  ret 
    } // end of method TestClass::.ctor

    // method line 2
    .method private static  specialname  rtspecialname 
           default void '.cctor' ()  cil managed 
    {
        // Method begins at RVA 0x20f4
	// Code size 1 (0x1)
	.maxstack 8
	IL_0000:  ret 
    } // end of method TestClass::.cctor

    // method line 3
    .method public static  hidebysig 
           default void syncMethod ()  cil managed synchronized 
    {
        // Method begins at RVA 0x20f8
	// Code size 71 (0x47)
	.maxstack 6
	.locals init (
		int32	V_0,
		int32	V_1)
	IL_0000:  ldc.i4.0 
	IL_0001:  stloc.0 
	IL_0002:  br IL_0025

	IL_0007:  ldloc.0 
	IL_0008:  ldc.i4.1 
	IL_0009:  add 
	IL_000a:  stloc.0 
	IL_000b:  ldsfld int32 TestClass::count
	IL_0010:  stloc.1 
	IL_0011:  ldloc.1 
	IL_0012:  ldc.i4.1 
	IL_0013:  add 
	IL_0014:  stloc.1 
	IL_0015:  ldc.i4 200
	IL_001a:  call void class [mscorlib]System.Threading.Thread::Sleep(int32)
	IL_001f:  ldloc.1 
	IL_0020:  stsfld int32 TestClass::count
	IL_0025:  ldloc.0 
	IL_0026:  ldc.i4.s 0x0a
	IL_0028:  blt IL_0007

	IL_002d:  ldstr "count: "
	IL_0032:  ldsflda int32 TestClass::count
	IL_0037:  call instance string int32::ToString()
	IL_003c:  call string string::Concat(string, string)
	IL_0041:  call void class [mscorlib]System.Console::WriteLine(string)
	IL_0046:  ret 
    } // end of method TestClass::syncMethod

    // method line 4
    .method public static  hidebysig 
           default void jumpStart1 ()  cil managed 
    {
        // Method begins at RVA 0x214c
	// Code size 6 (0x6)
	.maxstack 8
	//IL_0000:  call void class TestClass::syncMethod()
	ldftn void class TestClass::syncMethod()
	calli void ()
	ret 
    } // end of method TestClass::jumpStart1

    // method line 5
    .method public static  hidebysig 
           default void jumpStart2 ()  cil managed 
    {
        // Method begins at RVA 0x2154
	// Code size 6 (0x6)
	.maxstack 8
	ldftn void class TestClass::syncMethod()
	calli void ()
	ret
    } // end of method TestClass::jumpStart2

    // method line 6
    .method private static  hidebysig 
           default void Main ()  cil managed 
    {
        // Method begins at RVA 0x215c
	.entrypoint
	// Code size 65 (0x41)
	.maxstack 8
	.locals init (
		class [mscorlib]System.Threading.ThreadStart	V_0,
		class [mscorlib]System.Threading.ThreadStart	V_1,
		class [mscorlib]System.Threading.Thread	V_2,
		class [mscorlib]System.Threading.Thread	V_3)
	IL_0000:  ldnull 
	IL_0001:  ldftn void class TestClass::jumpStart1()
	IL_0007:  newobj instance void class \
[mscorlib]System.Threading.ThreadStart::'.ctor'(object, native int)  IL_000c:  \
stloc.0   IL_000d:  ldnull 
	IL_000e:  ldftn void class TestClass::jumpStart2()
	IL_0014:  newobj instance void class \
[mscorlib]System.Threading.ThreadStart::'.ctor'(object, native int)  IL_0019:  \
stloc.1   IL_001a:  ldloc.0 
	IL_001b:  newobj instance void class \
[mscorlib]System.Threading.Thread::'.ctor'(class \
[mscorlib]System.Threading.ThreadStart)  IL_0020:  stloc.2 
	IL_0021:  ldloc.1 
	IL_0022:  newobj instance void class \
[mscorlib]System.Threading.Thread::'.ctor'(class \
[mscorlib]System.Threading.ThreadStart)  IL_0027:  stloc.3 
	IL_0028:  ldloc.2 
	IL_0029:  callvirt instance void class [mscorlib]System.Threading.Thread::Start()
	IL_002e:  ldloc.3 
	IL_002f:  callvirt instance void class [mscorlib]System.Threading.Thread::Start()
	IL_0034:  ldloc.2 
	IL_0035:  callvirt instance void class [mscorlib]System.Threading.Thread::Join()
	IL_003a:  ldloc.3 
	IL_003b:  callvirt instance void class [mscorlib]System.Threading.Thread::Join()
	IL_0040:  ret 
    } // end of method TestClass::Main

  } // end of class TestClass



_______________________________________________
Mono-devel-list mailing list
Mono-devel-list@lists.ximian.com
http://lists.ximian.com/mailman/listinfo/mono-devel-list


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic