Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(293)

Side by Side Diff: mozilla/nsprpub/pr/src/md/windows/ntmisc.c

Issue 14249009: Change the NSS and NSPR source tree to the new directory structure to be (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/deps/third_party/nss/
Patch Set: Created 7 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « mozilla/nsprpub/pr/src/md/windows/ntinrval.c ('k') | mozilla/nsprpub/pr/src/md/windows/ntsec.c » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5
6 /*
7 * ntmisc.c
8 *
9 */
10
11 #include "primpl.h"
12 #include <math.h> /* for fabs() */
13 #include <windows.h>
14
15 char *_PR_MD_GET_ENV(const char *name)
16 {
17 return getenv(name);
18 }
19
20 /*
21 ** _PR_MD_PUT_ENV() -- add or change environment variable
22 **
23 **
24 */
25 PRIntn _PR_MD_PUT_ENV(const char *name)
26 {
27 return(putenv(name));
28 }
29
30
31 /*
32 **************************************************************************
33 **************************************************************************
34 **
35 ** Date and time routines
36 **
37 **************************************************************************
38 **************************************************************************
39 */
40
41 /*
42 * The NSPR epoch (00:00:00 1 Jan 1970 UTC) in FILETIME.
43 * We store the value in a PRTime variable for convenience.
44 */
45 #ifdef __GNUC__
46 const PRTime _pr_filetime_offset = 116444736000000000LL;
47 const PRTime _pr_filetime_divisor = 10LL;
48 #else
49 const PRTime _pr_filetime_offset = 116444736000000000i64;
50 const PRTime _pr_filetime_divisor = 10i64;
51 #endif
52
53 #ifdef WINCE
54
55 #define FILETIME_TO_INT64(ft) \
56 (((PRInt64)ft.dwHighDateTime) << 32 | (PRInt64)ft.dwLowDateTime)
57
58 static void
59 LowResTime(LPFILETIME lpft)
60 {
61 GetCurrentFT(lpft);
62 }
63
64 typedef struct CalibrationData {
65 long double freq; /* The performance counter frequency */
66 long double offset; /* The low res 'epoch' */
67 long double timer_offset; /* The high res 'epoch' */
68
69 /* The last high res time that we returned since recalibrating */
70 PRInt64 last;
71
72 PRBool calibrated;
73
74 CRITICAL_SECTION data_lock;
75 CRITICAL_SECTION calibration_lock;
76 PRInt64 granularity;
77 } CalibrationData;
78
79 static CalibrationData calibration;
80
81 typedef void (*GetSystemTimeAsFileTimeFcn)(LPFILETIME);
82 static GetSystemTimeAsFileTimeFcn ce6_GetSystemTimeAsFileTime = NULL;
83
84 static void
85 NowCalibrate(void)
86 {
87 FILETIME ft, ftStart;
88 LARGE_INTEGER liFreq, now;
89
90 if (calibration.freq == 0.0) {
91 if(!QueryPerformanceFrequency(&liFreq)) {
92 /* High-performance timer is unavailable */
93 calibration.freq = -1.0;
94 } else {
95 calibration.freq = (long double) liFreq.QuadPart;
96 }
97 }
98 if (calibration.freq > 0.0) {
99 PRInt64 calibrationDelta = 0;
100 /*
101 * By wrapping a timeBegin/EndPeriod pair of calls around this loop,
102 * the loop seems to take much less time (1 ms vs 15ms) on Vista.
103 */
104 timeBeginPeriod(1);
105 LowResTime(&ftStart);
106 do {
107 LowResTime(&ft);
108 } while (memcmp(&ftStart,&ft, sizeof(ft)) == 0);
109 timeEndPeriod(1);
110
111 calibration.granularity =
112 (FILETIME_TO_INT64(ft) - FILETIME_TO_INT64(ftStart))/10;
113
114 QueryPerformanceCounter(&now);
115
116 calibration.offset = (long double) FILETIME_TO_INT64(ft);
117 calibration.timer_offset = (long double) now.QuadPart;
118 /*
119 * The windows epoch is around 1600. The unix epoch is around 1970.
120 * _pr_filetime_offset is the difference (in windows time units which
121 * are 10 times more highres than the JS time unit)
122 */
123 calibration.offset -= _pr_filetime_offset;
124 calibration.offset *= 0.1;
125 calibration.last = 0;
126
127 calibration.calibrated = PR_TRUE;
128 }
129 }
130
131 #define CALIBRATIONLOCK_SPINCOUNT 0
132 #define DATALOCK_SPINCOUNT 4096
133 #define LASTLOCK_SPINCOUNT 4096
134
135 void
136 _MD_InitTime(void)
137 {
138 /* try for CE6 GetSystemTimeAsFileTime first */
139 HANDLE h = GetModuleHandleW(L"coredll.dll");
140 ce6_GetSystemTimeAsFileTime = (GetSystemTimeAsFileTimeFcn)
141 GetProcAddressA(h, "GetSystemTimeAsFileTime");
142
143 /* otherwise go the slow route */
144 if (ce6_GetSystemTimeAsFileTime == NULL) {
145 memset(&calibration, 0, sizeof(calibration));
146 NowCalibrate();
147 InitializeCriticalSection(&calibration.calibration_lock);
148 InitializeCriticalSection(&calibration.data_lock);
149 }
150 }
151
152 void
153 _MD_CleanupTime(void)
154 {
155 if (ce6_GetSystemTimeAsFileTime == NULL) {
156 DeleteCriticalSection(&calibration.calibration_lock);
157 DeleteCriticalSection(&calibration.data_lock);
158 }
159 }
160
161 #define MUTEX_SETSPINCOUNT(m, c)
162
163 /*
164 *-----------------------------------------------------------------------
165 *
166 * PR_Now --
167 *
168 * Returns the current time in microseconds since the epoch.
169 * The epoch is midnight January 1, 1970 GMT.
170 * The implementation is machine dependent. This is the
171 * implementation for Windows.
172 * Cf. time_t time(time_t *tp)
173 *
174 *-----------------------------------------------------------------------
175 */
176
177 PR_IMPLEMENT(PRTime)
178 PR_Now(void)
179 {
180 long double lowresTime, highresTimerValue;
181 FILETIME ft;
182 LARGE_INTEGER now;
183 PRBool calibrated = PR_FALSE;
184 PRBool needsCalibration = PR_FALSE;
185 PRInt64 returnedTime;
186 long double cachedOffset = 0.0;
187
188 if (ce6_GetSystemTimeAsFileTime) {
189 union {
190 FILETIME ft;
191 PRTime prt;
192 } currentTime;
193
194 PR_ASSERT(sizeof(FILETIME) == sizeof(PRTime));
195
196 ce6_GetSystemTimeAsFileTime(&currentTime.ft);
197
198 /* written this way on purpose, since the second term becomes
199 * a constant, and the entire expression is faster to execute.
200 */
201 return currentTime.prt/_pr_filetime_divisor -
202 _pr_filetime_offset/_pr_filetime_divisor;
203 }
204
205 do {
206 if (!calibration.calibrated || needsCalibration) {
207 EnterCriticalSection(&calibration.calibration_lock);
208 EnterCriticalSection(&calibration.data_lock);
209
210 /* Recalibrate only if no one else did before us */
211 if (calibration.offset == cachedOffset) {
212 /*
213 * Since calibration can take a while, make any other
214 * threads immediately wait
215 */
216 MUTEX_SETSPINCOUNT(&calibration.data_lock, 0);
217
218 NowCalibrate();
219
220 calibrated = PR_TRUE;
221
222 /* Restore spin count */
223 MUTEX_SETSPINCOUNT(&calibration.data_lock, DATALOCK_SPINCOUNT);
224 }
225 LeaveCriticalSection(&calibration.data_lock);
226 LeaveCriticalSection(&calibration.calibration_lock);
227 }
228
229 /* Calculate a low resolution time */
230 LowResTime(&ft);
231 lowresTime =
232 ((long double)(FILETIME_TO_INT64(ft) - _pr_filetime_offset)) * 0.1;
233
234 if (calibration.freq > 0.0) {
235 long double highresTime, diff;
236 DWORD timeAdjustment, timeIncrement;
237 BOOL timeAdjustmentDisabled;
238
239 /* Default to 15.625 ms if the syscall fails */
240 long double skewThreshold = 15625.25;
241
242 /* Grab high resolution time */
243 QueryPerformanceCounter(&now);
244 highresTimerValue = (long double)now.QuadPart;
245
246 EnterCriticalSection(&calibration.data_lock);
247 highresTime = calibration.offset + 1000000L *
248 (highresTimerValue-calibration.timer_offset)/calibration.freq;
249 cachedOffset = calibration.offset;
250
251 /*
252 * On some dual processor/core systems, we might get an earlier
253 * time so we cache the last time that we returned.
254 */
255 calibration.last = PR_MAX(calibration.last,(PRInt64)highresTime);
256 returnedTime = calibration.last;
257 LeaveCriticalSection(&calibration.data_lock);
258
259 /* Get an estimate of clock ticks per second from our own test */
260 skewThreshold = calibration.granularity;
261 /* Check for clock skew */
262 diff = lowresTime - highresTime;
263
264 /*
265 * For some reason that I have not determined, the skew can be
266 * up to twice a kernel tick. This does not seem to happen by
267 * itself, but I have only seen it triggered by another program
268 * doing some kind of file I/O. The symptoms are a negative diff
269 * followed by an equally large positive diff.
270 */
271 if (fabs(diff) > 2*skewThreshold) {
272 if (calibrated) {
273 /*
274 * If we already calibrated once this instance, and the
275 * clock is still skewed, then either the processor(s) are
276 * wildly changing clockspeed or the system is so busy that
277 * we get switched out for long periods of time. In either
278 * case, it would be infeasible to make use of high
279 * resolution results for anything, so let's resort to old
280 * behavior for this call. It's possible that in the
281 * future, the user will want the high resolution timer, so
282 * we don't disable it entirely.
283 */
284 returnedTime = (PRInt64)lowresTime;
285 needsCalibration = PR_FALSE;
286 } else {
287 /*
288 * It is possible that when we recalibrate, we will return
289 * a value less than what we have returned before; this is
290 * unavoidable. We cannot tell the different between a
291 * faulty QueryPerformanceCounter implementation and user
292 * changes to the operating system time. Since we must
293 * respect user changes to the operating system time, we
294 * cannot maintain the invariant that Date.now() never
295 * decreases; the old implementation has this behavior as
296 * well.
297 */
298 needsCalibration = PR_TRUE;
299 }
300 } else {
301 /* No detectable clock skew */
302 returnedTime = (PRInt64)highresTime;
303 needsCalibration = PR_FALSE;
304 }
305 } else {
306 /* No high resolution timer is available, so fall back */
307 returnedTime = (PRInt64)lowresTime;
308 }
309 } while (needsCalibration);
310
311 return returnedTime;
312 }
313
314 #else
315
316 PR_IMPLEMENT(PRTime)
317 PR_Now(void)
318 {
319 PRTime prt;
320 FILETIME ft;
321 SYSTEMTIME st;
322
323 GetSystemTime(&st);
324 SystemTimeToFileTime(&st, &ft);
325 _PR_FileTimeToPRTime(&ft, &prt);
326 return prt;
327 }
328
329 #endif
330
331 /*
332 ***********************************************************************
333 ***********************************************************************
334 *
335 * Process creation routines
336 *
337 ***********************************************************************
338 ***********************************************************************
339 */
340
341 /*
342 * Assemble the command line by concatenating the argv array.
343 * On success, this function returns 0 and the resulting command
344 * line is returned in *cmdLine. On failure, it returns -1.
345 */
346 static int assembleCmdLine(char *const *argv, char **cmdLine)
347 {
348 char *const *arg;
349 char *p, *q;
350 size_t cmdLineSize;
351 int numBackslashes;
352 int i;
353 int argNeedQuotes;
354
355 /*
356 * Find out how large the command line buffer should be.
357 */
358 cmdLineSize = 0;
359 for (arg = argv; *arg; arg++) {
360 /*
361 * \ and " need to be escaped by a \. In the worst case,
362 * every character is a \ or ", so the string of length
363 * may double. If we quote an argument, that needs two ".
364 * Finally, we need a space between arguments, and
365 * a null byte at the end of command line.
366 */
367 cmdLineSize += 2 * strlen(*arg) /* \ and " need to be escaped */
368 + 2 /* we quote every argument */
369 + 1; /* space in between, or final null */
370 }
371 p = *cmdLine = PR_MALLOC((PRUint32) cmdLineSize);
372 if (p == NULL) {
373 return -1;
374 }
375
376 for (arg = argv; *arg; arg++) {
377 /* Add a space to separates the arguments */
378 if (arg != argv) {
379 *p++ = ' ';
380 }
381 q = *arg;
382 numBackslashes = 0;
383 argNeedQuotes = 0;
384
385 /*
386 * If the argument is empty or contains white space, it needs to
387 * be quoted.
388 */
389 if (**arg == '\0' || strpbrk(*arg, " \f\n\r\t\v")) {
390 argNeedQuotes = 1;
391 }
392
393 if (argNeedQuotes) {
394 *p++ = '"';
395 }
396 while (*q) {
397 if (*q == '\\') {
398 numBackslashes++;
399 q++;
400 } else if (*q == '"') {
401 if (numBackslashes) {
402 /*
403 * Double the backslashes since they are followed
404 * by a quote
405 */
406 for (i = 0; i < 2 * numBackslashes; i++) {
407 *p++ = '\\';
408 }
409 numBackslashes = 0;
410 }
411 /* To escape the quote */
412 *p++ = '\\';
413 *p++ = *q++;
414 } else {
415 if (numBackslashes) {
416 /*
417 * Backslashes are not followed by a quote, so
418 * don't need to double the backslashes.
419 */
420 for (i = 0; i < numBackslashes; i++) {
421 *p++ = '\\';
422 }
423 numBackslashes = 0;
424 }
425 *p++ = *q++;
426 }
427 }
428
429 /* Now we are at the end of this argument */
430 if (numBackslashes) {
431 /*
432 * Double the backslashes if we have a quote string
433 * delimiter at the end.
434 */
435 if (argNeedQuotes) {
436 numBackslashes *= 2;
437 }
438 for (i = 0; i < numBackslashes; i++) {
439 *p++ = '\\';
440 }
441 }
442 if (argNeedQuotes) {
443 *p++ = '"';
444 }
445 }
446
447 *p = '\0';
448 return 0;
449 }
450
451 /*
452 * Assemble the environment block by concatenating the envp array
453 * (preserving the terminating null byte in each array element)
454 * and adding a null byte at the end.
455 *
456 * Returns 0 on success. The resulting environment block is returned
457 * in *envBlock. Note that if envp is NULL, a NULL pointer is returned
458 * in *envBlock. Returns -1 on failure.
459 */
460 static int assembleEnvBlock(char **envp, char **envBlock)
461 {
462 char *p;
463 char *q;
464 char **env;
465 char *curEnv;
466 char *cwdStart, *cwdEnd;
467 size_t envBlockSize;
468
469 if (envp == NULL) {
470 *envBlock = NULL;
471 return 0;
472 }
473
474 #ifdef WINCE
475 {
476 PRUnichar *wideCurEnv = mozce_GetEnvString();
477 int len = WideCharToMultiByte(CP_ACP, 0, wideCurEnv, -1,
478 NULL, 0, NULL, NULL);
479 curEnv = (char *) PR_MALLOC(len * sizeof(char));
480 WideCharToMultiByte(CP_ACP, 0, wideCurEnv, -1,
481 curEnv, len, NULL, NULL);
482 free(wideCurEnv);
483 }
484 #else
485 curEnv = GetEnvironmentStrings();
486 #endif
487
488 cwdStart = curEnv;
489 while (*cwdStart) {
490 if (cwdStart[0] == '=' && cwdStart[1] != '\0'
491 && cwdStart[2] == ':' && cwdStart[3] == '=') {
492 break;
493 }
494 cwdStart += strlen(cwdStart) + 1;
495 }
496 cwdEnd = cwdStart;
497 if (*cwdEnd) {
498 cwdEnd += strlen(cwdEnd) + 1;
499 while (*cwdEnd) {
500 if (cwdEnd[0] != '=' || cwdEnd[1] == '\0'
501 || cwdEnd[2] != ':' || cwdEnd[3] != '=') {
502 break;
503 }
504 cwdEnd += strlen(cwdEnd) + 1;
505 }
506 }
507 envBlockSize = cwdEnd - cwdStart;
508
509 for (env = envp; *env; env++) {
510 envBlockSize += strlen(*env) + 1;
511 }
512 envBlockSize++;
513
514 p = *envBlock = PR_MALLOC((PRUint32) envBlockSize);
515 if (p == NULL) {
516 #ifdef WINCE
517 PR_Free(curEnv);
518 #else
519 FreeEnvironmentStrings(curEnv);
520 #endif
521 return -1;
522 }
523
524 q = cwdStart;
525 while (q < cwdEnd) {
526 *p++ = *q++;
527 }
528 #ifdef WINCE
529 PR_Free(curEnv);
530 #else
531 FreeEnvironmentStrings(curEnv);
532 #endif
533
534 for (env = envp; *env; env++) {
535 q = *env;
536 while (*q) {
537 *p++ = *q++;
538 }
539 *p++ = '\0';
540 }
541 *p = '\0';
542 return 0;
543 }
544
545 /*
546 * For qsort. We sort (case-insensitive) the environment strings
547 * before generating the environment block.
548 */
549 static int compare(const void *arg1, const void *arg2)
550 {
551 return _stricmp(* (char**)arg1, * (char**)arg2);
552 }
553
554 PRProcess * _PR_CreateWindowsProcess(
555 const char *path,
556 char *const *argv,
557 char *const *envp,
558 const PRProcessAttr *attr)
559 {
560 #ifdef WINCE
561 STARTUPINFOW startupInfo;
562 PRUnichar *wideCmdLine;
563 PRUnichar *wideCwd;
564 int len = 0;
565 #else
566 STARTUPINFO startupInfo;
567 #endif
568 DWORD creationFlags = 0;
569 PROCESS_INFORMATION procInfo;
570 BOOL retVal;
571 char *cmdLine = NULL;
572 char *envBlock = NULL;
573 char **newEnvp = NULL;
574 const char *cwd = NULL; /* current working directory */
575 PRProcess *proc = NULL;
576 PRBool hasFdInheritBuffer;
577
578 proc = PR_NEW(PRProcess);
579 if (!proc) {
580 PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
581 goto errorExit;
582 }
583
584 if (assembleCmdLine(argv, &cmdLine) == -1) {
585 PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
586 goto errorExit;
587 }
588
589 #ifndef WINCE
590 /*
591 * If attr->fdInheritBuffer is not NULL, we need to insert
592 * it into the envp array, so envp cannot be NULL.
593 */
594 hasFdInheritBuffer = (attr && attr->fdInheritBuffer);
595 if ((envp == NULL) && hasFdInheritBuffer) {
596 envp = environ;
597 }
598
599 if (envp != NULL) {
600 int idx;
601 int numEnv;
602 PRBool found = PR_FALSE;
603
604 numEnv = 0;
605 while (envp[numEnv]) {
606 numEnv++;
607 }
608 newEnvp = (char **) PR_MALLOC((numEnv + 2) * sizeof(char *));
609 for (idx = 0; idx < numEnv; idx++) {
610 newEnvp[idx] = envp[idx];
611 if (hasFdInheritBuffer && !found
612 && !strncmp(newEnvp[idx], "NSPR_INHERIT_FDS=", 17)) {
613 newEnvp[idx] = attr->fdInheritBuffer;
614 found = PR_TRUE;
615 }
616 }
617 if (hasFdInheritBuffer && !found) {
618 newEnvp[idx++] = attr->fdInheritBuffer;
619 }
620 newEnvp[idx] = NULL;
621 qsort((void *) newEnvp, (size_t) idx, sizeof(char *), compare);
622 }
623 if (assembleEnvBlock(newEnvp, &envBlock) == -1) {
624 PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
625 goto errorExit;
626 }
627
628 ZeroMemory(&startupInfo, sizeof(startupInfo));
629 startupInfo.cb = sizeof(startupInfo);
630
631 if (attr) {
632 PRBool redirected = PR_FALSE;
633
634 /*
635 * XXX the default value for stdin, stdout, and stderr
636 * should probably be the console input and output, not
637 * those of the parent process.
638 */
639 startupInfo.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
640 startupInfo.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
641 startupInfo.hStdError = GetStdHandle(STD_ERROR_HANDLE);
642 if (attr->stdinFd) {
643 startupInfo.hStdInput = (HANDLE) attr->stdinFd->secret->md.osfd;
644 redirected = PR_TRUE;
645 }
646 if (attr->stdoutFd) {
647 startupInfo.hStdOutput = (HANDLE) attr->stdoutFd->secret->md.osfd;
648 redirected = PR_TRUE;
649 /*
650 * If stdout is redirected, we can assume that the process will
651 * not write anything useful to the console windows, and therefore
652 * automatically set the CREATE_NO_WINDOW flag.
653 */
654 creationFlags |= CREATE_NO_WINDOW;
655 }
656 if (attr->stderrFd) {
657 startupInfo.hStdError = (HANDLE) attr->stderrFd->secret->md.osfd;
658 redirected = PR_TRUE;
659 }
660 if (redirected) {
661 startupInfo.dwFlags |= STARTF_USESTDHANDLES;
662 }
663 cwd = attr->currentDirectory;
664 }
665 #endif
666
667 #ifdef WINCE
668 len = MultiByteToWideChar(CP_ACP, 0, cmdLine, -1, NULL, 0);
669 wideCmdLine = (PRUnichar *)PR_MALLOC(len * sizeof(PRUnichar));
670 MultiByteToWideChar(CP_ACP, 0, cmdLine, -1, wideCmdLine, len);
671 len = MultiByteToWideChar(CP_ACP, 0, cwd, -1, NULL, 0);
672 wideCwd = PR_MALLOC(len * sizeof(PRUnichar));
673 MultiByteToWideChar(CP_ACP, 0, cwd, -1, wideCwd, len);
674 retVal = CreateProcessW(NULL,
675 wideCmdLine,
676 NULL, /* security attributes for the new
677 * process */
678 NULL, /* security attributes for the primary
679 * thread in the new process */
680 TRUE, /* inherit handles */
681 creationFlags,
682 envBlock, /* an environment block, consisting
683 * of a null-terminated block of
684 * null-terminated strings. Each
685 * string is in the form:
686 * name=value
687 * XXX: usually NULL */
688 wideCwd, /* current drive and directory */
689 &startupInfo,
690 &procInfo
691 );
692 PR_Free(wideCmdLine);
693 PR_Free(wideCwd);
694 #else
695 retVal = CreateProcess(NULL,
696 cmdLine,
697 NULL, /* security attributes for the new
698 * process */
699 NULL, /* security attributes for the primary
700 * thread in the new process */
701 TRUE, /* inherit handles */
702 creationFlags,
703 envBlock, /* an environment block, consisting
704 * of a null-terminated block of
705 * null-terminated strings. Each
706 * string is in the form:
707 * name=value
708 * XXX: usually NULL */
709 cwd, /* current drive and directory */
710 &startupInfo,
711 &procInfo
712 );
713 #endif
714
715 if (retVal == FALSE) {
716 /* XXX what error code? */
717 PR_SetError(PR_UNKNOWN_ERROR, GetLastError());
718 goto errorExit;
719 }
720
721 CloseHandle(procInfo.hThread);
722 proc->md.handle = procInfo.hProcess;
723 proc->md.id = procInfo.dwProcessId;
724
725 PR_DELETE(cmdLine);
726 if (newEnvp) {
727 PR_DELETE(newEnvp);
728 }
729 if (envBlock) {
730 PR_DELETE(envBlock);
731 }
732 return proc;
733
734 errorExit:
735 if (cmdLine) {
736 PR_DELETE(cmdLine);
737 }
738 if (newEnvp) {
739 PR_DELETE(newEnvp);
740 }
741 if (envBlock) {
742 PR_DELETE(envBlock);
743 }
744 if (proc) {
745 PR_DELETE(proc);
746 }
747 return NULL;
748 } /* _PR_CreateWindowsProcess */
749
750 PRStatus _PR_DetachWindowsProcess(PRProcess *process)
751 {
752 CloseHandle(process->md.handle);
753 PR_DELETE(process);
754 return PR_SUCCESS;
755 }
756
757 /*
758 * XXX: This implementation is a temporary quick solution.
759 * It can be called by native threads only (not by fibers).
760 */
761 PRStatus _PR_WaitWindowsProcess(PRProcess *process,
762 PRInt32 *exitCode)
763 {
764 DWORD dwRetVal;
765
766 dwRetVal = WaitForSingleObject(process->md.handle, INFINITE);
767 if (dwRetVal == WAIT_FAILED) {
768 PR_SetError(PR_UNKNOWN_ERROR, GetLastError());
769 return PR_FAILURE;
770 }
771 PR_ASSERT(dwRetVal == WAIT_OBJECT_0);
772 if (exitCode != NULL &&
773 GetExitCodeProcess(process->md.handle, exitCode) == FALSE) {
774 PR_SetError(PR_UNKNOWN_ERROR, GetLastError());
775 return PR_FAILURE;
776 }
777 CloseHandle(process->md.handle);
778 PR_DELETE(process);
779 return PR_SUCCESS;
780 }
781
782 PRStatus _PR_KillWindowsProcess(PRProcess *process)
783 {
784 /*
785 * On Unix, if a process terminates normally, its exit code is
786 * between 0 and 255. So here on Windows, we use the exit code
787 * 256 to indicate that the process is killed.
788 */
789 if (TerminateProcess(process->md.handle, 256)) {
790 return PR_SUCCESS;
791 }
792 PR_SetError(PR_UNKNOWN_ERROR, GetLastError());
793 return PR_FAILURE;
794 }
795
796 PRStatus _MD_WindowsGetHostName(char *name, PRUint32 namelen)
797 {
798 PRIntn rv;
799 PRInt32 syserror;
800
801 rv = gethostname(name, (PRInt32) namelen);
802 if (0 == rv) {
803 return PR_SUCCESS;
804 }
805 syserror = WSAGetLastError();
806 PR_ASSERT(WSANOTINITIALISED != syserror);
807 _PR_MD_MAP_GETHOSTNAME_ERROR(syserror);
808 return PR_FAILURE;
809 }
810
811 PRStatus _MD_WindowsGetSysInfo(PRSysInfo cmd, char *name, PRUint32 namelen)
812 {
813 OSVERSIONINFO osvi;
814
815 PR_ASSERT((cmd == PR_SI_SYSNAME) || (cmd == PR_SI_RELEASE));
816
817 ZeroMemory(&osvi, sizeof(OSVERSIONINFO));
818 osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
819
820 if (! GetVersionEx (&osvi) ) {
821 _PR_MD_MAP_DEFAULT_ERROR(GetLastError());
822 return PR_FAILURE;
823 }
824
825 switch (osvi.dwPlatformId) {
826 case VER_PLATFORM_WIN32_NT:
827 if (PR_SI_SYSNAME == cmd)
828 (void)PR_snprintf(name, namelen, "Windows_NT");
829 else if (PR_SI_RELEASE == cmd)
830 (void)PR_snprintf(name, namelen, "%d.%d",osvi.dw MajorVersion,
831 osvi.dwMinorVers ion);
832 break;
833 case VER_PLATFORM_WIN32_WINDOWS:
834 if (PR_SI_SYSNAME == cmd) {
835 if ((osvi.dwMajorVersion > 4) ||
836 ((osvi.dwMajorVersion == 4) && (osvi.dwM inorVersion > 0)))
837 (void)PR_snprintf(name, namelen, "Window s_98");
838 else
839 (void)PR_snprintf(name, namelen, "Window s_95");
840 } else if (PR_SI_RELEASE == cmd) {
841 (void)PR_snprintf(name, namelen, "%d.%d",osvi.dw MajorVersion,
842 osvi.dwMinorVers ion);
843 }
844 break;
845 #ifdef VER_PLATFORM_WIN32_CE
846 case VER_PLATFORM_WIN32_CE:
847 if (PR_SI_SYSNAME == cmd)
848 (void)PR_snprintf(name, namelen, "Windows_CE");
849 else if (PR_SI_RELEASE == cmd)
850 (void)PR_snprintf(name, namelen, "%d.%d",osvi.dw MajorVersion,
851 osvi.dwMinorVers ion);
852 break;
853 #endif
854 default:
855 if (PR_SI_SYSNAME == cmd)
856 (void)PR_snprintf(name, namelen, "Windows_Unknow n");
857 else if (PR_SI_RELEASE == cmd)
858 (void)PR_snprintf(name, namelen, "%d.%d",0,0);
859 break;
860 }
861 return PR_SUCCESS;
862 }
863
864 PRStatus _MD_WindowsGetReleaseName(char *name, PRUint32 namelen)
865 {
866 OSVERSIONINFO osvi;
867
868 ZeroMemory(&osvi, sizeof(OSVERSIONINFO));
869 osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
870
871 if (! GetVersionEx (&osvi) ) {
872 _PR_MD_MAP_DEFAULT_ERROR(GetLastError());
873 return PR_FAILURE;
874 }
875
876 switch (osvi.dwPlatformId) {
877 case VER_PLATFORM_WIN32_NT:
878 case VER_PLATFORM_WIN32_WINDOWS:
879 (void)PR_snprintf(name, namelen, "%d.%d",osvi.dwMajorVer sion,
880 osvi.dwMinorVers ion);
881 break;
882 default:
883 (void)PR_snprintf(name, namelen, "%d.%d",0,0);
884 break;
885 }
886 return PR_SUCCESS;
887 }
888
889 /*
890 **********************************************************************
891 *
892 * Memory-mapped files
893 *
894 **********************************************************************
895 */
896
897 PRStatus _MD_CreateFileMap(PRFileMap *fmap, PRInt64 size)
898 {
899 DWORD dwHi, dwLo;
900 DWORD flProtect;
901 PROsfd osfd;
902
903 osfd = ( fmap->fd == (PRFileDesc*)-1 )? -1 : fmap->fd->secret->md.osfd;
904
905 dwLo = (DWORD) (size & 0xffffffff);
906 dwHi = (DWORD) (((PRUint64) size >> 32) & 0xffffffff);
907
908 if (fmap->prot == PR_PROT_READONLY) {
909 flProtect = PAGE_READONLY;
910 fmap->md.dwAccess = FILE_MAP_READ;
911 } else if (fmap->prot == PR_PROT_READWRITE) {
912 flProtect = PAGE_READWRITE;
913 fmap->md.dwAccess = FILE_MAP_WRITE;
914 } else {
915 PR_ASSERT(fmap->prot == PR_PROT_WRITECOPY);
916 #ifdef WINCE
917 /* WINCE does not have FILE_MAP_COPY. */
918 PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
919 return PR_FAILURE;
920 #else
921 flProtect = PAGE_WRITECOPY;
922 fmap->md.dwAccess = FILE_MAP_COPY;
923 #endif
924 }
925
926 fmap->md.hFileMap = CreateFileMapping(
927 (HANDLE) osfd,
928 NULL,
929 flProtect,
930 dwHi,
931 dwLo,
932 NULL);
933
934 if (fmap->md.hFileMap == NULL) {
935 PR_SetError(PR_UNKNOWN_ERROR, GetLastError());
936 return PR_FAILURE;
937 }
938 return PR_SUCCESS;
939 }
940
941 PRInt32 _MD_GetMemMapAlignment(void)
942 {
943 SYSTEM_INFO info;
944 GetSystemInfo(&info);
945 return info.dwAllocationGranularity;
946 }
947
948 extern PRLogModuleInfo *_pr_shma_lm;
949
950 void * _MD_MemMap(
951 PRFileMap *fmap,
952 PROffset64 offset,
953 PRUint32 len)
954 {
955 DWORD dwHi, dwLo;
956 void *addr;
957
958 dwLo = (DWORD) (offset & 0xffffffff);
959 dwHi = (DWORD) (((PRUint64) offset >> 32) & 0xffffffff);
960 if ((addr = MapViewOfFile(fmap->md.hFileMap, fmap->md.dwAccess,
961 dwHi, dwLo, len)) == NULL) {
962 {
963 LPVOID lpMsgBuf;
964
965 FormatMessage(
966 FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
967 NULL,
968 GetLastError(),
969 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
970 (LPTSTR) &lpMsgBuf,
971 0,
972 NULL
973 );
974 PR_LOG( _pr_shma_lm, PR_LOG_DEBUG, ("md_memmap(): %s", lpMsgBuf ));
975 }
976 PR_SetError(PR_UNKNOWN_ERROR, GetLastError());
977 }
978 return addr;
979 }
980
981 PRStatus _MD_MemUnmap(void *addr, PRUint32 len)
982 {
983 if (UnmapViewOfFile(addr)) {
984 return PR_SUCCESS;
985 } else {
986 PR_SetError(PR_UNKNOWN_ERROR, GetLastError());
987 return PR_FAILURE;
988 }
989 }
990
991 PRStatus _MD_CloseFileMap(PRFileMap *fmap)
992 {
993 CloseHandle(fmap->md.hFileMap);
994 PR_DELETE(fmap);
995 return PR_SUCCESS;
996 }
997
998 /*
999 ***********************************************************************
1000 *
1001 * Atomic increment and decrement operations for x86 processors
1002 *
1003 * We don't use InterlockedIncrement and InterlockedDecrement
1004 * because on NT 3.51 and Win95, they return a number with
1005 * the same sign as the incremented/decremented result, rather
1006 * than the result itself. On NT 4.0 these functions do return
1007 * the incremented/decremented result.
1008 *
1009 * The result is returned in the eax register by the inline
1010 * assembly code. We disable the harmless "no return value"
1011 * warning (4035) for these two functions.
1012 *
1013 ***********************************************************************
1014 */
1015
1016 #if defined(_M_IX86) || defined(_X86_)
1017
1018 #pragma warning(disable: 4035)
1019 PRInt32 _PR_MD_ATOMIC_INCREMENT(PRInt32 *val)
1020 {
1021 #if defined(__GNUC__)
1022 PRInt32 result;
1023 asm volatile ("lock ; xadd %0, %1"
1024 : "=r"(result), "=m"(*val)
1025 : "0"(1), "m"(*val));
1026 return result + 1;
1027 #else
1028 __asm
1029 {
1030 mov ecx, val
1031 mov eax, 1
1032 lock xadd dword ptr [ecx], eax
1033 inc eax
1034 }
1035 #endif /* __GNUC__ */
1036 }
1037 #pragma warning(default: 4035)
1038
1039 #pragma warning(disable: 4035)
1040 PRInt32 _PR_MD_ATOMIC_DECREMENT(PRInt32 *val)
1041 {
1042 #if defined(__GNUC__)
1043 PRInt32 result;
1044 asm volatile ("lock ; xadd %0, %1"
1045 : "=r"(result), "=m"(*val)
1046 : "0"(-1), "m"(*val));
1047 //asm volatile("lock ; xadd %0, %1" : "=m" (val), "=a" (result) : "-1" (1));
1048 return result - 1;
1049 #else
1050 __asm
1051 {
1052 mov ecx, val
1053 mov eax, 0ffffffffh
1054 lock xadd dword ptr [ecx], eax
1055 dec eax
1056 }
1057 #endif /* __GNUC__ */
1058 }
1059 #pragma warning(default: 4035)
1060
1061 #pragma warning(disable: 4035)
1062 PRInt32 _PR_MD_ATOMIC_ADD(PRInt32 *intp, PRInt32 val)
1063 {
1064 #if defined(__GNUC__)
1065 PRInt32 result;
1066 //asm volatile("lock ; xadd %1, %0" : "=m" (intp), "=a" (result) : "1" (val));
1067 asm volatile ("lock ; xadd %0, %1"
1068 : "=r"(result), "=m"(*intp)
1069 : "0"(val), "m"(*intp));
1070 return result + val;
1071 #else
1072 __asm
1073 {
1074 mov ecx, intp
1075 mov eax, val
1076 mov edx, eax
1077 lock xadd dword ptr [ecx], eax
1078 add eax, edx
1079 }
1080 #endif /* __GNUC__ */
1081 }
1082 #pragma warning(default: 4035)
1083
1084 #ifdef _PR_HAVE_ATOMIC_CAS
1085
1086 #pragma warning(disable: 4035)
1087 void
1088 PR_StackPush(PRStack *stack, PRStackElem *stack_elem)
1089 {
1090 #if defined(__GNUC__)
1091 void **tos = (void **) stack;
1092 void *tmp;
1093
1094 retry:
1095 if (*tos == (void *) -1)
1096 goto retry;
1097
1098 __asm__("xchg %0,%1"
1099 : "=r" (tmp), "=m"(*tos)
1100 : "0" (-1), "m"(*tos));
1101
1102 if (tmp == (void *) -1)
1103 goto retry;
1104
1105 *(void **)stack_elem = tmp;
1106 __asm__("" : : : "memory");
1107 *tos = stack_elem;
1108 #else
1109 __asm
1110 {
1111 mov ebx, stack
1112 mov ecx, stack_elem
1113 retry: mov eax,[ebx]
1114 cmp eax,-1
1115 je retry
1116 mov eax,-1
1117 xchg dword ptr [ebx], eax
1118 cmp eax,-1
1119 je retry
1120 mov [ecx],eax
1121 mov [ebx],ecx
1122 }
1123 #endif /* __GNUC__ */
1124 }
1125 #pragma warning(default: 4035)
1126
1127 #pragma warning(disable: 4035)
1128 PRStackElem *
1129 PR_StackPop(PRStack *stack)
1130 {
1131 #if defined(__GNUC__)
1132 void **tos = (void **) stack;
1133 void *tmp;
1134
1135 retry:
1136 if (*tos == (void *) -1)
1137 goto retry;
1138
1139 __asm__("xchg %0,%1"
1140 : "=r" (tmp), "=m"(*tos)
1141 : "0" (-1), "m"(*tos));
1142
1143 if (tmp == (void *) -1)
1144 goto retry;
1145
1146 if (tmp != (void *) 0)
1147 {
1148 void *next = *(void **)tmp;
1149 *tos = next;
1150 *(void **)tmp = 0;
1151 }
1152 else
1153 *tos = tmp;
1154
1155 return tmp;
1156 #else
1157 __asm
1158 {
1159 mov ebx, stack
1160 retry: mov eax,[ebx]
1161 cmp eax,-1
1162 je retry
1163 mov eax,-1
1164 xchg dword ptr [ebx], eax
1165 cmp eax,-1
1166 je retry
1167 cmp eax,0
1168 je empty
1169 mov ecx,[eax]
1170 mov [ebx],ecx
1171 mov [eax],0
1172 jmp done
1173 empty:
1174 mov [ebx],eax
1175 done:
1176 }
1177 #endif /* __GNUC__ */
1178 }
1179 #pragma warning(default: 4035)
1180
1181 #endif /* _PR_HAVE_ATOMIC_CAS */
1182
1183 #endif /* x86 processors */
OLDNEW
« no previous file with comments | « mozilla/nsprpub/pr/src/md/windows/ntinrval.c ('k') | mozilla/nsprpub/pr/src/md/windows/ntsec.c » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698