[Warning] Fiber in tango.core.Thread still bug, dont use it in any scientific calculation

Mikola Lysenko mclysenk at mtu.edu
Fri Dec 7 12:06:47 PST 2007


Have you tried testing this with any examples?  I'm fairly certain that the FPU does actually do what it is supposed to.  If you will notice, the calling convention on the method is extern(C), not extern(D).  As a result, the C calling specification requires that the FPU state is saved before any function call by the caller - not the callee.  As a result, this method should work and moreover save a great deal of time.  Dumping the FPU state is a rather costly operation, and best avoided if possible, which is why the C calling convention works this way.

If you can find code that breaks with the current Tango fiber implementation, I'd be happy to make the necessary changes.

-Mik


Swer Wrote:

> Any float point calculation in both main Fiber/slave Fiber will
> cause uncertain result, unless your CPU is 386sx with FP emu clib.
> 
> This bug exsits on both Win32 and x86 Linux Tango lib. Please dont
> use Fiber class unless you are sure there no any float point
> calculation in you program and in ALL api/lib you imported.
> 
> Thread.d firber context switch bug, there is no FP register
> save/restore. EBX ESI EDI EBP ESP IP FS only. this code is unsafe!
> 
> ==========CUT from tango/core/Thread.d line:2369-2405=======
>         version( AsmX86_Win32 )
>         {
>             asm
>             {
>                 naked;
> 
>                 // save current stack state
>                 push EBP;
>                 mov  EBP, ESP;
>                 push EAX;
>                 push dword ptr FS:[0];
>                 push dword ptr FS:[4];
>                 push dword ptr FS:[8];
>                 push EBX;
>                 push ESI;
>                 push EDI;
> 
>                 // store oldp again with more accurate address
>                 mov EAX, dword ptr 8[EBP];
>                 mov [EAX], ESP;
>                 // load newp to begin context switch
>                 mov ESP, dword ptr 12[EBP];
> 
>                 // load saved state from new stack
>                 pop EDI;
>                 pop ESI;
>                 pop EBX;
>                 pop dword ptr FS:[8];
>                 pop dword ptr FS:[4];
>                 pop dword ptr FS:[0];
>                 pop EAX;
>                 pop EBP;
> 
>                 // 'return' to complete switch
>                 ret;
>             }
>         }
> ===============CUT END====================
> 
> 
> GNU glibc2.7 swapcontext.S code is safe
> ===============CUT===================
> ENTRY(__swapcontext)
>  /* Load address of the context data structure we save in.  */
>  movl 4(%esp), %eax
> 
>  /* Return value of swapcontext.  EAX is the only register whose
>     value is not preserved.  */
>  movl $0, oEAX(%eax)
> 
>  /* Save the 32-bit register values and the return address.  */
>  movl %ecx, oECX(%eax)
>  movl %edx, oEDX(%eax)
>  movl %edi, oEDI(%eax)
>  movl %esi, oESI(%eax)
>  movl %ebp, oEBP(%eax)
>  movl (%esp), %ecx
>  movl %ecx, oEIP(%eax)
>  leal 4(%esp), %ecx
>  movl %ecx, oESP(%eax)
>  movl %ebx, oEBX(%eax)
> 
>  /* Save the FS segment register.  */
>  xorl %edx, %edx
>  movw %fs, %dx
>  movl %edx, oFS(%eax)
> 
>  /* We have separate floating-point register content memory on the
>     stack.  We use the __fpregs_mem block in the context.  Set the
>     links up correctly.  */
>  leal oFPREGSMEM(%eax), %ecx
>  movl %ecx, oFPREGS(%eax)
>  /* Save the floating-point context.  */
>  fnstenv (%ecx)
> 
>  /* Load address of the context data structure we have to load.  */
>  movl 8(%esp), %ecx
> 
>  /* Save the current signal mask and install the new one.  */
>  pushl %ebx
>  leal oSIGMASK(%eax), %edx
>  leal oSIGMASK(%ecx), %ecx
>  movl $SIG_SETMASK, %ebx
>  movl $__NR_sigprocmask, %eax
>  ENTER_KERNEL
>  popl %ebx
>  cmpl $-4095, %eax  /* Check %eax for error.  */
>  jae SYSCALL_ERROR_LABEL /* Jump to error handler if error.  */
> 
>  /* EAX was modified, reload it.  */
>  movl 8(%esp), %eax
> 
>  /* Restore the floating-point context.  Not the registers, only the
>     rest.  */
>  movl oFPREGS(%eax), %ecx
>  fldenv (%ecx)
> 
>  /* Restore the FS segment register.  We don't touch the GS register
>     since it is used for threads.  */
>  movl oFS(%eax), %edx
>  movw %dx, %fs
> 
>  /* Fetch the address to return to.  */
>  movl oEIP(%eax), %ecx
> 
>  /* Load the new stack pointer.  */
>  movl oESP(%eax), %esp
> 
>  /* Push the return address on the new stack so we can return there.  */
>  pushl %ecx
> 
>  /* Load the values of all the 32-bit registers (except ESP).
>     Since we are loading from EAX, it must be last.  */
>  movl oEDI(%eax), %edi
>  movl oESI(%eax), %esi
>  movl oEBP(%eax), %ebp
>  movl oEBX(%eax), %ebx
>  movl oEDX(%eax), %edx
>  movl oECX(%eax), %ecx
>  movl oEAX(%eax), %eax
> 
>  /* The following 'ret' will pop the address of the code and jump
>     to it.  */
> 
> L(pseudo_end):
>  ret
> PSEUDO_END(__swapcontext)
> =============CUT END=================
> 
> 
> Microsoft Windows Server 2003 SwitchToFiber code also safe.
> ===========Kernel32.dll SwitchToFiber==============
> 7C821804 k>/$  64:8B15 18000000  mov edx,dword ptr fs:[18]
> 7C82180B   |.  8B42 10           mov eax,dword ptr ds:[edx+10]
> 7C82180E   |.  8998 B8000000     mov dword ptr ds:[eax+B8],ebx
> 7C821814   |.  89B8 B0000000     mov dword ptr ds:[eax+B0],edi
> 7C82181A   |.  89B0 B4000000     mov dword ptr ds:[eax+B4],esi
> 7C821820   |.  89A8 C8000000     mov dword ptr ds:[eax+C8],ebp
> 7C821826   |.  8178 14 0F000100  cmp dword ptr ds:[eax+14],1000F
> 7C82182D   |.  75 14             jnz short kernel32.7C821843
> 7C82182F   |.  9B                wait
> 7C821830   |.  DD78 34           fstsw word ptr ds:[eax+34]
> 7C821833   |.  D978 30           fstcw word ptr ds:[eax+30]
> 7C821836   |.  803D 7A02FE7F 01  cmp byte ptr ds:[7FFE027A],1
> 7C82183D   |.  75 04             jnz short kernel32.7C821843
> 7C82183F   |.  0FAE58 28         stmxcsr dword ptr ds:[eax+28]
> 7C821843   |>  89A0 D8000000     mov dword ptr ds:[eax+D8],esp
> 7C821849   |.  8B8A B40F0000     mov ecx,dword ptr ds:[edx+FB4]
> 7C82184F   |.  8988 E8020000     mov dword ptr ds:[eax+2E8],ecx
> 7C821855   |.  8B8A A8010000     mov ecx,dword ptr ds:[edx+1A8]
> 7C82185B   |.  8988 E4020000     mov dword ptr ds:[eax+2E4],ecx
> 7C821861   |.  8B0A              mov ecx,dword ptr ds:[edx]
> 7C821863   |.  8B5A 08           mov ebx,dword ptr ds:[edx+8]
> 7C821866   |.  8BB2 780F0000     mov esi,dword ptr ds:[edx+F78]
> 7C82186C   |.  8948 04           mov dword ptr ds:[eax+4],ecx
> 7C82186F   |.  8958 0C           mov dword ptr ds:[eax+C],ebx
> 7C821872   |.  89B0 EC020000     mov dword ptr ds:[eax+2EC],esi
> 7C821878   |.  8B4C24 04         mov ecx,dword ptr ss:[esp+4]
> 7C82187C   |.  894A 10           mov dword ptr ds:[edx+10],ecx
> 7C82187F   |.  8B71 04           mov esi,dword ptr ds:[ecx+4]
> 7C821882   |.  8B59 08           mov ebx,dword ptr ds:[ecx+8]
> 7C821885   |.  8932              mov dword ptr ds:[edx],esi
> 7C821887   |.  895A 04           mov dword ptr ds:[edx+4],ebx
> 7C82188A   |.  8B71 0C           mov esi,dword ptr ds:[ecx+C]
> 7C82188D   |.  8B59 10           mov ebx,dword ptr ds:[ecx+10]
> 7C821890   |.  8BB9 EC020000     mov edi,dword ptr ds:[ecx+2EC]
> 7C821896   |.  8972 08           mov dword ptr ds:[edx+8],esi
> 7C821899   |.  899A 0C0E0000     mov dword ptr ds:[edx+E0C],ebx
> 7C82189F   |.  89BA 780F0000     mov dword ptr ds:[edx+F78],edi
> 7C8218A5   |.  8BB1 E4020000     mov esi,dword ptr ds:[ecx+2E4]
> 7C8218AB   |.  89B2 A8010000     mov dword ptr ds:[edx+1A8],esi
> 7C8218B1   |.  8179 14 0F000100  cmp dword ptr ds:[ecx+14],1000F
> 7C8218B8   |.  75 28             jnz short kernel32.7C8218E2
> 7C8218BA   |.  8B58 34           mov ebx,dword ptr ds:[eax+34]
> 7C8218BD   |.  66:3B59 34        cmp bx,word ptr ds:[ecx+34]
> 7C8218C1   |.  75 09             jnz short kernel32.7C8218CC
> 7C8218C3   |.  8B58 30           mov ebx,dword ptr ds:[eax+30]
> 7C8218C6   |.  66:3B59 30        cmp bx,word ptr ds:[ecx+30]
> 7C8218CA   |.  74 09             je short kernel32.7C8218D5
> 7C8218CC   |>  66:C741 38 FFFF   mov word ptr ds:[ecx+38],0FFFF
> 7C8218D2   |.  D961 30           fldenv (28-byte) ptr ds:[ecx+30]
> 7C8218D5   |>  803D 7A02FE7F 01  cmp byte ptr ds:[7FFE027A],1
> 7C8218DC   |.  75 04             jnz short kernel32.7C8218E2
> 7C8218DE   |.  0FAE51 28         ldmxcsr dword ptr ds:[ecx+28]
> 7C8218E2   |>  8BB9 B0000000     mov edi,dword ptr ds:[ecx+B0]
> 7C8218E8   |.  8BB1 B4000000     mov esi,dword ptr ds:[ecx+B4]
> 7C8218EE   |.  8BA9 C8000000     mov ebp,dword ptr ds:[ecx+C8]
> 7C8218F4   |.  8B99 B8000000     mov ebx,dword ptr ds:[ecx+B8]
> 7C8218FA   |.  8B81 E8020000     mov eax,dword ptr ds:[ecx+2E8]
> 7C821900   |.  8982 B40F0000     mov dword ptr ds:[edx+FB4],eax
> 7C821906   |.  8BA1 D8000000     mov esp,dword ptr ds:[ecx+D8]
> 7C82190C   \.  C2 0400           retn 4
> ===============CUT END=====================
> 
> Hope this bug fix fast because tango is my standard lib.
> 
> 




More information about the Digitalmars-d mailing list