Changeset 3159 for trunk/src/kmk
- Timestamp:
- Mar 19, 2018, 2:37:13 PM (7 years ago)
- Location:
- trunk/src/kmk
- Files:
-
- 10 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/kmk/function.c
r3156 r3159 3058 3058 { 3059 3059 FILE *fp; 3060 #ifdef KMK_FOPEN_NO_INHERIT_MODE 3061 const char *mode = "w" KMK_FOPEN_NO_INHERIT_MODE; 3062 #else 3060 3063 const char *mode = "w"; 3064 #endif 3061 3065 3062 3066 /* We are writing a file. */ … … 3064 3068 if (fn[0] == '>') 3065 3069 { 3070 #ifdef KMK_FOPEN_NO_INHERIT_MODE 3071 mode = "a" KMK_FOPEN_NO_INHERIT_MODE; 3072 #else 3066 3073 mode = "a"; 3074 #endif 3067 3075 ++fn; 3068 3076 } … … 3100 3108 O (fatal, *expanding_var, _("file: too many arguments")); 3101 3109 3110 #ifdef KMK_FOPEN_NO_INHERIT_MODE 3111 ENULLLOOP (fp, fopen (fn, "r" KMK_FOPEN_NO_INHERIT_MODE)); 3112 #else 3102 3113 ENULLLOOP (fp, fopen (fn, "r")); 3114 #endif 3103 3115 if (fp == NULL) 3104 3116 { -
trunk/src/kmk/job.c
r3156 r3159 42 42 int no_default_sh_exe = 1; 43 43 int batch_mode_shell = 1; 44 # ifndef CONFIG_NEW_WIN32_CTRL_EVENT 44 45 HANDLE main_thread; 46 # endif 45 47 46 48 #elif defined (_AMIGA) … … 813 815 #endif /* _AMIGA */ 814 816 #ifdef WINDOWS32 817 { 815 818 # ifndef CONFIG_NEW_WIN_CHILDREN 816 {817 819 HANDLE hPID; 818 820 HANDLE hcTID, hcPID; … … 822 824 coredump = 0; 823 825 826 # ifndef CONFIG_NEW_WIN32_CTRL_EVENT 824 827 /* Record the thread ID of the main process, so that we 825 828 could suspend it in the signal handler. */ … … 839 842 DB (DB_VERBOSE, ("Main thread handle = %p\n", main_thread)); 840 843 } 844 # endif 841 845 842 846 /* wait for anything to finish */ … … 875 879 876 880 pid = (pid_t) hPID; 881 # else /* CONFIG_NEW_WIN_CHILDREN */ 882 # ifndef CONFIG_NEW_WIN32_CTRL_EVENT 883 /* Ctrl-C handler needs to suspend the main thread handle to 884 prevent mayhem when concurrently calling reap_children. */ 885 if ( !main_thread 886 && !DuplicateHandle (GetCurrentProcess (), GetCurrentThread (), 887 GetCurrentProcess (), &main_thread, 0, 888 FALSE, DUPLICATE_SAME_ACCESS)) 889 fprintf (stderr, "Failed to duplicate main thread handle: %u\n", 890 GetLastError ()); 891 # endif 892 893 assert (!any_remote); 894 pid = 0; 895 coredump = exit_sig = exit_code = 0; 896 { 897 int rc = MkWinChildWait(block, &pid, &exit_code, &exit_sig, &coredump, &c); 898 if (rc != 0) 899 ON (fatal, NILF, _("MkWinChildWait: %u"), rc); 900 } 901 if (pid == 0) 902 { 903 /* No more children, stop. */ 904 reap_more = 0; 905 break; 906 } 907 908 /* If we have started jobs in this second, remove one. */ 909 if (job_counter) 910 --job_counter; 911 # endif /* CONFIG_NEW_WIN_CHILDREN */ 877 912 } 878 # else /* CONFIG_NEW_WIN_CHILDREN */879 assert (!any_remote);880 pid = 0;881 coredump = exit_sig = exit_code = 0;882 {883 int rc = MkWinChildWait(block, &pid, &exit_code, &exit_sig, &coredump, &c);884 if (rc != 0)885 ON (fatal, NILF, _("MkWinChildWait: %u"), rc);886 }887 if (pid == 0)888 {889 /* No more children, stop. */890 reap_more = 0;891 break;892 }893 894 /* If we have started jobs in this second, remove one. */895 if (job_counter)896 --job_counter;897 # endif /* CONFIG_NEW_WIN_CHILDREN */898 913 #endif /* WINDOWS32 */ 899 914 } -
trunk/src/kmk/kmkbuiltin.h
r3108 r3159 47 47 #endif 48 48 49 /** This is for telling fopen() to get a close-on-exec handle. 50 * @todo glibc 2.7+ and recent cygwin supports 'e' for doing this. */ 51 #ifndef KMK_FOPEN_NO_INHERIT_MODE 52 # ifdef _MSC_VER 53 # define KMK_FOPEN_NO_INHERIT_MODE "N" 54 # else 55 # define KMK_FOPEN_NO_INHERIT_MODE "" 56 # endif 57 #endif 49 58 50 59 #include "kbuild_version.h" -
trunk/src/kmk/kmkbuiltin/append.c
r3141 r3159 190 190 191 191 /* 192 * Open the output file .192 * Open the output file, preferrably with close-on-exec. 193 193 */ 194 194 iFile = i; 195 pFile = fopen(argv[i], fTruncate ? "w" : "a"); 195 pFile = fopen(argv[i], 196 fTruncate ? "w" KMK_FOPEN_NO_INHERIT_MODE 197 : "a" KMK_FOPEN_NO_INHERIT_MODE); 196 198 if (!pFile) 197 199 return err(1, "failed to open '%s'", argv[i]); -
trunk/src/kmk/kmkbuiltin/kDepIDB.c
r2955 r3159 732 732 pOutput = stdout; 733 733 else 734 pOutput = fopen(pszOutput, "w" );734 pOutput = fopen(pszOutput, "w" KMK_FOPEN_NO_INHERIT_MODE); 735 735 if (!pOutput) 736 736 { … … 812 812 else 813 813 { 814 pInput = fopen(argv[i], "rb" );814 pInput = fopen(argv[i], "rb" KMK_FOPEN_NO_INHERIT_MODE); 815 815 if (!pInput) 816 816 { -
trunk/src/kmk/kmkbuiltin/md5sum.c
r3131 r3159 156 156 157 157 errno = 0; 158 pFile = fopen(pszFilename, fText ? "r" : "rb"); 158 pFile = fopen(pszFilename, 159 fText ? "r" KMK_FOPEN_NO_INHERIT_MODE 160 : "rb" KMK_FOPEN_NO_INHERIT_MODE); 159 161 if (!pFile && errno == EINVAL && !fText) 160 pFile = fopen(pszFilename, "r" );162 pFile = fopen(pszFilename, "r" KMK_FOPEN_NO_INHERIT_MODE); 161 163 return pFile; 162 164 … … 472 474 * Try open the md5.lst file and process it line by line. 473 475 */ 474 pFile = fopen(pszFilename, "r" );476 pFile = fopen(pszFilename, "r" KMK_FOPEN_NO_INHERIT_MODE); 475 477 if (pFile) 476 478 { … … 837 839 if (pOutput) 838 840 fclose(pOutput); 839 pOutput = fopen(pszOutput, "w" );841 pOutput = fopen(pszOutput, "w" KMK_FOPEN_NO_INHERIT_MODE); 840 842 if (!pOutput) 841 843 { 842 rc = err(1, "fopen(\"%s\", \"w \") failed", pszOutput);844 rc = err(1, "fopen(\"%s\", \"w" KMK_FOPEN_NO_INHERIT_MODE "\") failed", pszOutput); 843 845 break; 844 846 } -
trunk/src/kmk/kmkbuiltin/redirect.c
r3156 r3159 878 878 */ 879 879 FILE *pWorkingStdErr = NULL; 880 # if defined(CONFIG_NEW_WIN_CHILDREN) && defined(KMK) 881 if (cOrders > 0) 882 MkWinChildExclusiveAcquire(); 883 # endif 880 884 rcExit = kRedirectExecFdOrders(cOrders, paOrders, &pWorkingStdErr); 881 885 if (rcExit == 0) … … 890 894 HANDLE hProcess = (HANDLE)_spawnvpe(_P_NOWAIT, pszExecutable, papszArgs, papszEnvVars); 891 895 kRedirectRestoreFdOrders(cOrders, paOrders, &pWorkingStdErr); 896 # ifdef CONFIG_NEW_WIN_CHILDREN 897 if (cOrders > 0) 898 MkWinChildExclusiveRelease(); 899 # endif 892 900 if ((intptr_t)hProcess != -1) 893 901 { … … 1015 1023 #endif /* !KMK */ 1016 1024 } 1025 #if defined(CONFIG_NEW_WIN_CHILDREN) && defined(KBUILD_OS_WINDOWS) && defined(KMK) 1026 else if (cOrders > 0) 1027 MkWinChildExclusiveRelease(); 1028 #endif 1029 1017 1030 } 1018 1031 -
trunk/src/kmk/main.c
r3156 r3159 3129 3129 setrlimit (RLIMIT_STACK, &stack_limit); 3130 3130 #endif 3131 fprintf(stderr, "respawning 1..\n"); 3132 fprintf(stderr, "respawning 2..\n"); 3133 fprintf(stderr, "respawning 3..!\n"); 3131 3134 # if !defined(WINDOWS32) || !defined(CONFIG_NEW_WIN_CHILDREN) 3132 3135 exec_command ((char **)nargv, environ); -
trunk/src/kmk/w32/winchildren.c
r3158 r3159 25 25 26 26 /* No GNU coding style here atm, convert if upstreamed. */ 27 28 /** @page pg_win_children Windows child process creation and managment 29 * 30 * This new implementation aims at addressing the following: 31 * 32 * 1. Speed up process creation by doing the expensive CreateProcess call 33 * in a worker thread. 34 * 35 * 2. No 64 process limit imposed by WaitForMultipleObjects. 36 * 37 * 3. Better distribute jobs among processor groups. 38 * 39 * 4. Offloading more expensive kmkbuiltin operations to worker threads, 40 * making the main thread focus on managing child processes. 41 * 42 * 5. Output synchronization using reusable pipes [not yet implemented]. 43 * 44 * 45 * To be quite honest, the first item (CreateProcess expense) didn't occur to me 46 * at first and was more of a sideeffect discovered along the way. A test 47 * rebuilding IPRT went from 4m52s to 3m19s on a 8 thread system. 48 * 49 * The 2nd and 3rd goals are related to newer build servers that have lots of 50 * CPU threads and various Windows NT (aka NT OS/2 at the time) design choices 51 * made in the late 1980ies. 52 * 53 * WaitForMultipleObjects does not support waiting for more than 64 objects, 54 * unlike poll and select. This is just something everyone ends up having to 55 * work around in the end. 56 * 57 * Affinity masks are uintptr_t sized, so 64-bit hosts can only manage 64 58 * processors and 32-bit only 32. Workaround was introduced with Windows 7 59 * (IIRC) and is called processor groups. The CPU threads are grouped into 1 or 60 * more groups of up to 64 processors. Processes are generally scheduled to a 61 * signle processor group at first, but threads may be changed to be scheduled 62 * on different groups. This code will try distribute children evenly among the 63 * processor groups, using a very simple algorithm (see details in code). 64 * 65 */ 66 27 67 28 68 /********************************************************************************************************************************* … … 66 106 /** Normal child process. */ 67 107 WINCHILDTYPE_PROCESS, 108 #ifdef KMK 68 109 /** kmkbuiltin command. */ 69 110 WINCHILDTYPE_BUILTIN, … … 72 113 /** kmk_redirect job. */ 73 114 WINCHILDTYPE_REDIRECT, 115 #endif 74 116 /** End of valid child types. */ 75 117 WINCHILDTYPE_END … … 247 289 static unsigned volatile g_idxLastChildcareWorker = 0; 248 290 291 /** Temporary RW lock for serializing kmkbuiltin_redirect and CreateProcess. */ 292 static SRWLOCK g_RWLock; 249 293 250 294 … … 320 364 } 321 365 } 366 367 /* Temporary: */ 368 InitializeSRWLock(&g_RWLock); 322 369 } 323 370 … … 1205 1252 if (rc == 0) 1206 1253 { 1254 AcquireSRWLockShared(&g_RWLock); /* temporary */ 1255 1207 1256 /* 1208 1257 * Populate startup info. … … 1248 1297 TRUE /*fInheritHandles*/, fFlags, pwszzEnvironment, NULL /*pwsz*/, &StartupInfo, &ProcInfo); 1249 1298 rc = GetLastError(); 1299 ReleaseSRWLockShared(&g_RWLock); /* temporary */ 1250 1300 if (fRet) 1251 1301 { … … 1315 1365 } 1316 1366 1367 #ifdef KMK 1368 1317 1369 /** 1318 1370 * Childcare worker: handle builtin command. … … 1366 1418 mkWinChildcareWorkerWaitForProcess(pWorker, pChild, pChild->u.Redirect.hProcess); 1367 1419 } 1420 1421 #endif /* KMK */ 1368 1422 1369 1423 /** … … 1435 1489 mkWinChildcareWorkerThreadHandleProcess(pWorker, pChild); 1436 1490 break; 1491 #ifdef KMK 1437 1492 case WINCHILDTYPE_BUILTIN: 1438 1493 mkWinChildcareWorkerThreadHandleBuiltin(pWorker, pChild); … … 1444 1499 mkWinChildcareWorkerThreadHandleRedirect(pWorker, pChild); 1445 1500 break; 1501 #endif 1502 default: 1503 assert(0); 1446 1504 } 1447 1505 … … 1638 1696 } 1639 1697 1698 #ifdef KMK 1699 1640 1700 case WINCHILDTYPE_BUILTIN: 1641 1701 assert(0); … … 1657 1717 } 1658 1718 break; 1719 1720 #endif /* KMK */ 1721 1722 default: 1723 assert(0); 1659 1724 } 1660 1725 … … 1890 1955 } 1891 1956 1957 #ifdef KMK 1958 1892 1959 /** 1893 1960 * Interface used by kSubmit.c for registering stuff to wait on. … … 1919 1986 return mkWinChildPushToCareWorker(pChild, pPid); 1920 1987 } 1988 1989 #endif /* CONFIG_NEW_WIN_CHILDREN */ 1921 1990 1922 1991 /** … … 1943 2012 pChild->iSignal = iSignal; 1944 2013 break; 2014 2015 #ifdef KMK 1945 2016 1946 2017 case WINCHILDTYPE_SUBMIT: … … 1958 2029 case WINCHILDTYPE_BUILTIN: 1959 2030 break; 2031 2032 #endif /* KMK */ 2033 2034 default: 2035 assert(0); 1960 2036 } 1961 2037 } … … 2015 2091 case WINCHILDTYPE_PROCESS: 2016 2092 break; 2093 #ifdef KMK 2017 2094 case WINCHILDTYPE_BUILTIN: 2018 2095 break; … … 2021 2098 case WINCHILDTYPE_REDIRECT: 2022 2099 break; 2100 #endif /* KMK */ 2023 2101 default: 2024 2102 assert(0); 2025 2103 } 2026 2104 mkWinChildDelete(pChild); 2105 2106 #ifdef KMK 2107 /* Flush the volatile directory cache. */ 2108 dir_cache_invalid_after_job(); 2109 #endif 2027 2110 return 0; 2028 2111 } 2029 2112 2030 2113 /** 2114 * Get the child completed event handle. 2115 * 2116 * Needed when w32os.c is waiting for a job token to become available, given 2117 * that completed children is the typical source of these tokens (esp. for kmk). 2118 * 2119 * @returns Event handle. 2120 */ 2031 2121 intptr_t MkWinChildGetCompleteEventHandle(void) 2032 2122 { 2033 2123 return (intptr_t)g_hEvtWaitChildren; 2034 2124 } 2035 2036 2125 2037 2126 /** … … 2053 2142 int rc; 2054 2143 2055 /** @todo this code needs testing... */2056 2057 2144 /* 2058 2145 * Get the executable name. … … 2084 2171 GetStartupInfoW(&StartupInfo); 2085 2172 if (!CreateProcessW(wszImageName, pwszCommandLine, NULL /*pProcSecAttr*/, NULL /*pThreadSecAttr*/, 2086 TRUE /*fInheritHandles*/, 0 /*fFlags*/, pwszzEnvironment, NULL /*pwsz*/,2173 TRUE /*fInheritHandles*/, CREATE_UNICODE_ENVIRONMENT, pwszzEnvironment, NULL /*pwsz*/, 2087 2174 &StartupInfo, &ProcInfo)) 2088 2175 ON(fatal, NILF, _("MkWinChildReExecMake: CreateProcessW failed: %u\n"), GetLastError()); … … 2103 2190 if (dwStatus == WAIT_OBJECT_0) 2104 2191 { 2105 if (GetExitCodeProcess(ProcInfo.hProcess, &dwExitCode)) 2192 if (!GetExitCodeProcess(ProcInfo.hProcess, &dwExitCode)) 2193 { 2106 2194 ON(fatal, NILF, _("MkWinChildReExecMake: GetExitCodeProcess failed: %u\n"), GetLastError()); 2107 else2108 2195 dwExitCode = -2222; 2196 } 2109 2197 } 2110 2198 else if (dwStatus) … … 2117 2205 } 2118 2206 2119 2207 /** Temporary serialization with kmkbuiltin_redirect. */ 2208 void MkWinChildExclusiveAcquire(void) 2209 { 2210 AcquireSRWLockExclusive(&g_RWLock); 2211 } 2212 2213 /** Temporary serialization with kmkbuiltin_redirect. */ 2214 void MkWinChildExclusiveRelease(void) 2215 { 2216 ReleaseSRWLockExclusive(&g_RWLock); 2217 } 2218 2219 /** 2220 * Implementation of the CLOSE_ON_EXEC macro. 2221 * 2222 * @returns errno value. 2223 * @param fd The file descriptor to hide from children. 2224 */ 2120 2225 int MkWinChildUnrelatedCloseOnExec(int fd) 2121 2226 { … … 2128 2233 return 0; 2129 2234 } 2235 return errno; 2130 2236 } 2131 2237 return EINVAL; 2132 2238 } 2133 2239 2134 2135 -
trunk/src/kmk/w32/winchildren.h
r3156 r3159 36 36 int MkWinChildKill(pid_t pid, int iSignal, struct child *pMkChild); 37 37 int MkWinChildWait(int fBlock, pid_t *pPid, int *piExitCode, int *piSignal, int *pfCoreDumped, struct child **ppMkChild); 38 void MkWinChildExclusiveAcquire(void); 39 void MkWinChildExclusiveRelease(void); 38 40 39 41 #undef CLOSE_ON_EXEC
Note:
See TracChangeset
for help on using the changeset viewer.