VirtualBox

source: vbox/trunk/src/libs/xpcom18a4/nsprpub/pr/src/misc/prinit.c@ 101795

Last change on this file since 101795 was 101795, checked in by vboxsync, 16 months ago

libs/xpcom: Remove unused code because _PR_PTHREADS is always defined, bugref:10545

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 16.7 KB
Line 
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2/* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 *
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
9 *
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
13 * License.
14 *
15 * The Original Code is the Netscape Portable Runtime (NSPR).
16 *
17 * The Initial Developer of the Original Code is
18 * Netscape Communications Corporation.
19 * Portions created by the Initial Developer are Copyright (C) 1998-2000
20 * the Initial Developer. All Rights Reserved.
21 *
22 * Contributor(s):
23 *
24 * Alternatively, the contents of this file may be used under the terms of
25 * either the GNU General Public License Version 2 or later (the "GPL"), or
26 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 * in which case the provisions of the GPL or the LGPL are applicable instead
28 * of those above. If you wish to allow use of your version of this file only
29 * under the terms of either the GPL or the LGPL, and not to allow others to
30 * use your version of this file under the terms of the MPL, indicate your
31 * decision by deleting the provisions above and replace them with the notice
32 * and other provisions required by the GPL or the LGPL. If you do not delete
33 * the provisions above, a recipient may use your version of this file under
34 * the terms of any one of the MPL, the GPL or the LGPL.
35 *
36 * ***** END LICENSE BLOCK ***** */
37
38#include "primpl.h"
39#include <ctype.h>
40#include <string.h>
41#ifdef VBOX_USE_IPRT_IN_NSPR
42# include <iprt/initterm.h>
43#endif
44
45PRLogModuleInfo *_pr_clock_lm;
46PRLogModuleInfo *_pr_cmon_lm;
47PRLogModuleInfo *_pr_io_lm;
48PRLogModuleInfo *_pr_cvar_lm;
49PRLogModuleInfo *_pr_mon_lm;
50PRLogModuleInfo *_pr_linker_lm;
51PRLogModuleInfo *_pr_sched_lm;
52PRLogModuleInfo *_pr_thread_lm;
53PRLogModuleInfo *_pr_gc_lm;
54PRLogModuleInfo *_pr_shm_lm;
55PRLogModuleInfo *_pr_shma_lm;
56
57PRFileDesc *_pr_stdin;
58PRFileDesc *_pr_stdout;
59PRFileDesc *_pr_stderr;
60
61PRLock *_pr_sleeplock; /* used in PR_Sleep(), classic and pthreads */
62
63static void _PR_InitCallOnce(void);
64
65PRBool _pr_initialized = PR_FALSE;
66
67
68PR_IMPLEMENT(PRBool) PR_VersionCheck(const char *importedVersion)
69{
70 /*
71 ** This is the secret handshake algorithm.
72 **
73 ** This release has a simple version compatibility
74 ** check algorithm. This release is not backward
75 ** compatible with previous major releases. It is
76 ** not compatible with future major, minor, or
77 ** patch releases.
78 */
79 int vmajor = 0, vminor = 0, vpatch = 0;
80 const char *ptr = importedVersion;
81
82 while (isdigit(*ptr)) {
83 vmajor = 10 * vmajor + *ptr - '0';
84 ptr++;
85 }
86 if (*ptr == '.') {
87 ptr++;
88 while (isdigit(*ptr)) {
89 vminor = 10 * vminor + *ptr - '0';
90 ptr++;
91 }
92 if (*ptr == '.') {
93 ptr++;
94 while (isdigit(*ptr)) {
95 vpatch = 10 * vpatch + *ptr - '0';
96 ptr++;
97 }
98 }
99 }
100
101 if (vmajor != PR_VMAJOR) {
102 return PR_FALSE;
103 }
104 if (vmajor == PR_VMAJOR && vminor > PR_VMINOR) {
105 return PR_FALSE;
106 }
107 if (vmajor == PR_VMAJOR && vminor == PR_VMINOR && vpatch > PR_VPATCH) {
108 return PR_FALSE;
109 }
110 return PR_TRUE;
111} /* PR_VersionCheck */
112
113
114PR_IMPLEMENT(PRBool) PR_Initialized(void)
115{
116 return _pr_initialized;
117}
118
119PRInt32 _native_threads_only = 0;
120
121#ifdef WINNT
122static void _pr_SetNativeThreadsOnlyMode(void)
123{
124 HMODULE mainExe;
125 PRBool *globalp;
126 char *envp;
127
128 mainExe = GetModuleHandle(NULL);
129 PR_ASSERT(NULL != mainExe);
130 globalp = (PRBool *) GetProcAddress(mainExe, "nspr_native_threads_only");
131 if (globalp) {
132 _native_threads_only = (*globalp != PR_FALSE);
133 } else if (envp = getenv("NSPR_NATIVE_THREADS_ONLY")) {
134 _native_threads_only = (atoi(envp) == 1);
135 }
136}
137#endif
138
139#if !defined(_PR_INET6) || defined(_PR_INET6_PROBE)
140extern PRStatus _pr_init_ipv6(void);
141#endif
142
143static void _PR_InitStuff(void)
144{
145
146 if (_pr_initialized) return;
147 _pr_initialized = PR_TRUE;
148#ifdef VBOX_USE_IPRT_IN_NSPR
149 RTR3InitDll(RTR3INIT_FLAGS_UNOBTRUSIVE);
150#endif
151#ifdef WINNT
152 _pr_SetNativeThreadsOnlyMode();
153#endif
154
155
156 (void) PR_GetPageSize();
157
158 _pr_clock_lm = PR_NewLogModule("clock");
159 _pr_cmon_lm = PR_NewLogModule("cmon");
160 _pr_io_lm = PR_NewLogModule("io");
161 _pr_mon_lm = PR_NewLogModule("mon");
162 _pr_linker_lm = PR_NewLogModule("linker");
163 _pr_cvar_lm = PR_NewLogModule("cvar");
164 _pr_sched_lm = PR_NewLogModule("sched");
165 _pr_thread_lm = PR_NewLogModule("thread");
166 _pr_gc_lm = PR_NewLogModule("gc");
167 _pr_shm_lm = PR_NewLogModule("shm");
168 _pr_shma_lm = PR_NewLogModule("shma");
169
170 /* NOTE: These init's cannot depend on _PR_MD_CURRENT_THREAD() */
171 _PR_MD_EARLY_INIT();
172
173 _PR_InitLocks();
174 _PR_InitAtomic();
175 _PR_InitSegs();
176 _PR_InitTPD();
177 _PR_InitEnv();
178 _PR_InitLayerCache();
179 _PR_InitClock();
180
181 _pr_sleeplock = PR_NewLock();
182 PR_ASSERT(NULL != _pr_sleeplock);
183
184 _PR_InitThreads(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
185
186 _PR_InitCMon();
187 _PR_InitIO();
188 _PR_InitLog();
189 _PR_InitLinker();
190 _PR_InitCallOnce();
191 _PR_InitDtoa();
192
193 nspr_InitializePRErrorTable();
194
195 _PR_MD_FINAL_INIT();
196}
197
198void _PR_ImplicitInitialization(void)
199{
200 _PR_InitStuff();
201
202 /* Enable interrupts */
203#if !defined(_PR_PTHREADS) && !defined(_PR_GLOBAL_THREADS_ONLY)
204 _PR_MD_START_INTERRUPTS();
205#endif
206
207}
208
209PR_IMPLEMENT(void) PR_DisableClockInterrupts(void)
210{
211#if !defined(_PR_PTHREADS) && !defined(_PR_BTHREADS)
212 if (!_pr_initialized) {
213 _PR_InitStuff();
214 } else {
215 _PR_MD_DISABLE_CLOCK_INTERRUPTS();
216 }
217#endif
218}
219
220PR_IMPLEMENT(void) PR_EnableClockInterrupts(void)
221{
222#if !defined(_PR_PTHREADS) && !defined(_PR_BTHREADS)
223 if (!_pr_initialized) {
224 _PR_InitStuff();
225 }
226 _PR_MD_ENABLE_CLOCK_INTERRUPTS();
227#endif
228}
229
230PR_IMPLEMENT(void) PR_BlockClockInterrupts(void)
231{
232#if !defined(_PR_PTHREADS) && !defined(_PR_BTHREADS)
233 _PR_MD_BLOCK_CLOCK_INTERRUPTS();
234#endif
235}
236
237PR_IMPLEMENT(void) PR_UnblockClockInterrupts(void)
238{
239#if !defined(_PR_PTHREADS) && !defined(_PR_BTHREADS)
240 _PR_MD_UNBLOCK_CLOCK_INTERRUPTS();
241#endif
242}
243
244PR_IMPLEMENT(void) PR_Init(
245 PRThreadType type, PRThreadPriority priority, PRUintn maxPTDs)
246{
247#if defined(XP_MAC)
248#pragma unused (type, priority, maxPTDs)
249#endif
250
251 _PR_ImplicitInitialization();
252}
253
254PR_IMPLEMENT(PRIntn) PR_Initialize(
255 PRPrimordialFn prmain, PRIntn argc, char **argv, PRUintn maxPTDs)
256{
257#if defined(XP_MAC)
258#pragma unused (maxPTDs)
259#endif
260
261 PRIntn rv;
262 _PR_ImplicitInitialization();
263 rv = prmain(argc, argv);
264 PR_Cleanup();
265 return rv;
266} /* PR_Initialize */
267
268PR_IMPLEMENT(PRProcessAttr *)
269PR_NewProcessAttr(void)
270{
271 PRProcessAttr *attr;
272
273 attr = PR_NEWZAP(PRProcessAttr);
274 if (!attr) {
275 PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
276 }
277 return attr;
278}
279
280PR_IMPLEMENT(void)
281PR_ResetProcessAttr(PRProcessAttr *attr)
282{
283 PR_FREEIF(attr->currentDirectory);
284 PR_FREEIF(attr->fdInheritBuffer);
285 memset(attr, 0, sizeof(*attr));
286}
287
288PR_IMPLEMENT(void)
289PR_DestroyProcessAttr(PRProcessAttr *attr)
290{
291 PR_FREEIF(attr->currentDirectory);
292 PR_FREEIF(attr->fdInheritBuffer);
293 PR_DELETE(attr);
294}
295
296PR_IMPLEMENT(void)
297PR_ProcessAttrSetStdioRedirect(
298 PRProcessAttr *attr,
299 PRSpecialFD stdioFd,
300 PRFileDesc *redirectFd)
301{
302 switch (stdioFd) {
303 case PR_StandardInput:
304 attr->stdinFd = redirectFd;
305 break;
306 case PR_StandardOutput:
307 attr->stdoutFd = redirectFd;
308 break;
309 case PR_StandardError:
310 attr->stderrFd = redirectFd;
311 break;
312 default:
313 PR_ASSERT(0);
314 }
315}
316
317/*
318 * OBSOLETE
319 */
320PR_IMPLEMENT(void)
321PR_SetStdioRedirect(
322 PRProcessAttr *attr,
323 PRSpecialFD stdioFd,
324 PRFileDesc *redirectFd)
325{
326#if defined(DEBUG)
327 static PRBool warn = PR_TRUE;
328 if (warn) {
329 warn = _PR_Obsolete("PR_SetStdioRedirect()",
330 "PR_ProcessAttrSetStdioRedirect()");
331 }
332#endif
333 PR_ProcessAttrSetStdioRedirect(attr, stdioFd, redirectFd);
334}
335
336PR_IMPLEMENT(PRStatus)
337PR_ProcessAttrSetCurrentDirectory(
338 PRProcessAttr *attr,
339 const char *dir)
340{
341 PR_FREEIF(attr->currentDirectory);
342 attr->currentDirectory = (char *) PR_MALLOC(strlen(dir) + 1);
343 if (!attr->currentDirectory) {
344 PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
345 return PR_FAILURE;
346 }
347 strcpy(attr->currentDirectory, dir);
348 return PR_SUCCESS;
349}
350
351PR_IMPLEMENT(PRStatus)
352PR_ProcessAttrSetInheritableFD(
353 PRProcessAttr *attr,
354 PRFileDesc *fd,
355 const char *name)
356{
357 /* We malloc the fd inherit buffer in multiples of this number. */
358#define FD_INHERIT_BUFFER_INCR 128
359 /* The length of "NSPR_INHERIT_FDS=" */
360#define NSPR_INHERIT_FDS_STRLEN 17
361 /* The length of osfd (PRInt32) printed in hexadecimal with 0x prefix */
362#define OSFD_STRLEN 10
363 /* The length of fd type (PRDescType) printed in decimal */
364#define FD_TYPE_STRLEN 1
365 PRSize newSize;
366 int remainder;
367 char *newBuffer;
368 int nwritten;
369 char *cur;
370 int freeSize;
371
372 if (fd->identity != PR_NSPR_IO_LAYER) {
373 PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
374 return PR_FAILURE;
375 }
376 if (fd->secret->inheritable == _PR_TRI_UNKNOWN) {
377 _PR_MD_QUERY_FD_INHERITABLE(fd);
378 }
379 if (fd->secret->inheritable != _PR_TRI_TRUE) {
380 PR_SetError(PR_NO_ACCESS_RIGHTS_ERROR, 0);
381 return PR_FAILURE;
382 }
383
384 /*
385 * We also need to account for the : separators and the
386 * terminating null byte.
387 */
388 if (NULL == attr->fdInheritBuffer) {
389 /* The first time, we print "NSPR_INHERIT_FDS=<name>:<type>:<val>" */
390 newSize = NSPR_INHERIT_FDS_STRLEN + strlen(name)
391 + FD_TYPE_STRLEN + OSFD_STRLEN + 2 + 1;
392 } else {
393 /* At other times, we print ":<name>:<type>:<val>" */
394 newSize = attr->fdInheritBufferUsed + strlen(name)
395 + FD_TYPE_STRLEN + OSFD_STRLEN + 3 + 1;
396 }
397 if (newSize > attr->fdInheritBufferSize) {
398 /* Make newSize a multiple of FD_INHERIT_BUFFER_INCR */
399 remainder = newSize % FD_INHERIT_BUFFER_INCR;
400 if (remainder != 0) {
401 newSize += (FD_INHERIT_BUFFER_INCR - remainder);
402 }
403 if (NULL == attr->fdInheritBuffer) {
404 newBuffer = (char *) PR_MALLOC(newSize);
405 } else {
406 newBuffer = (char *) PR_REALLOC(attr->fdInheritBuffer, newSize);
407 }
408 if (NULL == newBuffer) {
409 PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
410 return PR_FAILURE;
411 }
412 attr->fdInheritBuffer = newBuffer;
413 attr->fdInheritBufferSize = newSize;
414 }
415 cur = attr->fdInheritBuffer + attr->fdInheritBufferUsed;
416 freeSize = attr->fdInheritBufferSize - attr->fdInheritBufferUsed;
417 if (0 == attr->fdInheritBufferUsed) {
418 nwritten = PR_snprintf(cur, freeSize,
419 "NSPR_INHERIT_FDS=%s:%d:0x%lx",
420 name, (PRIntn)fd->methods->file_type, fd->secret->md.osfd);
421 } else {
422 nwritten = PR_snprintf(cur, freeSize, ":%s:%d:0x%lx",
423 name, (PRIntn)fd->methods->file_type, fd->secret->md.osfd);
424 }
425 attr->fdInheritBufferUsed += nwritten;
426 return PR_SUCCESS;
427}
428
429PR_IMPLEMENT(PRFileDesc *) PR_GetInheritedFD(
430 const char *name)
431{
432 PRFileDesc *fd;
433 const char *envVar;
434 const char *ptr;
435 int len = strlen(name);
436 PRInt32 osfd;
437 int nColons;
438 PRIntn fileType;
439
440 envVar = PR_GetEnv("NSPR_INHERIT_FDS");
441 if (NULL == envVar || '\0' == envVar[0]) {
442 PR_SetError(PR_UNKNOWN_ERROR, 0);
443 return NULL;
444 }
445
446 ptr = envVar;
447 while (1) {
448 if ((strncmp(ptr, name, len) == 0) && (ptr[len] == ':')) {
449 ptr += len + 1;
450 PR_sscanf(ptr, "%d:0x%lx", &fileType, &osfd);
451 switch ((PRDescType)fileType) {
452 case PR_DESC_FILE:
453 fd = PR_ImportFile(osfd);
454 break;
455 case PR_DESC_PIPE:
456 fd = PR_ImportPipe(osfd);
457 break;
458 case PR_DESC_SOCKET_TCP:
459 fd = PR_ImportTCPSocket(osfd);
460 break;
461 case PR_DESC_SOCKET_UDP:
462 fd = PR_ImportUDPSocket(osfd);
463 break;
464 default:
465 PR_ASSERT(0);
466 PR_SetError(PR_UNKNOWN_ERROR, 0);
467 fd = NULL;
468 break;
469 }
470 if (fd) {
471 /*
472 * An inherited FD is inheritable by default.
473 * The child process needs to call PR_SetFDInheritable
474 * to make it non-inheritable if so desired.
475 */
476 fd->secret->inheritable = _PR_TRI_TRUE;
477 }
478 return fd;
479 }
480 /* Skip three colons */
481 nColons = 0;
482 while (*ptr) {
483 if (*ptr == ':') {
484 if (++nColons == 3) {
485 break;
486 }
487 }
488 ptr++;
489 }
490 if (*ptr == '\0') {
491 PR_SetError(PR_UNKNOWN_ERROR, 0);
492 return NULL;
493 }
494 ptr++;
495 }
496}
497
498PR_IMPLEMENT(PRProcess*) PR_CreateProcess(
499 const char *path,
500 char *const *argv,
501 char *const *envp,
502 const PRProcessAttr *attr)
503{
504 return _PR_MD_CREATE_PROCESS(path, argv, envp, attr);
505} /* PR_CreateProcess */
506
507PR_IMPLEMENT(PRStatus) PR_CreateProcessDetached(
508 const char *path,
509 char *const *argv,
510 char *const *envp,
511 const PRProcessAttr *attr)
512{
513#ifndef _PR_MD_CREATE_PROCESS_DETACHED
514 PRProcess *process;
515 PRStatus rv;
516s
517#ifdef XP_OS2
518 process = _PR_CreateOS2ProcessEx(path, argv, envp, attr, PR_TRUE);
519#else
520 process = PR_CreateProcess(path, argv, envp, attr);
521#endif
522 if (NULL == process) {
523 return PR_FAILURE;
524 }
525 rv = PR_DetachProcess(process);
526 PR_ASSERT(PR_SUCCESS == rv);
527 if (rv == PR_FAILURE) {
528 PR_DELETE(process);
529 return PR_FAILURE;
530 }
531 return PR_SUCCESS;
532#else /* _PR_MD_CREATE_PROCESS_DETACHED */
533 return _PR_MD_CREATE_PROCESS_DETACHED(path, argv, envp, attr);
534#endif /* _PR_MD_CREATE_PROCESS_DETACHED */
535}
536
537PR_IMPLEMENT(PRStatus) PR_DetachProcess(PRProcess *process)
538{
539 return _PR_MD_DETACH_PROCESS(process);
540}
541
542PR_IMPLEMENT(PRStatus) PR_WaitProcess(PRProcess *process, PRInt32 *exitCode)
543{
544 return _PR_MD_WAIT_PROCESS(process, exitCode);
545} /* PR_WaitProcess */
546
547PR_IMPLEMENT(PRStatus) PR_KillProcess(PRProcess *process)
548{
549 return _PR_MD_KILL_PROCESS(process);
550}
551
552/*
553 ********************************************************************
554 *
555 * Module initialization
556 *
557 ********************************************************************
558 */
559
560static struct {
561 PRLock *ml;
562 PRCondVar *cv;
563} mod_init;
564
565static void _PR_InitCallOnce(void) {
566 mod_init.ml = PR_NewLock();
567 PR_ASSERT(NULL != mod_init.ml);
568 mod_init.cv = PR_NewCondVar(mod_init.ml);
569 PR_ASSERT(NULL != mod_init.cv);
570}
571
572void _PR_CleanupCallOnce()
573{
574 PR_DestroyLock(mod_init.ml);
575 mod_init.ml = NULL;
576 PR_DestroyCondVar(mod_init.cv);
577 mod_init.cv = NULL;
578}
579
580PR_IMPLEMENT(PRStatus) PR_CallOnce(
581 PRCallOnceType *once,
582 PRCallOnceFN func)
583{
584 if (!_pr_initialized) _PR_ImplicitInitialization();
585
586 if (!once->initialized) {
587 if (PR_AtomicSet(&once->inProgress, 1) == 0) {
588 once->status = (*func)();
589 PR_Lock(mod_init.ml);
590 once->initialized = 1;
591 PR_NotifyAllCondVar(mod_init.cv);
592 PR_Unlock(mod_init.ml);
593 } else {
594 PR_Lock(mod_init.ml);
595 while (!once->initialized) {
596 PR_WaitCondVar(mod_init.cv, PR_INTERVAL_NO_TIMEOUT);
597 }
598 PR_Unlock(mod_init.ml);
599 }
600 }
601 return once->status;
602}
603
604PR_IMPLEMENT(PRStatus) PR_CallOnceWithArg(
605 PRCallOnceType *once,
606 PRCallOnceWithArgFN func,
607 void *arg)
608{
609 if (!_pr_initialized) _PR_ImplicitInitialization();
610
611 if (!once->initialized) {
612 if (PR_AtomicSet(&once->inProgress, 1) == 0) {
613 once->status = (*func)(arg);
614 PR_Lock(mod_init.ml);
615 once->initialized = 1;
616 PR_NotifyAllCondVar(mod_init.cv);
617 PR_Unlock(mod_init.ml);
618 } else {
619 PR_Lock(mod_init.ml);
620 while (!once->initialized) {
621 PR_WaitCondVar(mod_init.cv, PR_INTERVAL_NO_TIMEOUT);
622 }
623 PR_Unlock(mod_init.ml);
624 }
625 }
626 return once->status;
627}
628
629PRBool _PR_Obsolete(const char *obsolete, const char *preferred)
630{
631#if defined(DEBUG)
632#ifndef XP_MAC
633 PR_fprintf(
634 PR_STDERR, "'%s' is obsolete. Use '%s' instead.\n",
635 obsolete, (NULL == preferred) ? "something else" : preferred);
636#else
637#pragma unused (obsolete, preferred)
638#endif
639#endif
640 return PR_FALSE;
641} /* _PR_Obsolete */
642
643/* prinit.c */
644
645
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette