Changeset 2289
- Timestamp:
- Aug 21, 2005, 12:08:50 AM (20 years ago)
- 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
to1.119
r2288 r2289 5 5 2005-08-20: knut st. osmundsen <bird-gccos2-spam@anduin.net> 6 6 - 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(). 7 15 o Added _memcpy_amd. 16 o Fixed some logging statements in sharedpm.c. 8 17 o Log __fmutex_release_internal_must_complete. 9 18 o Corrected a few prototypes in process.h to use pid_t. -
Property cvs2svn:cvs-rev
changed from
-
trunk/src/emx/include/InnoTekLIBC/backend.h
-
Property cvs2svn:cvs-rev
changed from
1.28
to1.29
r2288 r2289 767 767 768 768 /** 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 */ 776 pid_t __libc_Back_processFork(void); 777 778 /** 769 779 * Waits/polls for on one or more processes to change it's running status. 770 780 * -
Property cvs2svn:cvs-rev
changed from
-
trunk/src/emx/include/InnoTekLIBC/fork.h
-
Property cvs2svn:cvs-rev
changed from
1.3
to1.4
r2288 r2289 34 34 35 35 /** 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 37 40 38 41 /** Timeout on waiting semaphore in fork operations */ … … 272 275 typedef struct __libc_ForkHandle 273 276 { 274 /** Fork version . */277 /** Fork version (__LIBC_FORK_VERSION). */ 275 278 unsigned uVersion; 276 279 /** Parent process, i.e. the one which have called fork(). */ … … 422 425 * the front. */ 423 426 __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; 424 431 425 432 /** Pointer to the start of the fork buffer. */ … … 538 545 typedef struct __libc_ForkModule 539 546 { 540 /** Fork version. */547 /** Fork module version (__LIBC_FORK_MODULE_VERSION). */ 541 548 unsigned uVersion; 542 549 /** Fork callback function. -
Property cvs2svn:cvs-rev
changed from
-
trunk/src/emx/include/emx/asm386.h
-
Property cvs2svn:cvs-rev
changed from
1.10
to1.11
r2288 r2289 40 40 41 41 #define ALIGN .align 4, 0x90 42 #define ALIGNP2(a) .align a, 0x90 42 43 43 44 #define SET_ERRNO_CONST(x) \ -
Property cvs2svn:cvs-rev
changed from
-
trunk/src/emx/include/sys/errno.h
-
Property cvs2svn:cvs-rev
changed from
1.10
to1.11
r2288 r2289 194 194 #endif /* _POSIX_SOURCE */ 195 195 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 196 201 #ifdef _KERNEL 197 202 /* pseudo-errors returned inside kernel to modify return to process */ -
Property cvs2svn:cvs-rev
changed from
-
trunk/src/emx/include/sys/process.h
-
Property cvs2svn:cvs-rev
changed from
1.5
to1.6
r2288 r2289 7 7 #define _SYS_PROCESS_H 8 8 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) 15 typedef __pid_t pid_t; 16 #define _PID_T_DECLARED 17 #define _PID_T 11 18 #endif 12 19 … … 51 58 void exit (int) __attribute__ ((__noreturn__)); 52 59 void _exit (int) __attribute__ ((__noreturn__)); 53 int fork (void);54 int getpid (void);55 int getppid (void);60 pid_t fork (void); 61 pid_t getpid (void); 62 pid_t getppid (void); 56 63 int spawnl (int, __const__ char *, __const__ char *, ...); 57 64 int spawnle (int, __const__ char *, __const__ char *, ...); … … 63 70 int spawnvpe (int, __const__ char *, char * __const__ *, char * __const__ *); 64 71 int system (__const__ char *); 65 int wait (int *);66 int waitpid (int, int *, int);72 pid_t wait (int *); 73 pid_t waitpid (pid_t, int *, int); 67 74 68 75 int _execl (__const__ char *, __const__ char *, ...); … … 75 82 int _execvpe (__const__ char *, char * __const__ *, char * __const__ *); 76 83 int _fork (void); 77 int _getpid (void);78 int _getppid (void);84 pid_t _getpid (void); 85 pid_t _getppid (void); 79 86 int _spawnl (int, __const__ char *, __const__ char *, ...); 80 87 int _spawnle (int, __const__ char *, __const__ char *, ...); … … 85 92 int _spawnvp (int, __const__ char *, char * __const__ *); 86 93 int _spawnvpe (int, __const__ char *, char * __const__ *, char * __const__ *); 87 int _wait (int *);88 int _waitpid (int, int *, int);94 pid_t _wait (int *); 95 pid_t _waitpid (pid_t, int *, int); 89 96 90 91 #if defined (__cplusplus) 92 } 93 #endif 97 __END_DECLS 94 98 95 99 #endif /* not _SYS_PROCESS_H */ -
Property cvs2svn:cvs-rev
changed from
-
trunk/src/emx/src/lib/libc.def
-
Property cvs2svn:cvs-rev
changed from
1.135
to1.136
r2288 r2289 236 236 "___fmutex_request_internal" @249 237 237 "___fmutex_request_internal_must_complete" @250 238 "___ fork" @251238 "___libc_Back_processFork" @251 239 239 ;msun - dead "___fpclassify" @252 240 240 ;msun - dead "___fpclassifyf" @253 … … 1943 1943 "___libc_LogError" @1941 1944 1944 "___libc_LogErrorLeave" @1942 1945 "__memcpy_amd" @1943 -
Property cvs2svn:cvs-rev
changed from
-
trunk/src/emx/src/lib/libc06b4.def
-
Property cvs2svn:cvs-rev
changed from
1.12
to1.13
r2288 r2289 234 234 "___fmutex_request_internal" @249 235 235 "___fmutex_request_internal_must_complete" @250 236 "___ fork" @251236 "___libc_Back_processFork" @251 237 237 "___fpclassify" = ___nullstub_function @252 238 238 "___fpclassifyf" = ___nullstub_function @253 -
Property cvs2svn:cvs-rev
changed from
-
trunk/src/emx/src/lib/libc06b5.def
-
Property cvs2svn:cvs-rev
changed from
1.6
to1.7
r2288 r2289 237 237 "___fmutex_request_internal" @249 238 238 "___fmutex_request_internal_must_complete" @250 239 "___ fork" @251239 "___libc_Back_processFork" @251 240 240 ;msun - dead "___fpclassify" @252 241 241 ;msun - dead "___fpclassifyf" @253 -
Property cvs2svn:cvs-rev
changed from
-
trunk/src/emx/src/lib/process/fork.c
-
Property cvs2svn:cvs-rev
changed from
1.8
to1.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 */ 2 26 27 28 /******************************************************************************* 29 * Header Files * 30 *******************************************************************************/ 3 31 #include "libc-alias.h" 4 32 #include <process.h> 5 #include <emx/syscalls.h> 33 #include <unistd.h> 34 #include <errno.h> 35 #include <InnoTekLIBC/backend.h> 6 36 #define __LIBC_LOG_GROUP __LIBC_LOG_GRP_FORK 7 37 #include <InnoTekLIBC/logstrict.h> 8 38 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 */ 47 pid_t _STD(fork)(void) 10 48 { 11 49 LIBCLOG_ENTER("\n"); 12 int pid = __fork();50 pid_t pid = __libc_Back_processFork(); 13 51 if (pid >= 0) 14 52 LIBCLOG_RETURN_INT(pid); 15 LIBCLOG_ERROR_RETURN_INT(pid); 53 errno = -pid; 54 LIBCLOG_ERROR_RETURN_INT(-1); 16 55 } 17 56 -
Property cvs2svn:cvs-rev
changed from
-
trunk/src/emx/src/lib/startup/386/crt0.s
-
Property cvs2svn:cvs-rev
changed from
1.13
to1.14
r2288 r2289 109 109 110 110 ForkModule: 111 .long 0x00010000 // uVersion 111 .long 0x00010000 // uVersion (__LIBC_FORK_MODULE_VERSION) 112 112 .long __atfork_callback // pfnAtFork 113 113 .long ___fork_parent1__ // papParent1 -
Property cvs2svn:cvs-rev
changed from
-
trunk/src/emx/src/lib/startup/386/dll0.s
-
Property cvs2svn:cvs-rev
changed from
1.16
to1.17
r2288 r2289 120 120 121 121 ForkModule: 122 .long 0x00010000 // uVersion 122 .long 0x00010000 // uVersion (__LIBC_FORK_MODULE_VERSION) 123 123 .long __atfork_callback // pfnAtFork 124 124 .long ___fork_parent1__ // papParent1 -
Property cvs2svn:cvs-rev
changed from
-
trunk/src/emx/src/lib/sys/libcfork.c
-
Property cvs2svn:cvs-rev
changed from
1.15
to1.16
r2288 r2289 2 2 /** @file 3 3 * 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> 7 7 * 8 8 * … … 92 92 } __LIBC_FORKXCPTREGREC, *__LIBC_PFORKXCPTREGREC; 93 93 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 */ 97 typedef struct X86FPUMMX 98 { 99 uint8_t reg[10]; 100 } X86FPUMMX; 101 /** Pointer to 80-bit MMX/FPU register type. */ 102 typedef X86FPUMMX *PX86FPUMMX; 103 104 /** 105 * FPU Extended state (aka FXSAVE/FXRSTORE Memory Region). 106 */ 107 #pragma pack(1) 108 typedef 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. */ 165 typedef X86FXSTATE *PX86FXSTATE; 101 166 102 167 … … 115 180 * In the 2nd section they are ordered by what they do. 116 181 */ 117 /* public */118 int __libc_fork(void *pvForkRet, void *pvStackRet);119 182 /* sequential */ 183 static int forkParDo(void *pvForkRet, void *pvStackRet, __LIBC_PFORKXCPTREGREC pXcptRegRec); 120 184 static int forkParCanFork(__LIBC_PFORKMODULE pModules); 185 static int forkParValidateModules(__LIBC_PFORKMODULE pModules); 121 186 static __LIBC_PFORKHANDLE forkParAllocHandle(__LIBC_PFORKMODULE pModules, void *pvStackRet, void *pvForkRet); 122 187 static int forkParRunPreExecParent(__LIBC_PFORKHANDLE pForkHandle, __LIBC_PFORKMODULE pModules); … … 131 196 static void forkChlCompletionChild(__LIBC_PFORKHANDLE pForkHandle, int rc); 132 197 static void forkParCompletionParent(__LIBC_PFORKHANDLE pForkHandle, int rc); 133 static void forkBothCompletion(__LIBC_PFORKHANDLE pForkHandle, int rc, __LIBC_FORKCTX enmCtx );198 static void forkBothCompletion(__LIBC_PFORKHANDLE pForkHandle, int rc, __LIBC_FORKCTX enmCtx, unsigned volatile *piCompletionCallback); 134 199 static void forkBthCloseHandle(__LIBC_PFORKHANDLE pForkHandle, __LIBC_FORKCTX enmContext); 135 200 /* any time */ … … 150 215 static int forkBthBufferSpace(__LIBC_PFORKHANDLE pForkHandle, size_t cb); 151 216 static int forkBthBufferGiveWaitNext(__LIBC_PFORKHANDLE pForkHandle, __LIBC_FORKCTX enmCtx); 152 static void forkBthCopyPages(void *pvTrg, const void *pvSrc, size_t cb); 217 static void forkBthCopyPagesDetect(void *pvDst, const void *pvSrc, size_t cb); 218 static void forkBthCopyPagesPlain(void *pvDst, const void *pvSrc, size_t cb); 219 static void forkBthCopyPagesMMX(void *pvDst, const void *pvSrc, size_t cb); 220 #if 0 221 static void forkBthCopyPagesMMXNonTemporal(void *pvDst, const void *pvSrc, size_t cb); 222 static void forkBthCopyPagesSSE2(void *pvDst, const void *pvSrc, size_t cb); 223 #endif 153 224 static void forkBthCallbacksSort(__LIBC_PFORKCALLBACK *papCallbacks); 154 225 static int forkBthCallbacksCompare(const void *pv1, const void *pv2); … … 165 236 PVOID pvWhatEver); 166 237 238 /******************************************************************************* 239 * Global Variables * 240 *******************************************************************************/ 241 /** Pointer to the page copy function. */ 242 static 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! */ 245 static volatile __LIBC_PFORKHANDLE g_pForkHandle = NULL; 167 246 168 247 … … 224 303 int __libc_ForkRegisterModule(__LIBC_PFORKMODULE pModule, int fExecutable) 225 304 { 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); 227 308 int rc; 228 309 __LIBC_PSPMPROCESS pProcess; … … 356 437 357 438 /** 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 */ 443 static 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 */ 471 static 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 */ 491 pid_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. 360 607 * 361 608 * … … 375 622 * 376 623 * @returns pid of the forked child process on success. 377 * @returns -1 and errnoon failure.624 * @returns Negative error code (errno.h) on failure. 378 625 * 379 626 * @param pvForkRet Return address for the child. 380 627 * @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 */ 630 static int forkParDo(void *pvForkRet, void *pvStackRet, __LIBC_PFORKXCPTREGREC pXcptRegRec) 383 631 { 384 632 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();393 633 394 634 /* 395 635 * Get module list. 396 636 */ 397 pModules = forkBthGetModules();637 __LIBC_PFORKMODULE pModules = forkBthGetModules(); 398 638 if (!pModules) 399 LIBCLOG_ERROR_RETURN_INT(- 1);639 LIBCLOG_ERROR_RETURN_INT(-ENOSYS); 400 640 401 641 /* … … 406 646 { 407 647 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); 431 657 432 658 /* … … 434 660 * Install signal handlers after that. 435 661 */ 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; 437 665 if (pForkHandle) 438 666 { … … 483 711 * Process child context completion callbacks. 484 712 */ 485 if (! XcptRegRec.fDoneCompletion)713 if (!pXcptRegRec->fDoneCompletion) 486 714 forkParCompletionParent(pForkHandle, rc); 487 715 forkBthCloseHandle(pForkHandle, __LIBC_FORK_CTX_PARENT); 488 716 } 717 else 718 rc = -ENOMEM; 489 719 490 720 … … 493 723 */ 494 724 if (rc >= 0) 725 { 495 726 __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)505 727 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); 510 730 } 511 731 … … 633 853 errno = EINVAL; 634 854 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 */ 868 static 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); 635 886 } 636 887 … … 954 1205 if (pForkHandle->enmStage == __LIBC_FORK_STAGE_EXEC) 955 1206 { 956 rc = DosOpenMutexSem(NULL, &pForkHandle->hmtx); 957 if (!rc) 1207 if (pForkHandle->uVersion == __LIBC_FORK_VERSION) 958 1208 { 959 rc = DosOpen EventSem(NULL, &pForkHandle->hevParent);1209 rc = DosOpenMutexSem(NULL, &pForkHandle->hmtx); 960 1210 if (!rc) 961 1211 { 962 rc = DosOpenEventSem(NULL, &pForkHandle->hev Child);1212 rc = DosOpenEventSem(NULL, &pForkHandle->hevParent); 963 1213 if (!rc) 964 1214 { 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); 977 1233 } 978 1234 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); 980 1236 } 981 1237 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); 983 1239 } 984 1240 else … … 1017 1273 1018 1274 /* 1275 * Block signals while we're in here. We cannot handle them properly anyway. 1276 */ 1277 ULONG cNesting = 0; 1278 DosEnterMustComplete(&cNesting); 1279 1280 /* 1019 1281 * Open and process the buffer on first call. 1020 1282 */ … … 1023 1285 rc = forkBthBufferWait(pForkHandle, __LIBC_FORK_CTX_CHILD); 1024 1286 if (rc < 0) 1287 { 1288 DosExitMustComplete(&cNesting); 1025 1289 LIBCLOG_RETURN_INT(rc); 1290 } 1026 1291 rc = forkBthBufferProcess(pForkHandle, __LIBC_FORK_CTX_CHILD, NULL); 1027 1292 if (rc < 0) 1293 { 1294 DosExitMustComplete(&cNesting); 1028 1295 LIBCLOG_RETURN_INT(rc); 1296 } 1029 1297 1030 1298 /* next stage */ … … 1037 1305 rc = pModule->pfnAtFork(pModule, pForkHandle, __LIBC_FORK_OP_EXEC_CHILD); 1038 1306 if (rc < 0) 1307 { 1308 DosExitMustComplete(&cNesting); 1039 1309 LIBCLOG_RETURN_INT(rc); 1310 } 1040 1311 1041 1312 /* done? */ 1042 1313 if (!fExecutable) 1314 { 1315 DosExitMustComplete(&cNesting); 1043 1316 LIBCLOG_RETURN_INT(0); 1317 } 1044 1318 1045 1319 /* … … 1081 1355 "D" ((uintptr_t)pForkHandle->pvStackRet), 1082 1356 "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); 1084 1359 } 1085 1360 … … 1113 1388 rc = forkBthBufferSpace(pForkHandle, offsetof(__LIBC_FORKPKGHDR, u.Next.achStart)); 1114 1389 if (rc < 0) 1115 LIBCLOG_RETURN_INT(rc);1390 forkChlFatalError(pForkHandle, rc, NULL); 1116 1391 forkBthBufferNext(pForkHandle); 1117 1392 forkBthBufferEnd(pForkHandle); … … 1139 1414 forkChlFatalError(pForkHandle, rc, NULL); 1140 1415 1141 1142 1416 /* 1143 1417 * Do completion child calls (success). … … 1161 1435 1162 1436 /* 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 */ 1167 1443 __libc_spmExeInited(); 1168 1444 pTib->tib_pexchain = END_OF_CHAIN; … … 1297 1573 { 1298 1574 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); 1300 1576 LIBCLOG_RETURN_VOID(); 1301 1577 } … … 1312 1588 { 1313 1589 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); 1315 1591 LIBCLOG_RETURN_VOID(); 1316 1592 } … … 1320 1596 * Execute completion callbacks for a context. 1321 1597 * 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 */ 1605 void forkBothCompletion(__LIBC_PFORKHANDLE pForkHandle, int rc, __LIBC_FORKCTX enmCtx, unsigned volatile *piCompletionCallback) 1606 { 1330 1607 /* 1331 1608 * Call completion callbacks in reverse registration order. … … 1337 1614 __LIBC_PFORKCOMPLETIONCALLBACK papfn = pForkHandle->papfnCompletionCallbacks; 1338 1615 unsigned iCC; 1339 for (iCC = 0; iCC < cCCs; iCC++) 1340 { 1616 while ((iCC = *piCompletionCallback) < cCCs) 1617 { 1618 *piCompletionCallback += 1; 1341 1619 if ( papfn[iCC].enmContext == __LIBC_FORK_CTX_BOTH 1342 1620 || papfn[iCC].enmContext == enmCtx) … … 1465 1743 pChunk->pv = pvStart; 1466 1744 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) 1469 1747 pChunk->offData = 0; /* fixme: probably could do this without if's. */ 1470 1748 … … 1506 1784 break; /* need to flush the buffer. */ 1507 1785 } 1508 forkBthCopyPages(&pChunk->achData[pChunk->offData], pvStart, pChunk->cb);1786 pfnForkBthCopyPages(&pChunk->achData[pChunk->offData], pvStart, pChunk->cb); 1509 1787 } 1510 1788 else … … 1575 1853 break; /* need to flush the buffer. */ 1576 1854 } 1577 forkBthCopyPages(&pChunk->achData[pChunk->offData], pvStart, pChunk->cb);1855 pfnForkBthCopyPages(&pChunk->achData[pChunk->offData], pvStart, pChunk->cb); 1578 1856 } 1579 1857 } … … 2107 2385 */ 2108 2386 if (pChunk->cb) 2109 forkBthCopyPages(pChunk->pv, &pChunk->achData[pChunk->offData], pChunk->cb);2387 pfnForkBthCopyPages(pChunk->pv, &pChunk->achData[pChunk->offData], pChunk->cb); 2110 2388 2111 2389 /* next */ … … 2295 2573 2296 2574 /** 2297 * Copy page memory .2298 * 2299 * @param pv TrgTarget address.2575 * Copy page memory, detect the right worker function and calls it. 2576 * 2577 * @param pvDst Target address. 2300 2578 * @param pvSrc Source address. 2301 2579 * @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 */ 2581 void 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 */ 2622 static 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); 2318 2625 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" 2322 2629 : "=&c" (r0), "=&D" (r1), "=&S" (r2) 2323 : "0" (cb / 4), "1" (pv Trg), "2" (pvSrc)2630 : "0" (cb / 4), "1" (pvDst), "2" (pvSrc) 2324 2631 : "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 */ 2644 static 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 ("\ 2650 1: \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 */ 2692 static 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 } 2327 2748 #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 */ 2758 static 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"); 2328 2804 LIBCLOG_RETURN_VOID(); 2329 2805 } 2806 #endif 2330 2807 2331 2808 … … 2590 3067 if (pXcptRepRec->fHandlerFlags & (EH_UNWINDING | EH_EXIT_UNWIND)) 2591 3068 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); 2593 3074 2594 3075 switch (pXcptRepRec->ExceptionNum) … … 2716 3197 DosGetInfoBlocks(&pTib, &pPib); 2717 3198 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); 2719 3204 2720 3205 switch (pXcptRepRec->ExceptionNum) -
Property cvs2svn:cvs-rev
changed from
Note:
See TracChangeset
for help on using the changeset viewer.