在下面的方法中,我们设置volatile int success = 0
然后输入while(!success)
循环。
循环递增tries
,然后进入一个事务,在该事务中,我们对java sun.misc.Unsafe.putLong
进行调用,并不断循环直到事务成功。
只要设置了调试标志__TRX_DEBUG__
,它将在返回之前打印尝试次数。
由于该数字始终为零,因此我添加了一些“ Hello” printf
。
程序的输出是
你好0 !!
putLong:(Lsun / misc / Unsafe; Ljava / lang / Class; Ljava / lang / Object; JJ)V尝试0次
我非常不明白为什么。
(请在继续投票之前先阅读下面的更多信息。)
/*
* Class: jnirtm_Transactionally
* Method: putLong
* Signature: (Lsun/misc/Unsafe;Ljava/lang/Class;Ljava/lang/Object;JJ)V
*/
jmethodID midPutLong = NULL;
JNIEXPORT void JNICALL Java_jnirtm_Transactionally_putLong__Lsun_misc_Unsafe_2Ljava_lang_Class_2Ljava_lang_Object_2JJ(
JNIEnv *env,
jclass _obsolete,
jobject unsafe,
jclass unsafe_class,
jobject base,
jlong off,
jlong value
){
if(midPutLong == NULL){
midPutLong = (*env)->GetMethodID(env,unsafe_class,"putLong","(Ljava/lang/Object;JJ)V");
#ifdef __TRX_ASSERT__
assert(midPutLong != NULL);
#endif
}
volatile int tries = 0;
volatile int success = 0;
while(!success){/*TODO: maybe switch to a different strategy when tries grows too large?*/
printf("Hello0?!\n");
__asm__ __volatile__ (
"incl %0\n"
"xbegin 1f" /*1f: local label 1, look forward to find first*/
:"+rm"(tries)
:"rm"(success)/*artificial dependency to prevent re-ordering*/
);
/*do we need more artificial dependencies, here, to avoid re-ordering?*/
//unsafe.putInt(base,off,value);
printf("Hello1?!\n");
(*env)-> CallVoidMethod(env,unsafe,midPutLong,base,off,value);
printf("Hello2?!\n");
__asm__ __volatile__ (
"xend\n\t"
"incl %0\n" /*increment success ==> break out of loop*/
"jmp 2f\n" /*jump to end of loop*/
"1:\n" /*local label 1 (jumped to when transaction is aborted)*/
"2:" /*local label 2 (jumped to after a successfully completed transaction)*/
:"+rm"(success)
:"rm"(tries) /*artificial dependency*/
);
}
#ifdef __TRX_DEBUG__
printf("putLong: (Lsun/misc/Unsafe;Ljava/lang/Class;Ljava/lang/Object;JJ)V with %d tries\n",tries);
#endif
}
有趣的是,在文件的更深处,我有另一种方法,
/*
* Class: jnirtm_Transactionally
* Method: putLong
* Signature: (Ljava/lang/Object;Ljava/lang/String;J)V
*/
JNIEXPORT void JNICALL Java_jnirtm_Transactionally_putLong__Ljava_lang_Object_2Ljava_lang_String_2J(JNIEnv* env, jclass _obsolete, jobject target, jstring fieldname, jlong value){
jclass targetClass = (*env)->GetObjectClass(env,target);
const char *str_fname = (*env)->GetStringUTFChars(env,fieldname,NULL);
jfieldID fidFLD = (*env)->GetFieldID(env, targetClass, str_fname, "J");
volatile int tries = 0;
volatile int success = 0;
while(!success){/*TODO: maybe switch to a different strategy when tries grows too large?*/
__asm__ __volatile__ (
"incl %0\n"
"xbegin 1f" /*1f: local label 1, look forward to find first*/
:"+rm"(tries)
:"rm"(success)/*artificial dependency to prevent re-ordering*/
);
/*do we need more artificial dependencies, here, to avoid re-ordering?*/
(*env)->SetLongField(env,targetClass,fidFLD,value);
__asm__ __volatile__ (
"xend\n\t"
"incl %0\n" /*increment success ==> break out of loop*/
"jmp 2f\n" /*jump to end of loop*/
"1:\n" /*local label 1 (jumped to when transaction is aborted)*/
"2:" /*local label 2 (jumped to after a successfully completed transaction)*/
:"+rm"(success)
:"rm"(tries) /*artificial dependency*/
);
}
#ifdef __TRX_DEBUG__
printf("putLong: (Ljava/lang/Object;Ljava/lang/String;J)V with %d tries\n",tries);
#endif
}
基本上是相同的(除了使用不同的方法来更改数据),但是始终输出
putLong:(Ljava / lang / Object; Ljava / lang / String; J)V尝试1次
每个方法每次运行都会被调用一次(从Java):
//requires base class acquisition and field index lookup
Transactionally.putLong(base$x, "x",3L);
assert(data.x == 3);
//requires callback to java which then invokes intrinsics
Transactionally.putLong(Transactionally.unsafe, Transactionally.unsafe_class, base$x, off$x, 4L);
assert(data.x == 4);
而且程序正在运行而不会引发断言错误,这只会增加我的困惑。
因为如果
assert(data.x == 4)
没有抛出错误,则(*env)-> CallVoidMethod(env,unsafe,midPutLong,base,off,value);
第一个C方法必须成功。
但是,它成功执行而没有在开始事务之前执行对
tries
的增量,也没有执行我在其周围插入的两个printf
。更新
将
printf
添加到第二种方法也不会打印它们。因此,我猜想在事务中会抑制IO,并且行为仅针对tries
计数器是不同的。为什么会发生这种情况,如何停止呢?
更新
删除了hello printfs,并且不确定如何直接创建asm代码,因此我反汇编了生成的
.so
文件。放大重要的部分,
这来自工作方法:
while(!success){/*TODO: maybe switch to a different strategy when tries grows too large?*/
867: eb 41 jmp 8aa <Java_jnirtm_Transactionally_putLong__Ljava_lang_Object_2Ljava_lang_String_2J+0xda>
__asm__ __volatile__ (
869: 8b 45 e4 mov -0x1c(%rbp),%eax
86c: 8b 55 e0 mov -0x20(%rbp),%edx
86f: ff c2 inc %edx
871: c7 f8 30 00 00 00 xbeginq 8a7 <Java_jnirtm_Transactionally_putLong__Ljava_lang_Object_2Ljava_lang_String_2J+0xd7>
877: 89 55 e0 mov %edx,-0x20(%rbp)
:"rm"(success)/*artificial dependency to prevent re-ordering*/
);
/*do we need more artificial dependencies, here, to avoid re-ordering?*/
(*env)->SetLongField(env,targetClass,fidFLD,value);
[...]
8aa: 8b 45 e4 mov -0x1c(%rbp),%eax
8ad: 85 c0 test %eax,%eax
8af: 74 b8 je 869 <Java_jnirtm_Transactionally_putLong__Ljava_lang_Object_2Ljava_lang_String_2J+0x99>
这是来自错误的方法:
while(!success){/*TODO: maybe switch to a different strategy when tries grows too large?*/
968: eb 5b jmp 9c5 <Java_jnirtm_Transactionally_putLong__Lsun_misc_Unsafe_2Ljava_lang_Class_2Ljava_lang_Object_2JJ+0xfb>
__asm__ __volatile__ (
96a: 8b 45 fc mov -0x4(%rbp),%eax
96d: 8b 55 f8 mov -0x8(%rbp),%edx
970: ff c2 inc %edx
972: c7 f8 4a 00 00 00 xbeginq 9c2 <Java_jnirtm_Transactionally_putLong__Lsun_misc_Unsafe_2Ljava_lang_Class_2Ljava_lang_Object_2JJ+0xf8>
978: 89 55 f8 mov %edx,-0x8(%rbp)
);
/*do we need more artificial dependencies, here, to avoid re-ordering?*/
//unsafe.putLong(base,off,value);
(*env)-> CallVoidMethod(env,unsafe,midPutLong,base,off,value);
[...]
9c5: 8b 45 fc mov -0x4(%rbp),%eax
9c8: 85 c0 test %eax,%eax
9ca: 74 9e je 96a <Java_jnirtm_Transactionally_putLong__Lsun_misc_Unsafe_2Ljava_lang_Class_2Ljava_lang_Object_2JJ+0xa0>
我仍然看不到任何可以解释这种行为的相关差异。
完整对象
lib/libRTM_transact.so: file format elf64-x86-64
Disassembly of section .init:
0000000000000670 <_init>:
670: 48 83 ec 08 sub $0x8,%rsp
674: 48 8b 05 5d 09 20 00 mov 0x20095d(%rip),%rax # 200fd8 <__gmon_start__>
67b: 48 85 c0 test %rax,%rax
67e: 74 02 je 682 <_init+0x12>
680: ff d0 callq *%rax
682: 48 83 c4 08 add $0x8,%rsp
686: c3 retq
Disassembly of section .plt:
0000000000000690 <.plt>:
690: ff 35 72 09 20 00 pushq 0x200972(%rip) # 201008 <_GLOBAL_OFFSET_TABLE_+0x8>
696: ff 25 74 09 20 00 jmpq *0x200974(%rip) # 201010 <_GLOBAL_OFFSET_TABLE_+0x10>
69c: 0f 1f 40 00 nopl 0x0(%rax)
00000000000006a0 <printf@plt>:
6a0: ff 25 72 09 20 00 jmpq *0x200972(%rip) # 201018 <printf@GLIBC_2.2.5>
6a6: 68 00 00 00 00 pushq $0x0
6ab: e9 e0 ff ff ff jmpq 690 <.plt>
00000000000006b0 <__assert_fail@plt>:
6b0: ff 25 6a 09 20 00 jmpq *0x20096a(%rip) # 201020 <__assert_fail@GLIBC_2.2.5>
6b6: 68 01 00 00 00 pushq $0x1
6bb: e9 d0 ff ff ff jmpq 690 <.plt>
Disassembly of section .plt.got:
00000000000006c0 <.plt.got>:
6c0: ff 25 32 09 20 00 jmpq *0x200932(%rip) # 200ff8 <__cxa_finalize@GLIBC_2.2.5>
6c6: 66 90 xchg %ax,%ax
Disassembly of section .text:
00000000000006d0 <deregister_tm_clones>:
6d0: 48 8d 3d 59 09 20 00 lea 0x200959(%rip),%rdi # 201030 <_edata>
6d7: 48 8d 05 59 09 20 00 lea 0x200959(%rip),%rax # 201037 <_edata+0x7>
6de: 55 push %rbp
6df: 48 29 f8 sub %rdi,%rax
6e2: 48 89 e5 mov %rsp,%rbp
6e5: 48 83 f8 0e cmp $0xe,%rax
6e9: 76 15 jbe 700 <deregister_tm_clones+0x30>
6eb: 48 8b 05 de 08 20 00 mov 0x2008de(%rip),%rax # 200fd0 <_ITM_deregisterTMCloneTable>
6f2: 48 85 c0 test %rax,%rax
6f5: 74 09 je 700 <deregister_tm_clones+0x30>
6f7: 5d pop %rbp
6f8: ff e0 jmpq *%rax
6fa: 66 0f 1f 44 00 00 nopw 0x0(%rax,%rax,1)
700: 5d pop %rbp
701: c3 retq
702: 0f 1f 40 00 nopl 0x0(%rax)
706: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1)
70d: 00 00 00
0000000000000710 <register_tm_clones>:
710: 48 8d 3d 19 09 20 00 lea 0x200919(%rip),%rdi # 201030 <_edata>
717: 48 8d 35 12 09 20 00 lea 0x200912(%rip),%rsi # 201030 <_edata>
71e: 55 push %rbp
71f: 48 29 fe sub %rdi,%rsi
722: 48 89 e5 mov %rsp,%rbp
725: 48 c1 fe 03 sar $0x3,%rsi
729: 48 89 f0 mov %rsi,%rax
72c: 48 c1 e8 3f shr $0x3f,%rax
730: 48 01 c6 add %rax,%rsi
733: 48 d1 fe sar %rsi
736: 74 18 je 750 <register_tm_clones+0x40>
738: 48 8b 05 b1 08 20 00 mov 0x2008b1(%rip),%rax # 200ff0 <_ITM_registerTMCloneTable>
73f: 48 85 c0 test %rax,%rax
742: 74 0c je 750 <register_tm_clones+0x40>
744: 5d pop %rbp
745: ff e0 jmpq *%rax
747: 66 0f 1f 84 00 00 00 nopw 0x0(%rax,%rax,1)
74e: 00 00
750: 5d pop %rbp
751: c3 retq
752: 0f 1f 40 00 nopl 0x0(%rax)
756: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1)
75d: 00 00 00
0000000000000760 <__do_global_dtors_aux>:
760: 80 3d c9 08 20 00 00 cmpb $0x0,0x2008c9(%rip) # 201030 <_edata>
767: 75 27 jne 790 <__do_global_dtors_aux+0x30>
769: 48 83 3d 87 08 20 00 cmpq $0x0,0x200887(%rip) # 200ff8 <__cxa_finalize@GLIBC_2.2.5>
770: 00
771: 55 push %rbp
772: 48 89 e5 mov %rsp,%rbp
775: 74 0c je 783 <__do_global_dtors_aux+0x23>
777: 48 8b 3d aa 08 20 00 mov 0x2008aa(%rip),%rdi # 201028 <__dso_handle>
77e: e8 3d ff ff ff callq 6c0 <.plt.got>
783: e8 48 ff ff ff callq 6d0 <deregister_tm_clones>
788: 5d pop %rbp
789: c6 05 a0 08 20 00 01 movb $0x1,0x2008a0(%rip) # 201030 <_edata>
790: f3 c3 repz retq
792: 0f 1f 40 00 nopl 0x0(%rax)
796: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1)
79d: 00 00 00
00000000000007a0 <frame_dummy>:
7a0: 48 8d 3d 61 06 20 00 lea 0x200661(%rip),%rdi # 200e08 <__JCR_END__>
7a7: 48 83 3f 00 cmpq $0x0,(%rdi)
7ab: 75 0b jne 7b8 <frame_dummy+0x18>
7ad: e9 5e ff ff ff jmpq 710 <register_tm_clones>
7b2: 66 0f 1f 44 00 00 nopw 0x0(%rax,%rax,1)
7b8: 48 8b 05 29 08 20 00 mov 0x200829(%rip),%rax # 200fe8 <_Jv_RegisterClasses>
7bf: 48 85 c0 test %rax,%rax
7c2: 74 e9 je 7ad <frame_dummy+0xd>
7c4: 55 push %rbp
7c5: 48 89 e5 mov %rsp,%rbp
7c8: ff d0 callq *%rax
7ca: 5d pop %rbp
7cb: e9 40 ff ff ff jmpq 710 <register_tm_clones>
00000000000007d0 <Java_jnirtm_Transactionally_putLong__Ljava_lang_Object_2Ljava_lang_String_2J>:
/*
* Class: jnirtm_Transactionally
* Method: putLong
* Signature: (Ljava/lang/Object;Ljava/lang/String;J)V
*/
JNIEXPORT void JNICALL Java_jnirtm_Transactionally_putLong__Ljava_lang_Object_2Ljava_lang_String_2J(JNIEnv* env, jclass _obsolete, jobject target, jstring fieldname, jlong value){
7d0: 55 push %rbp
7d1: 48 89 e5 mov %rsp,%rbp
7d4: 48 83 ec 50 sub $0x50,%rsp
7d8: 48 89 7d d8 mov %rdi,-0x28(%rbp)
7dc: 48 89 75 d0 mov %rsi,-0x30(%rbp)
7e0: 48 89 55 c8 mov %rdx,-0x38(%rbp)
7e4: 48 89 4d c0 mov %rcx,-0x40(%rbp)
7e8: 4c 89 45 b8 mov %r8,-0x48(%rbp)
jclass targetClass = (*env)->GetObjectClass(env,target);
7ec: 48 8b 45 d8 mov -0x28(%rbp),%rax
7f0: 48 8b 00 mov (%rax),%rax
7f3: 48 8b 80 f8 00 00 00 mov 0xf8(%rax),%rax
7fa: 48 8b 4d c8 mov -0x38(%rbp),%rcx
7fe: 48 8b 55 d8 mov -0x28(%rbp),%rdx
802: 48 89 ce mov %rcx,%rsi
805: 48 89 d7 mov %rdx,%rdi
808: ff d0 callq *%rax
80a: 48 89 45 e8 mov %rax,-0x18(%rbp)
const char *str_fname = (*env)->GetStringUTFChars(env,fieldname,NULL);
80e: 48 8b 45 d8 mov -0x28(%rbp),%rax
812: 48 8b 00 mov (%rax),%rax
815: 48 8b 80 48 05 00 00 mov 0x548(%rax),%rax
81c: 48 8b 75 c0 mov -0x40(%rbp),%rsi
820: 48 8b 4d d8 mov -0x28(%rbp),%rcx
824: ba 00 00 00 00 mov $0x0,%edx
829: 48 89 cf mov %rcx,%rdi
82c: ff d0 callq *%rax
82e: 48 89 45 f0 mov %rax,-0x10(%rbp)
jfieldID fidFLD = (*env)->GetFieldID(env, targetClass, str_fname, "J");
832: 48 8b 45 d8 mov -0x28(%rbp),%rax
836: 48 8b 00 mov (%rax),%rax
839: 48 8b 80 f0 02 00 00 mov 0x2f0(%rax),%rax
840: 48 8b 55 f0 mov -0x10(%rbp),%rdx
844: 48 8b 75 e8 mov -0x18(%rbp),%rsi
848: 48 8b 7d d8 mov -0x28(%rbp),%rdi
84c: 48 8d 0d ad 01 00 00 lea 0x1ad(%rip),%rcx # a00 <_fini+0x18>
853: ff d0 callq *%rax
855: 48 89 45 f8 mov %rax,-0x8(%rbp)
volatile int tries = 0;
859: c7 45 e0 00 00 00 00 movl $0x0,-0x20(%rbp)
volatile int success = 0;
860: c7 45 e4 00 00 00 00 movl $0x0,-0x1c(%rbp)
while(!success){/*TODO: maybe switch to a different strategy when tries grows too large?*/
867: eb 41 jmp 8aa <Java_jnirtm_Transactionally_putLong__Ljava_lang_Object_2Ljava_lang_String_2J+0xda>
__asm__ __volatile__ (
869: 8b 45 e4 mov -0x1c(%rbp),%eax
86c: 8b 55 e0 mov -0x20(%rbp),%edx
86f: ff c2 inc %edx
871: c7 f8 30 00 00 00 xbeginq 8a7 <Java_jnirtm_Transactionally_putLong__Ljava_lang_Object_2Ljava_lang_String_2J+0xd7>
877: 89 55 e0 mov %edx,-0x20(%rbp)
:"rm"(success)/*artificial dependency to prevent re-ordering*/
);
/*do we need more artificial dependencies, here, to avoid re-ordering?*/
(*env)->SetLongField(env,targetClass,fidFLD,value);
87a: 48 8b 45 d8 mov -0x28(%rbp),%rax
87e: 48 8b 00 mov (%rax),%rax
881: 48 8b 80 70 03 00 00 mov 0x370(%rax),%rax
888: 48 8b 4d b8 mov -0x48(%rbp),%rcx
88c: 48 8b 55 f8 mov -0x8(%rbp),%rdx
890: 48 8b 75 e8 mov -0x18(%rbp),%rsi
894: 48 8b 7d d8 mov -0x28(%rbp),%rdi
898: ff d0 callq *%rax
__asm__ __volatile__ (
89a: 8b 45 e0 mov -0x20(%rbp),%eax
89d: 8b 55 e4 mov -0x1c(%rbp),%edx
8a0: 0f 01 d5 xend
8a3: ff c2 inc %edx
8a5: eb 00 jmp 8a7 <Java_jnirtm_Transactionally_putLong__Ljava_lang_Object_2Ljava_lang_String_2J+0xd7>
8a7: 89 55 e4 mov %edx,-0x1c(%rbp)
while(!success){/*TODO: maybe switch to a different strategy when tries grows too large?*/
8aa: 8b 45 e4 mov -0x1c(%rbp),%eax
8ad: 85 c0 test %eax,%eax
8af: 74 b8 je 869 <Java_jnirtm_Transactionally_putLong__Ljava_lang_Object_2Ljava_lang_String_2J+0x99>
:"+rm"(success)
:"rm"(tries) /*artificial dependency*/
);
}
#ifdef __TRX_DEBUG__
printf("putLong: (Ljava/lang/Object;Ljava/lang/String;J)V with %d tries\n",tries);
8b1: 8b 45 e0 mov -0x20(%rbp),%eax
8b4: 89 c6 mov %eax,%esi
8b6: 48 8d 3d 4b 01 00 00 lea 0x14b(%rip),%rdi # a08 <_fini+0x20>
8bd: b8 00 00 00 00 mov $0x0,%eax
8c2: e8 d9 fd ff ff callq 6a0 <printf@plt>
#endif
}
8c7: 90 nop
8c8: c9 leaveq
8c9: c3 retq
00000000000008ca <Java_jnirtm_Transactionally_putLong__Lsun_misc_Unsafe_2Ljava_lang_Class_2Ljava_lang_Object_2JJ>:
jobject unsafe,
jclass unsafe_class,
jobject base,
jlong off,
jlong value
){
8ca: 55 push %rbp
8cb: 48 89 e5 mov %rsp,%rbp
8ce: 48 83 ec 40 sub $0x40,%rsp
8d2: 48 89 7d e8 mov %rdi,-0x18(%rbp)
8d6: 48 89 75 e0 mov %rsi,-0x20(%rbp)
8da: 48 89 55 d8 mov %rdx,-0x28(%rbp)
8de: 48 89 4d d0 mov %rcx,-0x30(%rbp)
8e2: 4c 89 45 c8 mov %r8,-0x38(%rbp)
8e6: 4c 89 4d c0 mov %r9,-0x40(%rbp)
if(midPutLong == NULL){
8ea: 48 8b 05 ef 06 20 00 mov 0x2006ef(%rip),%rax # 200fe0 <midPutLong@@Base-0x58>
8f1: 48 8b 00 mov (%rax),%rax
8f4: 48 85 c0 test %rax,%rax
8f7: 75 61 jne 95a <Java_jnirtm_Transactionally_putLong__Lsun_misc_Unsafe_2Ljava_lang_Class_2Ljava_lang_Object_2JJ+0x90>
midPutLong = (*env)->GetMethodID(env,unsafe_class,"putLong","(Ljava/lang/Object;JJ)V");
8f9: 48 8b 45 e8 mov -0x18(%rbp),%rax
8fd: 48 8b 00 mov (%rax),%rax
900: 48 8b 80 08 01 00 00 mov 0x108(%rax),%rax
907: 48 8b 75 d0 mov -0x30(%rbp),%rsi
90b: 48 8b 7d e8 mov -0x18(%rbp),%rdi
90f: 48 8d 0d 33 01 00 00 lea 0x133(%rip),%rcx # a49 <_fini+0x61>
916: 48 8d 15 44 01 00 00 lea 0x144(%rip),%rdx # a61 <_fini+0x79>
91d: ff d0 callq *%rax
91f: 48 89 c2 mov %rax,%rdx
922: 48 8b 05 b7 06 20 00 mov 0x2006b7(%rip),%rax # 200fe0 <midPutLong@@Base-0x58>
929: 48 89 10 mov %rdx,(%rax)
#ifdef __TRX_ASSERT__
assert(midPutLong != NULL);
92c: 48 8b 05 ad 06 20 00 mov 0x2006ad(%rip),%rax # 200fe0 <midPutLong@@Base-0x58>
933: 48 8b 00 mov (%rax),%rax
936: 48 85 c0 test %rax,%rax
939: 75 1f jne 95a <Java_jnirtm_Transactionally_putLong__Lsun_misc_Unsafe_2Ljava_lang_Class_2Ljava_lang_Object_2JJ+0x90>
93b: 48 8d 0d be 01 00 00 lea 0x1be(%rip),%rcx # b00 <__PRETTY_FUNCTION__.3410>
942: ba 43 00 00 00 mov $0x43,%edx
947: 48 8d 35 1b 01 00 00 lea 0x11b(%rip),%rsi # a69 <_fini+0x81>
94e: 48 8d 3d 2d 01 00 00 lea 0x12d(%rip),%rdi # a82 <_fini+0x9a>
955: e8 56 fd ff ff callq 6b0 <__assert_fail@plt>
#endif
}
volatile int tries = 0;
95a: c7 45 f8 00 00 00 00 movl $0x0,-0x8(%rbp)
volatile int success = 0;
961: c7 45 fc 00 00 00 00 movl $0x0,-0x4(%rbp)
while(!success){/*TODO: maybe switch to a different strategy when tries grows too large?*/
968: eb 5b jmp 9c5 <Java_jnirtm_Transactionally_putLong__Lsun_misc_Unsafe_2Ljava_lang_Class_2Ljava_lang_Object_2JJ+0xfb>
__asm__ __volatile__ (
96a: 8b 45 fc mov -0x4(%rbp),%eax
96d: 8b 55 f8 mov -0x8(%rbp),%edx
970: ff c2 inc %edx
972: c7 f8 4a 00 00 00 xbeginq 9c2 <Java_jnirtm_Transactionally_putLong__Lsun_misc_Unsafe_2Ljava_lang_Class_2Ljava_lang_Object_2JJ+0xf8>
978: 89 55 f8 mov %edx,-0x8(%rbp)
);
/*do we need more artificial dependencies, here, to avoid re-ordering?*/
//unsafe.putInt(base,off,value);
(*env)-> CallVoidMethod(env,unsafe,midPutLong,base,off,value);
97b: 48 8b 45 e8 mov -0x18(%rbp),%rax
97f: 48 8b 00 mov (%rax),%rax
982: 4c 8b 90 e8 01 00 00 mov 0x1e8(%rax),%r10
989: 48 8b 05 50 06 20 00 mov 0x200650(%rip),%rax # 200fe0 <midPutLong@@Base-0x58>
990: 48 8b 10 mov (%rax),%rdx
993: 48 8b 7d c0 mov -0x40(%rbp),%rdi
997: 48 8b 4d c8 mov -0x38(%rbp),%rcx
99b: 48 8b 75 d8 mov -0x28(%rbp),%rsi
99f: 48 8b 45 e8 mov -0x18(%rbp),%rax
9a3: 4c 8b 4d 10 mov 0x10(%rbp),%r9
9a7: 49 89 f8 mov %rdi,%r8
9aa: 48 89 c7 mov %rax,%rdi
9ad: b8 00 00 00 00 mov $0x0,%eax
9b2: 41 ff d2 callq *%r10
__asm__ __volatile__ (
9b5: 8b 45 f8 mov -0x8(%rbp),%eax
9b8: 8b 55 fc mov -0x4(%rbp),%edx
9bb: 0f 01 d5 xend
9be: ff c2 inc %edx
9c0: eb 00 jmp 9c2 <Java_jnirtm_Transactionally_putLong__Lsun_misc_Unsafe_2Ljava_lang_Class_2Ljava_lang_Object_2JJ+0xf8>
9c2: 89 55 fc mov %edx,-0x4(%rbp)
while(!success){/*TODO: maybe switch to a different strategy when tries grows too large?*/
9c5: 8b 45 fc mov -0x4(%rbp),%eax
9c8: 85 c0 test %eax,%eax
9ca: 74 9e je 96a <Java_jnirtm_Transactionally_putLong__Lsun_misc_Unsafe_2Ljava_lang_Class_2Ljava_lang_Object_2JJ+0xa0>
:"+rm"(success)
:"rm"(tries) /*artificial dependency*/
);
}
#ifdef __TRX_DEBUG__
printf("putLong: (Lsun/misc/Unsafe;Ljava/lang/Class;Ljava/lang/Object;JJ)V with %d tries\n",tries);
9cc: 8b 45 f8 mov -0x8(%rbp),%eax
9cf: 89 c6 mov %eax,%esi
9d1: 48 8d 3d c0 00 00 00 lea 0xc0(%rip),%rdi # a98 <_fini+0xb0>
9d8: b8 00 00 00 00 mov $0x0,%eax
9dd: e8 be fc ff ff callq 6a0 <printf@plt>
#endif
}
9e2: 90 nop
9e3: c9 leaveq
9e4: c3 retq
Disassembly of section .fini:
00000000000009e8 <_fini>:
9e8: 48 83 ec 08 sub $0x8,%rsp
9ec: 48 83 c4 08 add $0x8,%rsp
9f0: c3 retq
最佳答案
无法在事务中执行任何I / O操作,因此printf
调用可能会中止该事务。然后,控制权传递给1:
标签,这是未定义的行为,因为不允许在asm
语句之间进行跳转,并且修改了eax
而不将其列出在内容管理器或输出列表中。xbegin
的目标必须在同一asm
语句中,或者是使用asm
goto
扩展名引用的C标签。或更好地使用内部函数,并避免内联汇编。
关于java - 程序丢失增量和两个``printf'',我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/47284960/