Changeset 2289


Ignore:
Timestamp:
Aug 21, 2005, 12:08:50 AM (20 years ago)
Author:
bird
Message:

o Protect the fork operations by the means of must complete so

signals won't interrupt us till we're finished. This might leave
unkillable processes around if fork goes highwire.

o Better exception logging during fork.
o Use MMX memcpy in fork (if supported).
o The C function libc_Back_processFork() replaces the pure assembly fork().

Location:
trunk/src/emx
Files:
1 deleted
13 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/emx/ChangeLog.LIBC

    • Property cvs2svn:cvs-rev changed from 1.118 to 1.119
    r2288 r2289  
    552005-08-20: knut st. osmundsen <bird-gccos2-spam@anduin.net>
    66    - libc:
     7        o Define _EMX_SOURCE (__USE_EMX) along with _BSD_SOURCE and _SVID_SOURCE as
     8          defaults in features.h.
     9        o Protect the fork operations by the means of must complete so
     10          signals won't interrupt us till we're finished. This might leave
     11          unkillable processes around if fork goes highwire.
     12        o Better exception logging during fork.
     13        o Use MMX memcpy in fork (if supported).
     14        o The C function __libc_Back_processFork() replaces the pure assembly __fork().
    715        o Added _memcpy_amd.
     16        o Fixed some logging statements in sharedpm.c.
    817        o Log __fmutex_release_internal_must_complete.
    918        o Corrected a few prototypes in process.h to use pid_t.
  • trunk/src/emx/include/InnoTekLIBC/backend.h

    • Property cvs2svn:cvs-rev changed from 1.28 to 1.29
    r2288 r2289  
    767767
    768768/**
     769 * Fork a child process pretty much identical to the calling process.
     770 * See SuS for full description of what fork() does and doesn't.
     771 *
     772 * @returns 0 in the child process.
     773 * @returns process identifier of the new child in the parent process. (positive, non-zero)
     774 * @returns Negative error code (errno.h) on failure.
     775 */
     776pid_t __libc_Back_processFork(void);
     777
     778/**
    769779 * Waits/polls for on one or more processes to change it's running status.
    770780 *
  • trunk/src/emx/include/InnoTekLIBC/fork.h

    • Property cvs2svn:cvs-rev changed from 1.3 to 1.4
    r2288 r2289  
    3434
    3535/** Current fork version. */
    36 #define __LIBC_FORK_VERSION             0x00010000
     36#define __LIBC_FORK_VERSION             0x00020000
     37
     38/** Current fork module version. */
     39#define __LIBC_FORK_MODULE_VERSION      0x00010000
    3740
    3841/** Timeout on waiting semaphore in fork operations */
     
    272275typedef struct __libc_ForkHandle
    273276{
    274     /** Fork version. */
     277    /** Fork version (__LIBC_FORK_VERSION). */
    275278    unsigned                uVersion;
    276279    /** Parent process, i.e. the one which have called fork(). */
     
    422425     * the front. */
    423426    __LIBC_PFORKCOMPLETIONCALLBACK  papfnCompletionCallbacks;
     427    /** Index of the next completion callback for the parent. */
     428    volatile unsigned       iCompletionCallbackParent;
     429    /** Index of the next completion callback for the child. */
     430    volatile unsigned       iCompletionCallbackChild;
    424431
    425432    /** Pointer to the start of the fork buffer. */
     
    538545typedef struct __libc_ForkModule
    539546{
    540     /** Fork version. */
     547    /** Fork module version (__LIBC_FORK_MODULE_VERSION). */
    541548    unsigned                    uVersion;
    542549    /** Fork callback function.
  • trunk/src/emx/include/emx/asm386.h

    • Property cvs2svn:cvs-rev changed from 1.10 to 1.11
    r2288 r2289  
    4040
    4141#define ALIGN   .align  4, 0x90
     42#define ALIGNP2(a) .align  a, 0x90
    4243
    4344#define SET_ERRNO_CONST(x) \
  • trunk/src/emx/include/sys/errno.h

    • Property cvs2svn:cvs-rev changed from 1.10 to 1.11
    r2288 r2289  
    194194#endif /* _POSIX_SOURCE */
    195195
     196#ifdef __USE_EMX
     197#define ENEWVER         90              /* mixing with a new version of a struct */
     198#define EBADVER         91              /* bad version number */
     199#endif
     200
    196201#ifdef _KERNEL
    197202/* pseudo-errors returned inside kernel to modify return to process */
  • trunk/src/emx/include/sys/process.h

    • Property cvs2svn:cvs-rev changed from 1.5 to 1.6
    r2288 r2289  
    77#define _SYS_PROCESS_H
    88
    9 #if defined (__cplusplus)
    10 extern "C" {
     9#include <sys/cdefs.h>
     10#include <sys/_types.h>
     11
     12__BEGIN_DECLS
     13
     14#if !defined(_PID_T_DECLARED) && !defined(_PID_T)
     15typedef __pid_t pid_t;
     16#define _PID_T_DECLARED
     17#define _PID_T
    1118#endif
    1219
     
    5158void exit (int) __attribute__ ((__noreturn__));
    5259void _exit (int) __attribute__ ((__noreturn__));
    53 int fork (void);
    54 int getpid (void);
    55 int getppid (void);
     60pid_t fork (void);
     61pid_t getpid (void);
     62pid_t getppid (void);
    5663int spawnl (int, __const__ char *, __const__ char *, ...);
    5764int spawnle (int, __const__ char *, __const__ char *, ...);
     
    6370int spawnvpe (int, __const__ char *, char * __const__ *, char * __const__ *);
    6471int system (__const__ char *);
    65 int wait (int *);
    66 int waitpid (int, int *, int);
     72pid_t wait (int *);
     73pid_t waitpid (pid_t, int *, int);
    6774
    6875int _execl (__const__ char *, __const__ char *, ...);
     
    7582int _execvpe (__const__ char *, char * __const__ *, char * __const__ *);
    7683int _fork (void);
    77 int _getpid (void);
    78 int _getppid (void);
     84pid_t _getpid (void);
     85pid_t _getppid (void);
    7986int _spawnl (int, __const__ char *, __const__ char *, ...);
    8087int _spawnle (int, __const__ char *, __const__ char *, ...);
     
    8592int _spawnvp (int, __const__ char *, char * __const__ *);
    8693int _spawnvpe (int, __const__ char *, char * __const__ *, char * __const__ *);
    87 int _wait (int *);
    88 int _waitpid (int, int *, int);
     94pid_t _wait (int *);
     95pid_t _waitpid (pid_t, int *, int);
    8996
    90 
    91 #if defined (__cplusplus)
    92 }
    93 #endif
     97__END_DECLS
    9498
    9599#endif /* not _SYS_PROCESS_H */
  • trunk/src/emx/src/lib/libc.def

    • Property cvs2svn:cvs-rev changed from 1.135 to 1.136
    r2288 r2289  
    236236    "___fmutex_request_internal" @249
    237237    "___fmutex_request_internal_must_complete" @250
    238     "___fork" @251
     238    "___libc_Back_processFork" @251
    239239    ;msun - dead "___fpclassify" @252
    240240    ;msun - dead "___fpclassifyf" @253
     
    19431943    "___libc_LogError" @1941
    19441944    "___libc_LogErrorLeave" @1942
     1945    "__memcpy_amd" @1943
  • trunk/src/emx/src/lib/libc06b4.def

    • Property cvs2svn:cvs-rev changed from 1.12 to 1.13
    r2288 r2289  
    234234    "___fmutex_request_internal" @249
    235235    "___fmutex_request_internal_must_complete" @250
    236     "___fork" @251
     236    "___libc_Back_processFork" @251
    237237    "___fpclassify" = ___nullstub_function @252
    238238    "___fpclassifyf" = ___nullstub_function @253
  • trunk/src/emx/src/lib/libc06b5.def

    • Property cvs2svn:cvs-rev changed from 1.6 to 1.7
    r2288 r2289  
    237237    "___fmutex_request_internal" @249
    238238    "___fmutex_request_internal_must_complete" @250
    239     "___fork" @251
     239    "___libc_Back_processFork" @251
    240240    ;msun - dead "___fpclassify" @252
    241241    ;msun - dead "___fpclassifyf" @253
  • trunk/src/emx/src/lib/process/fork.c

    • Property cvs2svn:cvs-rev changed from 1.8 to 1.9
    r2288 r2289  
    1 /* fork.c (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes */
     1/* $Id: $ */
     2/** @file
     3 *
     4 * LIBC fork().
     5 *
     6 * Copyright (c) 2004-2005 knut st. osmundsen <bird@anduin.net>
     7 *
     8 *
     9 * This file is part of InnoTek LIBC.
     10 *
     11 * InnoTek LIBC is free software; you can redistribute it and/or modify
     12 * it under the terms of the GNU General Public License as published by
     13 * the Free Software Foundation; either version 2 of the License, or
     14 * (at your option) any later version.
     15 *
     16 * InnoTek LIBC is distributed in the hope that it will be useful,
     17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     19 * GNU General Public License for more details.
     20 *
     21 * You should have received a copy of the GNU General Public License
     22 * along with InnoTek LIBC; if not, write to the Free Software
     23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
     24 *
     25 */
    226
     27
     28/*******************************************************************************
     29*   Header Files                                                               *
     30*******************************************************************************/
    331#include "libc-alias.h"
    432#include <process.h>
    5 #include <emx/syscalls.h>
     33#include <unistd.h>
     34#include <errno.h>
     35#include <InnoTekLIBC/backend.h>
    636#define __LIBC_LOG_GROUP __LIBC_LOG_GRP_FORK
    737#include <InnoTekLIBC/logstrict.h>
    838
    9 int _STD(fork)(void)
     39
     40/**
     41 * Fork of a child process.
     42 *
     43 * @returns 0 in the child process.
     44 * @returns process identifier of the new child in the parent process. (positive, non-zero)
     45 * @returns -1 and errno on failure.
     46 */
     47pid_t _STD(fork)(void)
    1048{
    1149    LIBCLOG_ENTER("\n");
    12     int pid = __fork();
     50    pid_t pid = __libc_Back_processFork();
    1351    if (pid >= 0)
    1452        LIBCLOG_RETURN_INT(pid);
    15     LIBCLOG_ERROR_RETURN_INT(pid);
     53    errno = -pid;
     54    LIBCLOG_ERROR_RETURN_INT(-1);
    1655}
    1756
  • trunk/src/emx/src/lib/startup/386/crt0.s

    • Property cvs2svn:cvs-rev changed from 1.13 to 1.14
    r2288 r2289  
    109109
    110110ForkModule:
    111     .long  0x00010000                   // uVersion
     111    .long  0x00010000                   // uVersion (__LIBC_FORK_MODULE_VERSION)
    112112    .long  __atfork_callback            // pfnAtFork
    113113    .long  ___fork_parent1__            // papParent1
  • trunk/src/emx/src/lib/startup/386/dll0.s

    • Property cvs2svn:cvs-rev changed from 1.16 to 1.17
    r2288 r2289  
    120120
    121121ForkModule:
    122     .long  0x00010000                   // uVersion
     122    .long  0x00010000                   // uVersion (__LIBC_FORK_MODULE_VERSION)
    123123    .long  __atfork_callback            // pfnAtFork
    124124    .long  ___fork_parent1__            // papParent1
  • trunk/src/emx/src/lib/sys/libcfork.c

    • Property cvs2svn:cvs-rev changed from 1.15 to 1.16
    r2288 r2289  
    22/** @file
    33 *
    4  * LIBC Fork.
    5  *
    6  * Copyright (c) 2004 knut st. osmundsen <bird-srcspam@anduin.net>
     4 * LIBC SYS Backend fork().
     5 *
     6 * Copyright (c) 2004-2005 knut st. osmundsen <bird-srcspam@anduin.net>
    77 *
    88 *
     
    9292} __LIBC_FORKXCPTREGREC, *__LIBC_PFORKXCPTREGREC;
    9393
    94 
    95 /*******************************************************************************
    96 *   Global Variables                                                           *
    97 *******************************************************************************/
    98 /** Pointer to the forkhandle for the current fork operation.
    99  * This is *only* used by the exception and signal handlers! */
    100 static volatile __LIBC_PFORKHANDLE g_pForkHandle = NULL;
     94/**
     95 * 80-bit MMX/FPU register type.
     96 */
     97typedef struct X86FPUMMX
     98{
     99    uint8_t reg[10];
     100} X86FPUMMX;
     101/** Pointer to 80-bit MMX/FPU register type. */
     102typedef X86FPUMMX *PX86FPUMMX;
     103
     104/**
     105 * FPU Extended state (aka FXSAVE/FXRSTORE Memory Region).
     106 */
     107#pragma pack(1)
     108typedef struct X86FXSTATE
     109{
     110    /** Control word. */
     111    uint16_t    FCW;
     112    /** Status word. */
     113    uint16_t    FSW;
     114    /** Tag word (it's a byte actually). */
     115    uint8_t     FTW;
     116    uint8_t     huh1;
     117    /** Opcode. */
     118    uint16_t    FOP;
     119    /** Instruction pointer. */
     120    uint32_t    FPUIP;
     121    /** Code selector. */
     122    uint16_t    CS;
     123    uint16_t    Rsvrd1;
     124    /* - offset 16 - */
     125    /** Data pointer. */
     126    uint32_t    FPUDP;
     127    /** Data segment */
     128    uint16_t    DS;
     129    uint16_t    Rsrvd2;
     130    uint32_t    MXCSR;
     131    uint32_t    MXCSR_MASK;
     132    /* - offset 32 - */
     133    union
     134    {
     135        /** MMX view. */
     136        uint64_t    mmx;
     137        /** FPU view - todo. */
     138        X86FPUMMX   fpu;
     139        /** 8-bit view. */
     140        uint8_t     au8[16];
     141        /** 16-bit view. */
     142        uint16_t    au16[8];
     143        /** 32-bit view. */
     144        uint32_t    au32[4];
     145        /** 64-bit view. */
     146        uint64_t    au64[2];
     147    } aRegs[8];
     148    /* - offset 160 - */
     149    union
     150    {
     151        /** 8-bit view. */
     152        uint8_t     au8[16];
     153        /** 16-bit view. */
     154        uint16_t    au16[8];
     155        /** 32-bit view. */
     156        uint32_t    au32[4];
     157        /** 64-bit view. */
     158        uint64_t    au64[2];
     159    } aXMM[8];
     160    /* - offset 288 - */
     161    uint32_t    au32RsrvdRest[(512 - 288) / sizeof(uint32_t)];
     162} X86FXSTATE;
     163#pragma pack()
     164/** Pointer to FPU Extended state. */
     165typedef X86FXSTATE  *PX86FXSTATE;
    101166
    102167
     
    115180 * In the 2nd section they are ordered by what they do.
    116181 */
    117 /* public */
    118 int __libc_fork(void *pvForkRet, void *pvStackRet);
    119182/* sequential */
     183static int                  forkParDo(void *pvForkRet, void *pvStackRet, __LIBC_PFORKXCPTREGREC pXcptRegRec);
    120184static int                  forkParCanFork(__LIBC_PFORKMODULE pModules);
     185static int                  forkParValidateModules(__LIBC_PFORKMODULE pModules);
    121186static __LIBC_PFORKHANDLE   forkParAllocHandle(__LIBC_PFORKMODULE pModules, void *pvStackRet, void *pvForkRet);
    122187static int                  forkParRunPreExecParent(__LIBC_PFORKHANDLE pForkHandle, __LIBC_PFORKMODULE pModules);
     
    131196static void                 forkChlCompletionChild(__LIBC_PFORKHANDLE pForkHandle, int rc);
    132197static void                 forkParCompletionParent(__LIBC_PFORKHANDLE pForkHandle, int rc);
    133 static void                 forkBothCompletion(__LIBC_PFORKHANDLE pForkHandle, int rc, __LIBC_FORKCTX enmCtx);
     198static void                 forkBothCompletion(__LIBC_PFORKHANDLE pForkHandle, int rc, __LIBC_FORKCTX enmCtx, unsigned volatile *piCompletionCallback);
    134199static void                 forkBthCloseHandle(__LIBC_PFORKHANDLE pForkHandle, __LIBC_FORKCTX enmContext);
    135200/* any time */
     
    150215static int                  forkBthBufferSpace(__LIBC_PFORKHANDLE pForkHandle, size_t cb);
    151216static int                  forkBthBufferGiveWaitNext(__LIBC_PFORKHANDLE pForkHandle, __LIBC_FORKCTX enmCtx);
    152 static void                 forkBthCopyPages(void *pvTrg, const void *pvSrc, size_t cb);
     217static void                 forkBthCopyPagesDetect(void *pvDst, const void *pvSrc, size_t cb);
     218static void                 forkBthCopyPagesPlain(void *pvDst, const void *pvSrc, size_t cb);
     219static void                 forkBthCopyPagesMMX(void *pvDst, const void *pvSrc, size_t cb);
     220#if 0
     221static void                 forkBthCopyPagesMMXNonTemporal(void *pvDst, const void *pvSrc, size_t cb);
     222static void                 forkBthCopyPagesSSE2(void *pvDst, const void *pvSrc, size_t cb);
     223#endif
    153224static void                 forkBthCallbacksSort(__LIBC_PFORKCALLBACK *papCallbacks);
    154225static int                  forkBthCallbacksCompare(const void *pv1, const void *pv2);
     
    165236                                                    PVOID                        pvWhatEver);
    166237
     238/*******************************************************************************
     239*   Global Variables                                                           *
     240*******************************************************************************/
     241/** Pointer to the page copy function. */
     242static void                (*pfnForkBthCopyPages)(void *pvDst, const void *pvSrc, size_t cb) = forkBthCopyPagesDetect;
     243/** Pointer to the forkhandle for the current fork operation.
     244 * This is *only* used by the exception and signal handlers! */
     245static volatile __LIBC_PFORKHANDLE g_pForkHandle = NULL;
    167246
    168247
     
    224303int __libc_ForkRegisterModule(__LIBC_PFORKMODULE pModule, int fExecutable)
    225304{
    226     LIBCLOG_ENTER("pModule=%p fExecutable=%d\n", (void *)pModule, fExecutable);
     305    LIBCLOG_ENTER("pModule=%p:{.uVersion=%#x, .pfnAtFork=%p, .papParent1=%p, .papChild1=%p, .pvDataSegBase=%p, .pvDataSegEnd=%p, .fFlags=%#x, .pNext=%p} fExecutable=%d\n",
     306                  (void *)pModule, pModule->uVersion, (void *)pModule->pfnAtFork, (void *)pModule->papParent1, (void *)pModule->papChild1,
     307                  (void *)pModule->pvDataSegBase, (void *)pModule->pvDataSegEnd, pModule->fFlags, (void *)pModule->pNext, fExecutable);
    227308    int                 rc;
    228309    __LIBC_PSPMPROCESS  pProcess;
     
    356437
    357438/**
    358  * This is the function called by __fork() after registers
    359  * have been saved on the stack.
     439 * Checks if the current CPU supports CPUID.
     440 *
     441 * @returns 1 if CPUID is supported, 0 if it doesn't.
     442 */
     443static inline int HasCpuId(void)
     444{
     445    int         fRet = 0;
     446    uint32_t    u1;
     447    uint32_t    u2;
     448    __asm__ ("pushf\n\t"
     449             "pop   %1\n\t"
     450             "mov   %1, %2\n\t"
     451             "xorl  $0x200000, %1\n\t"
     452             "push  %1\n\t"
     453             "popf\n\t"
     454             "pushf\n\t"
     455             "pop   %1\n\t"
     456             "cmpl  %1, %2\n\t"
     457             "setne %0\n\t"
     458             "push  %2\n\t"
     459             "popf\n\t"
     460             : "=m" (fRet), "=r" (u1), "=r" (u2));
     461    return fRet;
     462}
     463
     464
     465/**
     466 * Performs the cpuid instruction returning edx.
     467 *
     468 * @param   uOperator   CPUID operation (eax).
     469 * @returns EDX after cpuid operation.
     470 */
     471static inline uint32_t CpuIdEDX(unsigned uOperator)
     472{
     473    uint32_t    u32EDX;
     474    __asm__ ("cpuid"
     475             : "=a" (uOperator),
     476               "=d" (u32EDX)
     477             : "0" (uOperator)
     478             : "ebx", "ecx");
     479    return u32EDX;
     480}
     481
     482
     483/**
     484 * Fork a child process pretty much identical to the calling process.
     485 * See SuS for full description of what fork() does and doesn't.
     486 *
     487 * @returns 0 in the child process.
     488 * @returns process identifier of the new child in the parent process. (positive, non-zero)
     489 * @returns Negative error code (errno.h) on failure.
     490 */
     491pid_t __libc_Back_processFork(void)
     492{
     493    LIBCLOG_ENTER("__libc_Back_processFork:\n");
     494
     495    /*
     496     * Determin fxsave/fxrstor support.
     497     */
     498    static int fHaveFXSR = -1;
     499    if (fHaveFXSR == -1)
     500        fHaveFXSR = HasCpuId() && (CpuIdEDX(1) & 0x1000000); /* bit 24 - fxsr */
     501
     502    /*
     503     * Save the FPU state
     504     */
     505    PX86FXSTATE pFPU = (PX86FXSTATE)alloca(512 + 16);
     506    pFPU = (PX86FXSTATE)(((uintptr_t)pFPU + 15) & ~15);
     507    if (fHaveFXSR)
     508        __asm__ __volatile__ ("fxsave %0" : "=m" (*pFPU));
     509    else
     510        __asm__ __volatile__ ("fnsave %0" : "=m" (*pFPU));
     511
     512    /*
     513     * Take the Exec Semaphore.
     514     */
     515    int rc = _fmutex_request(&__libc_gmtxExec, 0);
     516    if (rc)
     517    {
     518        rc = -__libc_native2errno(rc);
     519        LIBCLOG_ERROR_RETURN_INT(rc);
     520    }
     521
     522    /*
     523     * Install exception handler, enter must complete section (pretending we're in the kernel).
     524     */
     525    g_pForkHandle = NULL;               /* exception handler variable */
     526
     527    PTIB  pTib = NULL;
     528    PPIB  pPib;
     529    FS_VAR_SAVE_LOAD();
     530    DosGetInfoBlocks(&pTib, &pPib);
     531    __LIBC_FORKXCPTREGREC XcptRegRec;
     532    XcptRegRec.fDoneCompletion       = 0;
     533    XcptRegRec.Core.ExceptionHandler = forkParExceptionHandler;
     534    XcptRegRec.Core.prev_structure   = pTib->tib_pexchain;
     535    pTib->tib_pexchain = &XcptRegRec.Core;
     536
     537    ULONG cNesting = 0;
     538    DosEnterMustComplete(&cNesting);
     539
     540    /*
     541     * Save registers.
     542     */
     543    pid_t pid = -1;
     544    __asm__ __volatile__ (
     545        "pushf\n\t"
     546        "pushl   %%ebx\n\t"
     547        "pushl   %%esi\n\t"
     548        "pushl   %%edi\n\t"
     549        "pushl   %%ebp\n\t"
     550        "pushl   %%gs\n\t"
     551
     552    /*
     553     * Call the fork worker, forkParDo().
     554     */
     555        "movl    %%esp, %%eax\n\t"
     556        "pushl   %%edx\n\t"
     557        "pushl   %%eax\n\t"
     558        "pushl   $fork_ret\n\t"
     559        "call    _forkParDo\n\t"
     560        "addl    $12, %%esp\n\t"         /* __cdecl */
     561        "jmp     fork_skip_regs\n\t"
     562
     563    /*
     564     * The Child returns here.
     565     */
     566        "fork_ret:\n\t"
     567        "popl    %%gs\n\t"
     568        "popl    %%ebp\n\t"
     569        "popl    %%edi\n\t"
     570        "popl    %%esi\n\t"
     571        "popl    %%ebx\n\t"
     572        "popf\n\t"
     573        "\n"
     574        "fork_skip_regs:\n\t"
     575        : "=a" (pid): "d" (&XcptRegRec) : "ecx");
     576
     577    /*
     578     * Restore the exception handler and exit the must complete section.
     579     */
     580    pTib->tib_pexchain = XcptRegRec.Core.prev_structure;
     581    DosExitMustComplete(&cNesting);
     582
     583    /*
     584     * Release the exec semaphore.
     585     */
     586    _fmutex_release(&__libc_gmtxExec);
     587
     588    /*
     589     * Restore the FPU state.
     590     */
     591    if (fHaveFXSR)
     592        __asm__ __volatile__ ("fxrstor %0" : "=m" (*pFPU));
     593    else
     594        __asm__ __volatile__ ("frstor %0" : "=m" (*pFPU));
     595
     596    FS_RESTORE();
     597    LIBCLOG_RETURN_INT(pid);
     598}
     599
     600
     601/**
     602 * This is the function called by __libc_Back_processFork() to drive the
     603 * parent side of the fork.
     604 *
     605 * At this point we're in a must-complete section, owning the exec mutex,
     606 * and have forkParExceptionHandler installed.
    360607 *
    361608 *
     
    375622 *
    376623 * @returns pid of the forked child process on success.
    377  * @returns -1 and errno on failure.
     624 * @returns Negative error code (errno.h) on failure.
    378625 *
    379626 * @param   pvForkRet       Return address for the child.
    380627 * @param   pvStackRet      ESP for the child when returning from fork.
    381  */
    382 int __libc_fork(void *pvForkRet, void *pvStackRet)
     628 * @param   pXctpRegRec     Pointer to the exception registration record (fDoneCompletion).
     629 */
     630static int forkParDo(void *pvForkRet, void *pvStackRet, __LIBC_PFORKXCPTREGREC pXcptRegRec)
    383631{
    384632    LIBCLOG_ENTER("pvForkRet=%p pvStackRet=%p\n", pvForkRet, pvStackRet);
    385     __LIBC_PFORKHANDLE  pForkHandle;
    386     __LIBC_PFORKMODULE  pModules;
    387     int                 rc;
    388     pid_t               pid = -1;
    389     PTIB                pTib;
    390     PPIB                pPib;
    391     __LIBC_FORKXCPTREGREC XcptRegRec;
    392     FS_VAR();
    393633
    394634    /*
    395635     * Get module list.
    396636     */
    397     pModules = forkBthGetModules();
     637    __LIBC_PFORKMODULE pModules = forkBthGetModules();
    398638    if (!pModules)
    399         LIBCLOG_ERROR_RETURN_INT(-1);
     639        LIBCLOG_ERROR_RETURN_INT(-ENOSYS);
    400640
    401641    /*
     
    406646    {
    407647        LIBC_ASSERTM_FAILED("Can't fork this process, the executable wasn't built with -Zfork!\n");
    408         LIBCLOG_ERROR_RETURN_INT(-1);
    409     }
    410 
    411     /*
    412      * Take the Exec Semaphore.
    413      */
    414     rc = _fmutex_request(&__libc_gmtxExec, 0);
    415     if (rc)
    416     {
    417         _sys_set_errno(rc);
    418         LIBCLOG_ERROR_RETURN_INT(-1);
    419     }
    420 
    421     /*
    422      * Register the exception handler.
    423      */
    424     FS_SAVE_LOAD();
    425     DosGetInfoBlocks(&pTib, &pPib);
    426     XcptRegRec.fDoneCompletion = 0;
    427     XcptRegRec.Core.ExceptionHandler = forkParExceptionHandler;
    428     XcptRegRec.Core.prev_structure = pTib->tib_pexchain;
    429     pTib->tib_pexchain = &XcptRegRec.Core;
    430     g_pForkHandle = NULL;
     648        LIBCLOG_ERROR_RETURN_INT(-ENOSYS);
     649    }
     650
     651    /*
     652     * Check that we can handle all the modules in the chain.
     653     */
     654    int rc = forkParValidateModules(pModules);
     655    if (rc < 0)
     656        LIBCLOG_ERROR_RETURN_INT(rc);
    431657
    432658    /*
     
    434660     * Install signal handlers after that.
    435661     */
    436     g_pForkHandle = pForkHandle = forkParAllocHandle(pModules, pvStackRet, pvForkRet);
     662    pid_t   pid = -1;
     663    __LIBC_PFORKHANDLE pForkHandle = forkParAllocHandle(pModules, pvStackRet, pvForkRet);
     664    g_pForkHandle = pForkHandle;
    437665    if (pForkHandle)
    438666    {
     
    483711         * Process child context completion callbacks.
    484712         */
    485         if (!XcptRegRec.fDoneCompletion)
     713        if (!pXcptRegRec->fDoneCompletion)
    486714            forkParCompletionParent(pForkHandle, rc);
    487715        forkBthCloseHandle(pForkHandle, __LIBC_FORK_CTX_PARENT);
    488716    }
     717    else
     718        rc = -ENOMEM;
    489719
    490720
     
    493723     */
    494724    if (rc >= 0)
     725    {
    495726        __libc_back_processWaitNotifyExec(pid);
    496 
    497     /*
    498      * Reregister the exception handler but now replacing the existing chain.
    499      */
    500     pTib->tib_pexchain = XcptRegRec.Core.prev_structure;
    501     g_pForkHandle = NULL;
    502     _fmutex_release(&__libc_gmtxExec);
    503     FS_RESTORE();
    504     if (rc >= 0)
    505727        LIBCLOG_RETURN_INT(pid);
    506 
    507     /* failure - we are non-posix in or errno code perhaps, but couldn't care less for the moment... */
    508     errno = -rc;
    509     LIBCLOG_ERROR_RETURN_INT(-1);
     728    }
     729    LIBCLOG_ERROR_RETURN_INT(-rc);
    510730}
    511731
     
    633853    errno = EINVAL;
    634854    LIBCLOG_RETURN_INT(-1);
     855}
     856
     857
     858/**
     859 * Validate that we can handle all the modules in the list.
     860 *
     861 * This routine will check the version number of each module and make
     862 * sure we're able to cope with it.
     863 *
     864 * @returns 0 if all modules returns succesfully.
     865 * @returns negative error code (errno.h) on incompatability.
     866 * @param   pModules        Head of the module list.
     867 */
     868static int forkParValidateModules(__LIBC_PFORKMODULE pModules)
     869{
     870    LIBCLOG_ENTER("pModules=%p\n", (void *)pModules);
     871    unsigned            i = 0;
     872    __LIBC_PFORKMODULE  pModule;
     873    for (pModule = pModules; pModule; pModule = pModule->pNext)
     874    {
     875        (void)i;
     876        LIBCLOG_MSG("%p: #%d uVersion=%#10x pfnAtFork=%p papParent=%p papChild=%p pvDataSegBase=%p pvDataSegEnd=%p fFlags=%#010x pNext=%p\n",
     877                    (void *)pModule, i++, pModule->uVersion, (void *)pModule->pfnAtFork, (void *)pModule->papParent1, (void *)pModule->papChild1,
     878                    pModule->pvDataSegBase, pModule->pvDataSegEnd, pModule->fFlags, (void *)pModule->pNext);
     879        if ((pModule->uVersion >> 16) != (__LIBC_FORK_MODULE_VERSION >> 16))
     880        {
     881            LIBCLOG_ERROR("Encountered a new and incompatible module version, %#x. pModule=%p\n", pModule->uVersion, (void *)pModule);
     882            LIBCLOG_ERROR_RETURN_INT(-ENEWVER);
     883        }
     884    }
     885    LIBCLOG_RETURN_INT(0);
    635886}
    636887
     
    9541205        if (pForkHandle->enmStage == __LIBC_FORK_STAGE_EXEC)
    9551206        {
    956             rc = DosOpenMutexSem(NULL, &pForkHandle->hmtx);
    957             if (!rc)
     1207            if (pForkHandle->uVersion == __LIBC_FORK_VERSION)
    9581208            {
    959                 rc = DosOpenEventSem(NULL, &pForkHandle->hevParent);
     1209                rc = DosOpenMutexSem(NULL, &pForkHandle->hmtx);
    9601210                if (!rc)
    9611211                {
    962                     rc = DosOpenEventSem(NULL, &pForkHandle->hevChild);
     1212                    rc = DosOpenEventSem(NULL, &pForkHandle->hevParent);
    9631213                    if (!rc)
    9641214                    {
    965                         /*
    966                          * Succesfully opened the handle for the first time.
    967                          * Set the pidChild.
    968                          */
    969                         PTIB pTib;
    970                         PPIB pPib;
    971                         DosGetInfoBlocks(&pTib, &pPib);
    972                         pForkHandle->pidChild = pPib->pib_ulpid;
    973                         LIBC_ASSERTM(pForkHandle->pidParent == pPib->pib_ulppid,
    974                                      "Invalid parent pid... pidParent=%04x pib_ulppid=%04lx (pib_ulpid=%04lx).\n",
    975                                      pForkHandle->pidParent, pPib->pib_ulppid, pPib->pib_ulpid);
    976                         LIBCLOG_RETURN_P(pForkHandle);
     1215                        rc = DosOpenEventSem(NULL, &pForkHandle->hevChild);
     1216                        if (!rc)
     1217                        {
     1218                            /*
     1219                             * Succesfully opened the handle for the first time.
     1220                             * Set the pidChild.
     1221                             */
     1222                            PTIB pTib;
     1223                            PPIB pPib;
     1224                            DosGetInfoBlocks(&pTib, &pPib);
     1225                            pForkHandle->pidChild = pPib->pib_ulpid;
     1226                            LIBC_ASSERTM(pForkHandle->pidParent == pPib->pib_ulppid,
     1227                                         "Invalid parent pid... pidParent=%04x pib_ulppid=%04lx (pib_ulpid=%04lx).\n",
     1228                                         pForkHandle->pidParent, pPib->pib_ulppid, pPib->pib_ulpid);
     1229                            LIBCLOG_RETURN_P(pForkHandle);
     1230                        }
     1231                        else
     1232                            LIBC_ASSERTM_FAILED("DosOpenEventSem(NULL,..:{%lx}) -> %d (child)\n", pForkHandle->hevChild, rc);
    9771233                    }
    9781234                    else
    979                         LIBC_ASSERTM_FAILED("DosOpenEventSem(NULL,..:{%lx}) -> %d (child)\n", pForkHandle->hevChild, rc);
     1235                        LIBC_ASSERTM_FAILED("DosOpenEventSem(NULL,..:{%lx}) -> %d (parent)\n", pForkHandle->hevParent, rc);
    9801236                }
    9811237                else
    982                     LIBC_ASSERTM_FAILED("DosOpenEventSem(NULL,..:{%lx}) -> %d (parent)\n", pForkHandle->hevParent, rc);
     1238                    LIBC_ASSERTM_FAILED("pForkHandle->uVersion (%#x) != __LIBC_FORK_VERSION (%#x)\n", pForkHandle->uVersion, __LIBC_FORK_VERSION);
    9831239            }
    9841240            else
     
    10171273
    10181274    /*
     1275     * Block signals while we're in here. We cannot handle them properly anyway.
     1276     */
     1277    ULONG cNesting = 0;
     1278    DosEnterMustComplete(&cNesting);
     1279
     1280    /*
    10191281     * Open and process the buffer on first call.
    10201282     */
     
    10231285        rc = forkBthBufferWait(pForkHandle, __LIBC_FORK_CTX_CHILD);
    10241286        if (rc < 0)
     1287        {
     1288            DosExitMustComplete(&cNesting);
    10251289            LIBCLOG_RETURN_INT(rc);
     1290        }
    10261291        rc = forkBthBufferProcess(pForkHandle, __LIBC_FORK_CTX_CHILD, NULL);
    10271292        if (rc < 0)
     1293        {
     1294            DosExitMustComplete(&cNesting);
    10281295            LIBCLOG_RETURN_INT(rc);
     1296        }
    10291297
    10301298        /* next stage */
     
    10371305    rc = pModule->pfnAtFork(pModule, pForkHandle, __LIBC_FORK_OP_EXEC_CHILD);
    10381306    if (rc < 0)
     1307    {
     1308        DosExitMustComplete(&cNesting);
    10391309        LIBCLOG_RETURN_INT(rc);
     1310    }
    10401311
    10411312    /* done? */
    10421313    if (!fExecutable)
     1314    {
     1315        DosExitMustComplete(&cNesting);
    10431316        LIBCLOG_RETURN_INT(0);
     1317    }
    10441318
    10451319    /*
     
    10811355                           "D" ((uintptr_t)pForkHandle->pvStackRet),
    10821356                           "S" (pForkHandle->pvForkRet));
    1083     return forkChlDoFork2(pForkHandle); /* just for referencing the function - we'll never get here!!! */
     1357    /* just for referencing the functions so GCC doesn't optimize them away - we'll never get here!!! */
     1358    return forkChlDoFork2(pForkHandle) + forkParDo(NULL, NULL, NULL);
    10841359}
    10851360
     
    11131388    rc = forkBthBufferSpace(pForkHandle, offsetof(__LIBC_FORKPKGHDR, u.Next.achStart));
    11141389    if (rc < 0)
    1115         LIBCLOG_RETURN_INT(rc);
     1390        forkChlFatalError(pForkHandle, rc, NULL);
    11161391    forkBthBufferNext(pForkHandle);
    11171392    forkBthBufferEnd(pForkHandle);
     
    11391414        forkChlFatalError(pForkHandle, rc, NULL);
    11401415
    1141 
    11421416    /*
    11431417     * Do completion child calls (success).
     
    11611435
    11621436    /*
    1163      * The return here will go back to the inline assmebly which called us
    1164      * clean up the stack and jump to the resume location in __fork.s.
    1165      */
    1166     _fmutex_release(&__libc_gmtxExec);
     1437     * The return here will go back to the inline assmebly which called us in forkChlDoFork()
     1438     * and restore the stack pointer to the __libc_Back_processFork() and jump to the fork_ret
     1439     * label in __libc_Back_processFork().
     1440     * __libc_Back_processFork() will restore the exception handler chain, exit
     1441     * the must-complete section and release the execute semaphore.
     1442     */
    11671443    __libc_spmExeInited();
    11681444    pTib->tib_pexchain = END_OF_CHAIN;
     
    12971573{
    12981574    LIBCLOG_ENTER("pForkHandle=%p rc=%d\n", (void *)pForkHandle, rc);
    1299     forkBothCompletion(pForkHandle, rc, __LIBC_FORK_CTX_CHILD);
     1575    forkBothCompletion(pForkHandle, rc, __LIBC_FORK_CTX_CHILD, &pForkHandle->iCompletionCallbackChild);
    13001576    LIBCLOG_RETURN_VOID();
    13011577}
     
    13121588{
    13131589    LIBCLOG_ENTER("pForkHandle=%p rc=%d\n", (void *)pForkHandle, rc);
    1314     forkBothCompletion(pForkHandle, rc, __LIBC_FORK_CTX_PARENT);
     1590    forkBothCompletion(pForkHandle, rc, __LIBC_FORK_CTX_PARENT, &pForkHandle->iCompletionCallbackParent);
    13151591    LIBCLOG_RETURN_VOID();
    13161592}
     
    13201596 * Execute completion callbacks for a context.
    13211597 *
    1322  * @param   pForkHandle Fork Handle.
    1323  * @param   rc          The error code (errno.h) for the fork operation.
    1324  *                      Negative means error, zero or positive means success.
    1325  * @param   enmCtx      The Context.
    1326  */
    1327 void                 forkBothCompletion(__LIBC_PFORKHANDLE pForkHandle, int rc, __LIBC_FORKCTX enmCtx)
    1328 {
    1329 
     1598 * @param   pForkHandle             Fork Handle.
     1599 * @param   rc                      The error code (errno.h) for the fork operation.
     1600 *                                  Negative means error, zero or positive means success.
     1601 * @param   enmCtx                  The Context.
     1602 * @param   piCompletionCallaback   Pointer to the variable containing the current completion callback index.
     1603 *                                  This is both input and output.
     1604 */
     1605void                 forkBothCompletion(__LIBC_PFORKHANDLE pForkHandle, int rc, __LIBC_FORKCTX enmCtx, unsigned volatile *piCompletionCallback)
     1606{
    13301607    /*
    13311608     * Call completion callbacks in reverse registration order.
     
    13371614    __LIBC_PFORKCOMPLETIONCALLBACK  papfn = pForkHandle->papfnCompletionCallbacks;
    13381615    unsigned                        iCC;
    1339     for (iCC = 0; iCC < cCCs; iCC++)
    1340     {
     1616    while ((iCC = *piCompletionCallback) < cCCs)
     1617    {
     1618        *piCompletionCallback += 1;
    13411619        if (    papfn[iCC].enmContext == __LIBC_FORK_CTX_BOTH
    13421620            ||  papfn[iCC].enmContext == enmCtx)
     
    14651743            pChunk->pv = pvStart;
    14661744            pChunk->cb = pChunk->cbVirt = cbRange;
    1467             pChunk->offData = 16 - ((uintptr_t)&pChunk->achData[0] & 15);
    1468             if (pChunk->offData == 16)
     1745            pChunk->offData = 64 - ((uintptr_t)&pChunk->achData[0] & 63);
     1746            if (pChunk->offData == 64)
    14691747                pChunk->offData = 0;    /* fixme: probably could do this without if's. */
    14701748
     
    15061784                        break;          /* need to flush the buffer. */
    15071785                }
    1508                 forkBthCopyPages(&pChunk->achData[pChunk->offData], pvStart, pChunk->cb);
     1786                pfnForkBthCopyPages(&pChunk->achData[pChunk->offData], pvStart, pChunk->cb);
    15091787            }
    15101788            else
     
    15751853                                break;          /* need to flush the buffer. */
    15761854                        }
    1577                         forkBthCopyPages(&pChunk->achData[pChunk->offData], pvStart, pChunk->cb);
     1855                        pfnForkBthCopyPages(&pChunk->achData[pChunk->offData], pvStart, pChunk->cb);
    15781856                    }
    15791857                }
     
    21072385         */
    21082386        if (pChunk->cb)
    2109             forkBthCopyPages(pChunk->pv, &pChunk->achData[pChunk->offData], pChunk->cb);
     2387            pfnForkBthCopyPages(pChunk->pv, &pChunk->achData[pChunk->offData], pChunk->cb);
    21102388
    21112389        /* next */
     
    22952573
    22962574/**
    2297  * Copy page memory.
    2298  *
    2299  * @param   pvTrg   Target address.
     2575 * Copy page memory, detect the right worker function and calls it.
     2576 *
     2577 * @param   pvDst   Target address.
    23002578 * @param   pvSrc   Source address.
    23012579 * @param   cb      Number of bytes to copy.
    2302  * @remark  We will later make alignment requirements depending on which
    2303  *          fast copy algorithms we end up using...
    2304  */
    2305 void forkBthCopyPages(void *pvTrg, const void *pvSrc, size_t cb)
    2306 {
    2307     LIBCLOG_ENTER("pvTrg=%p pvSrc=%p cb=0x%08x\n", pvTrg, pvSrc, cb);
    2308     /** @todo install exception handler to catch access violations! */
    2309 
    2310     /** @todo optimize memcpy for duplicate pages. This can assume 4 byte alignment, we can
    2311      * if required force 8 or 16 alignment if required. The SSE[1-3] and MMX states are saved
    2312      * on the stack and can be restored in both contexts if we like to use those instruction
    2313      * extensions for faster memcpy.
    2314      */
    2315 #if 0
    2316     memcpy(pvTrg, pvSrc, cb);
    2317 #else
     2580 */
     2581void forkBthCopyPagesDetect(void *pvDst, const void *pvSrc, size_t cb)
     2582{
     2583    /*
     2584     * Decide which function to use.
     2585     */
     2586    pfnForkBthCopyPages = forkBthCopyPagesPlain; /* default, always works. */
     2587    if (HasCpuId())
     2588    {
     2589        unsigned uEdx = CpuIdEDX(1);
     2590        if (uEdx & (23/*MMX*/ << 1))
     2591        {
     2592            pfnForkBthCopyPages = forkBthCopyPagesMMX;
     2593#if 0  /* missing hardware to test this. */
     2594            /* hope this is right */
     2595            if (    (uEdx & (1 << 24)) /*FXSR*/
     2596                &&  (uEdx & (1 << 25)) /*SSE*/
     2597                &&  (uEdx & (1 << 26)) /*SSE2*/)
     2598                pfnForkBthCopyPages = forkBthCopyPagesSSE2;
     2599#endif
     2600#if 0 /* too slow for some peculiar reason... */
     2601            else
     2602            {
     2603                if (    uEdx & (23/*MMX*/ << 1)
     2604                    &&  uEdx & (25/*SSE*/ << 1))
     2605                    pfnForkBthCopyPages = forkBthCopyPagesMMXNonTemporal;
     2606            }
     2607#endif
     2608        }
     2609    }
     2610    pfnForkBthCopyPages(pvDst, pvSrc, cb);
     2611}
     2612
     2613
     2614__asm__(".align 4\n\t");
     2615/**
     2616 * Copy page memory, plain stupid rep movsl.
     2617 *
     2618 * @param   pvDst   Target address.
     2619 * @param   pvSrc   Source address.
     2620 * @param   cb      Number of bytes to copy.
     2621 */
     2622static void forkBthCopyPagesPlain(void *pvDst, const void *pvSrc, size_t cb)
     2623{
     2624    LIBCLOG_ENTER("pvDst=%p pvSrc=%p cb=0x%08x\n", pvDst, pvSrc, cb);
    23182625    register unsigned long int r0,r1,r2;
    2319     __asm__ __volatile__                                                       
    2320       ("cld\n\t"                                                               
    2321        "rep; movsl"                                                     
     2626    __asm__ __volatile__
     2627      ("cld\n\t"
     2628       "rep; movsl"
    23222629       : "=&c" (r0), "=&D" (r1), "=&S" (r2)
    2323        : "0" (cb / 4), "1" (pvTrg), "2" (pvSrc)
     2630       : "0" (cb / 4), "1" (pvDst), "2" (pvSrc)
    23242631       : "memory");
    2325 
    2326     memcpy(pvTrg, pvSrc, cb);
     2632    LIBCLOG_RETURN_VOID();
     2633}
     2634
     2635
     2636__asm__(".align 4\n\t");
     2637/**
     2638 * Copy page memory, MMX.
     2639 *
     2640 * @param   pvDst   Target address.
     2641 * @param   pvSrc   Source address.
     2642 * @param   cb      Number of bytes to copy.
     2643 */
     2644static void forkBthCopyPagesMMX(void *pvDst, const void *pvSrc, size_t cb)
     2645{
     2646    LIBCLOG_ENTER("pvDst=%p pvSrc=%p cb=0x%08x\n", pvDst, pvSrc, cb);
     2647    register unsigned long int r0,r1,r2;
     2648    __asm__ __volatile__
     2649      ("\
     26501:                                                              \n\
     2651        movq   (%0), %%mm1                                      \n\
     2652        movq  8(%0), %%mm2                                      \n\
     2653        movq 16(%0), %%mm3                                      \n\
     2654        movq 24(%0), %%mm4                                      \n\
     2655        movq %%mm1,   (%1)                                      \n\
     2656        movq %%mm2,  8(%1)                                      \n\
     2657        movq %%mm3, 16(%1)                                      \n\
     2658        movq %%mm4, 24(%1)                                      \n\
     2659        movq 32(%0), %%mm5                                      \n\
     2660        movq 40(%0), %%mm6                                      \n\
     2661        movq 48(%0), %%mm7                                      \n\
     2662        movq 56(%0), %%mm0                                      \n\
     2663        addl $64, %0                                            \n\
     2664        movq %%mm5, 32(%1)                                      \n\
     2665        movq %%mm6, 40(%1)                                      \n\
     2666        movq %%mm7, 48(%1)                                      \n\
     2667        movq %%mm0, 56(%1)                                      \n\
     2668        addl $64, %1                                            \n\
     2669                                                                \n\
     2670        decl %2                                                 \n\
     2671        jnz 1b                                                  \n\
     2672                                                                \n\
     2673        emms                                                    \n\
     2674        "
     2675       : "=&r" (r0), "=&r" (r1), "=&r" (r2)
     2676       : "0" (pvSrc), "1" (pvDst), "2" (cb/64)
     2677       : "memory");
     2678    LIBCLOG_RETURN_VOID();
     2679}
     2680
     2681
     2682#if 0 /* too slow */
     2683__asm__(".align 4\n\t");
     2684/**
     2685 * Copy page memory, MMX with non-temporal stores.
     2686 *
     2687 * @param   pvDst   Target address.
     2688 * @param   pvSrc   Source address.
     2689 * @param   cb      Number of bytes to copy.
     2690 * @remark requires the Pentium III MMX extensions (appears to mean SSE).
     2691 */
     2692static void forkBthCopyPagesMMXNonTemporal(void *pvDst, const void *pvSrc, size_t cb)
     2693{
     2694    LIBCLOG_ENTER("pvDst=%p pvSrc=%p cb=0x%08x\n", pvDst, pvSrc, cb);
     2695    register unsigned long int r0,r1,r2;
     2696    __asm__ __volatile__
     2697      ("\n\
     2698        movq   (%0), %%mm1                                          \n\
     2699        movq  8(%0), %%mm2                                          \n\
     2700        prefetchnta 320(%0)                                         \n\
     2701        movq 16(%0), %%mm3                                          \n\
     2702        movq 24(%0), %%mm4                                          \n\
     2703        movntq %%mm1,   (%1)                                        \n\
     2704        movntq %%mm2,  8(%1)                                        \n\
     2705        movntq %%mm3, 16(%1)                                        \n\
     2706        movntq %%mm4, 24(%1)                                        \n\
     2707        movq 32(%0), %%mm5                                          \n\
     2708        movq 40(%0), %%mm6                                          \n\
     2709        movq 48(%0), %%mm7                                          \n\
     2710        movq 56(%0), %%mm0                                          \n\
     2711        addl $64, %0                                                \n\
     2712        movntq %%mm5, 32(%1)                                        \n\
     2713        movntq %%mm6, 40(%1)                                        \n\
     2714        movntq %%mm7, 48(%1)                                        \n\
     2715        movntq %%mm0, 56(%1)                                        \n\
     2716        addl $64, %1                                                \n\
     2717        decl %2                                                     \n\
     2718        1:                                                          \n\
     2719        movq   (%0), %%mm1                                          \n\
     2720        movq  8(%0), %%mm2                                          \n\
     2721        movq 16(%0), %%mm3                                          \n\
     2722        movq 24(%0), %%mm4                                          \n\
     2723        movntq %%mm1,   (%1)                                        \n\
     2724        movntq %%mm2,  8(%1)                                        \n\
     2725        movntq %%mm3, 16(%1)                                        \n\
     2726        movntq %%mm4, 24(%1)                                        \n\
     2727        movq 32(%0), %%mm5                                          \n\
     2728        movq 40(%0), %%mm6                                          \n\
     2729        movq 48(%0), %%mm7                                          \n\
     2730        movq 56(%0), %%mm0                                          \n\
     2731        addl $64, %0                                                \n\
     2732        prefetchnta 320(%0)                                         \n\
     2733        movntq %%mm5, 32(%1)                                        \n\
     2734        movntq %%mm6, 40(%1)                                        \n\
     2735        movntq %%mm7, 48(%1)                                        \n\
     2736        movntq %%mm0, 56(%1)                                        \n\
     2737        addl $64, %1                                                \n\
     2738                                                                    \n\
     2739        decl %2                                                     \n\
     2740        jnz 1b                                                      \n\
     2741        emms                                                        \n\
     2742        "
     2743        : "=&r" (r0), "=&r" (r1), "=&r" (r2)
     2744        : "0" (pvSrc), "1" (pvDst), "2" (cb/64)
     2745        : "memory");
     2746    LIBCLOG_RETURN_VOID();
     2747}
    23272748#endif
     2749
     2750#if 0 /* untested */
     2751/**
     2752 * Copy page memory, SSE.
     2753 *
     2754 * @param   pvDst   Target address.
     2755 * @param   pvSrc   Source address.
     2756 * @param   cb      Number of bytes to copy.
     2757 */
     2758static void forkBthCopyPagesSSE2(void *pvDst, const void *pvSrc, size_t cb)
     2759{
     2760    LIBCLOG_ENTER("pvDst=%p pvSrc=%p cb=0x%08x\n", pvDst, pvSrc, cb);
     2761    if ((uintptr_t)pvDst & 15)  asm("int3");
     2762    if ((uintptr_t)pvSrc & 15)  asm("int3");
     2763    if (cb & 127)  asm("int3");
     2764
     2765    register unsigned long int r0,r1,r2;
     2766    __asm__ __volatile__
     2767      ("prefetchnta    (%0)                             \n\
     2768        prefetchnta  64(%0)                             \n\
     2769        prefetchnta 128(%0)                             \n\
     2770        prefetchnta 192(%0)                             \n\
     2771        prefetchnta 256(%0)                             \n\
     2772        jmp 1f                                          \n\
     2773                                                        \n\
     2774        .align 4                                        \n\
     2775        1:                                              \n\
     2776        prefetchnta 320(%0)                             \n\
     2777        movdqa    (%0), %%xmm0                          \n\
     2778        movdqa  16(%0), %%xmm1                          \n\
     2779        movntdq %%xmm0,   (%1)                          \n\
     2780        movntdq %%xmm1, 16(%1)                          \n\
     2781        movdqa  32(%0), %%xmm2                          \n\
     2782        movdqa  48(%0), %%xmm3                          \n\
     2783        movntdq %%xmm2, 32(%1)                          \n\
     2784        movntdq %%xmm3, 48(%1)                          \n\
     2785        movdqa  64(%0), %%xmm4                          \n\
     2786        movdqa  80(%0), %%xmm5                          \n\
     2787        movntdq %%xmm4, 64(%1)                          \n\
     2788        movntdq %%xmm5, 80(%1)                          \n\
     2789        movdqa  96(%0), %%xmm6                          \n\
     2790        movdqa  112(%0), %%xmm7                         \n\
     2791        movntdq %%xmm6, 96(%1)                          \n\
     2792        movntdq %%xmm7, 112(%1)                         \n\
     2793                                                        \n\
     2794        addl $128, %0                                   \n\
     2795        addl $128, %1                                   \n\
     2796        decl %2                                         \n\
     2797        jnz 1b                                          \n\
     2798                                                        \n\
     2799        sfence                                          \n\
     2800       "
     2801        : "=&r" (r0), "=&r" (r1), "=&r" (r2)
     2802        : "0" (pvDst), "1" (pvSrc), "2" (cb / 128)
     2803        : "memory");
    23282804    LIBCLOG_RETURN_VOID();
    23292805}
     2806#endif
    23302807
    23312808
     
    25903067    if (pXcptRepRec->fHandlerFlags & (EH_UNWINDING | EH_EXIT_UNWIND))
    25913068        return XCPT_CONTINUE_SEARCH;
    2592     LIBCLOG_MSG2("forkParExceptionHandler: ExceptionNum=%#lx eip=%#lx\n", pXcptRepRec->ExceptionNum, pCtx->ctx_RegEip);
     3069    LIBCLOG_MSG2("forkParExceptionHandler: ExceptionNum=%#lx ExceptionAddress=%p eip=%#lx ExceptionInfo={%#08lx,%#08lx,%#08lx,%#08lx} fHandlerFlags=%#lx\n",
     3070                 pXcptRepRec->ExceptionNum, pXcptRepRec->ExceptionAddress, pCtx->ctx_RegEip,
     3071                 pXcptRepRec->ExceptionInfo[0], pXcptRepRec->ExceptionInfo[1],
     3072                 pXcptRepRec->ExceptionInfo[2], pXcptRepRec->ExceptionInfo[3],
     3073                 pXcptRepRec->fHandlerFlags);
    25933074
    25943075    switch (pXcptRepRec->ExceptionNum)
     
    27163197    DosGetInfoBlocks(&pTib, &pPib);
    27173198    pTib->tib_pexchain = END_OF_CHAIN;
    2718     LIBCLOG_MSG2("forkParExceptionHandler: ExceptionNum=%#lx eip=%#lx\n", pXcptRepRec->ExceptionNum, pCtx->ctx_RegEip);
     3199    LIBCLOG_MSG2("forkChlExceptionHandler: ExceptionNum=%#lx ExceptionAddress=%p eip=%#lx ExceptionInfo={%#08lx,%#08lx,%#08lx,%#08lx} fHandlerFlags=%#lx\n",
     3200                 pXcptRepRec->ExceptionNum, pXcptRepRec->ExceptionAddress, pCtx->ctx_RegEip,
     3201                 pXcptRepRec->ExceptionInfo[0], pXcptRepRec->ExceptionInfo[1],
     3202                 pXcptRepRec->ExceptionInfo[2], pXcptRepRec->ExceptionInfo[3],
     3203                 pXcptRepRec->fHandlerFlags);
    27193204
    27203205    switch (pXcptRepRec->ExceptionNum)
Note: See TracChangeset for help on using the changeset viewer.